Django模块笔记【一】

入门笔记翻译整理自:https://docs.djangoproject.com/en/1.8/topics/

*该笔记将对各个模块进行单独介绍

*Model&Database

1. 模型(models)

模型是数据的唯一信息源,它指示了数据的域(fields)和行为(behaviors)。每个模型都对应一个数据库表。

①每个模型都是django.db.models.Model的子类;②模型的每个属性代表了数据库的域;③数据库入口API,参考making queries部分。

比如,

1 from django.db import models
2 
3 class Person(models.Model):
4     first_name = models.CharField(max_length=30)
5     last_name = models.CharField(max_length=30)

对应的数据库表:

1 CREATE TABLE myapp_person (
2     "id" serial NOT NULL PRIMARY KEY,
3     "first_name" varchar(30) NOT NULL,
4     "last_name" varchar(30) NOT NULL
5 );

使用模型:

INSTALLED_APPS = (
    #...
    'myapp',
    #...
)

2. 域(Fields)

Django使用Field类来决定:①数据库的列类型(如INTEGER, VARCHAR);②HTML widget(如<input type="text">,<select>)

各种Field的属性不尽相同,但是它们也有一些共同的可选属性。null=True,将空值存储为NULL,默认为False;blank=True,允许空值,默认为False;choices,举例如下:

 1 from django.db import models
 2 
 3 class Person(models.Model):
 4     SHIRT_SIZES = (
 5         ('S', 'Small'),
 6         ('M', 'Medium'),
 7         ('L', 'Large'),
 8     )
 9     name = models.CharField(max_length=60)
10     shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
1 >>> p = Person(name="Fred Flintstone", shirt_size="L")
2 >>> p.save()
3 >>> p.shirt_size
4 'L'
5 >>> p.get_shirt_size_display()
6 'Large'

default,定义field的默认值;help_text,在表单widget中显示帮助文档;primary_key=True,相应Field为主键,否则会自动生成主键,主键不可更改,比如:

1 from django.db import models
2 
3 class Fruit(models.Model):
4     name = models.CharField(max_length=100, primary_key=True)
1 >>> fruit = Fruit.objects.create(name='Apple')
2 >>> fruit.name = 'Pear'
3 >>> fruit.save()
4 >>> Fruit.objects.values_list('name', flat=True)
5 ['Apple', 'Pear']

unique=True,相应Field的值必须为独一无二的。

大多数域可以直接设置域别名(Verbose field names):

1 # verbose name is "person's first name"
2 first_name = models.CharField("person's first name", max_length=30)
3 # verbose name is "first name"
4 first_name = models.CharField(max_length=30)

ForeighKey,ManyToManyField和OneToOneField需要使用verbose_name参数,来设置域别名:

1 poll = models.ForeignKey(Poll, verbose_name="the related poll")
2 sites = models.ManyToManyField(Site, verbose_name="list of sites")
3 place = models.OneToOneField(Place, verbose_name="related place")

数据库中常见的三种关系为:多对一,多对多,一对一。

①多对一

1 from django.db import models
2 
3 class Manufacturer(models.Model):
4     # ...
5     pass
6 
7 class Car(models.Model):
8     manufacturer = models.ForeignKey(Manufacturer)
9     # ...

②多对多

1 from django.db import models
2 
3 class Topping(models.Model):
4     # ...
5     pass
6 
7 class Pizza(models.Model):
8     # ...
9     toppings = models.ManyToManyField(Topping)

或者

 1 from django.db import models
 2 
 3 class Person(models.Model):
 4     name = models.CharField(max_length=128)
 5 
 6     def __str__(self):              # __unicode__ on Python 2
 7         return self.name
 8 
 9 class Group(models.Model):
10     name = models.CharField(max_length=128)
11     members = models.ManyToManyField(Person, through='Membership')
12 
13     def __str__(self):              # __unicode__ on Python 2
14         return self.name
15 
16 class Membership(models.Model):
17     person = models.ForeignKey(Person)
18     group = models.ForeignKey(Group)
19     date_joined = models.DateField()
20     invite_reason = models.CharField(max_length=64)

③一对一

 1 from django.db import models
 2 
 3 class Place(models.Model):
 4     name = models.CharField(max_length=50)
 5     address = models.CharField(max_length=80)
 6 
 7     def __str__(self):              # __unicode__ on Python 2
 8         return "%s the place" % self.name
 9 
10 class Restaurant(models.Model):
11     place = models.OneToOneField(Place, primary_key=True)
12     serves_hot_dogs = models.BooleanField(default=False)
13     serves_pizza = models.BooleanField(default=False)
14 
15     def __str__(self):              # __unicode__ on Python 2
16         return "%s the restaurant" % self.place.name

3. 文档间模型(Models across files)

需要先导入相应模块:

1 from django.db import models
2 from geography.models import ZipCode
3 
4 class Restaurant(models.Model):
5     # ...
6     zip_code = models.ForeignKey(ZipCode)

4. 元选项(Meta options)

meta用于接收一切不是Field的数据。

1 from django.db import models
2 
3 class Ox(models.Model):
4     horn_length = models.IntegerField()
5 
6     class Meta:
7         ordering = ["horn_length"]
8         verbose_name_plural = "oxen"

5. 重写方法(Override predefined model methods)

 1 from django.db import models
 2 
 3 class Blog(models.Model):
 4     name = models.CharField(max_length=100)
 5     tagline = models.TextField()
 6 
 7     def save(self, *args, **kwargs):
 8         do_something()
 9         super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
10         do_something_else()

重写为

 1 from django.db import models
 2 
 3 class Blog(models.Model):
 4     name = models.CharField(max_length=100)
 5     tagline = models.TextField()
 6 
 7     def save(self, *args, **kwargs):
 8         if self.name == "Yoko Ono's blog":
 9             return # Yoko shall never have her own blog!
10         else:
11             super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.

6. 模型继承(Model inheritance)

①抽象基类(Abstract base classes)

 1 from django.db import models
 2 
 3 class CommonInfo(models.Model):
 4     name = models.CharField(max_length=100)
 5     age = models.PositiveIntegerField()
 6 
 7     class Meta:
 8         abstract = True
 9 
10 class Student(CommonInfo):
11     home_group = models.CharField(max_length=5)

 元继承

 1 from django.db import models
 2 
 3 class CommonInfo(models.Model):
 4     # ...
 5     class Meta:
 6         abstract = True
 7         ordering = ['name']
 8 
 9 class Student(CommonInfo):
10     # ...
11     class Meta(CommonInfo.Meta):
12         db_table = 'student_info'

②多表继承

父类和子类使用不同的数据库表。

1 from django.db import models
2 
3 class Place(models.Model):
4     name = models.CharField(max_length=50)
5     address = models.CharField(max_length=80)
6 
7 class Restaurant(Place):
8     serves_hot_dogs = models.BooleanField(default=False)
9     serves_pizza = models.BooleanField(default=False)
1 >>> p = Place.objects.get(id=12)
2 # If p is a Restaurant object, this will give the child class:
3 >>> p.restaurant
4 <Restaurant: ...>

元继承

1 class ChildModel(ParentModel):
2     # ...
3     class Meta:
4         # Remove parent's ordering effect
5         ordering = []

③代理模型(Proxy model)

父类和子类使用相同的数据库表。

 1 from django.db import models
 2 
 3 class Person(models.Model):
 4     first_name = models.CharField(max_length=30)
 5     last_name = models.CharField(max_length=30)
 6 
 7 class MyPerson(Person):
 8     class Meta:
 9         proxy = True
10 
11     def do_something(self):
12         # ...
13         pass
1 >>> p = Person.objects.create(first_name="foobar")
2 >>> MyPerson.objects.get(first_name="foobar")
3 <MyPerson: foobar>
1 class OrderedPerson(Person):
2     class Meta:
3         ordering = ["last_name"]
4         proxy = True

7. 多重继承

1 class Article(models.Model):
2     headline = models.CharField(max_length=50)
3     body = models.TextField()
4 
5 class Book(models.Model):
6     title = models.CharField(max_length=50)
7 
8 class BookReview(Book, Article):
9     pass

————————————————————————————————————————————————————————————————————————————————————————————

8. 创建队列(Making queries)

以下模型创建了一个网页博客应用,将以此为例:

 1 from django.db import models
 2 
 3 class Blog(models.Model):
 4     name = models.CharField(max_length=100)
 5     tagline = models.TextField()
 6 
 7     def __str__(self):              # __unicode__ on Python 2
 8         return self.name
 9 
10 class Author(models.Model):
11     name = models.CharField(max_length=50)
12     email = models.EmailField()
13 
14     def __str__(self):              # __unicode__ on Python 2
15         return self.name
16 
17 class Entry(models.Model):
18     blog = models.ForeignKey(Blog)
19     headline = models.CharField(max_length=255)
20     body_text = models.TextField()
21     pub_date = models.DateField()
22     mod_date = models.DateField()
23     authors = models.ManyToManyField(Author)
24     n_comments = models.IntegerField()
25     n_pingbacks = models.IntegerField()
26     rating = models.IntegerField()
27 
28     def __str__(self):              # __unicode__ on Python 2
29         return self.headline

创建和更改对象

1 >>> from blog.models import Blog
2 >>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
3 >>> b.save()
4 >>> b5.name = 'New name'
5 >>> b5.save()

储存外键和多对多域

1 >>> from blog.models import Entry
2 >>> entry = Entry.objects.get(pk=1)
3 >>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
4 >>> entry.blog = cheese_blog
5 >>> entry.save()
1 >>> john = Author.objects.create(name="John")
2 >>> paul = Author.objects.create(name="Paul")
3 >>> george = Author.objects.create(name="George")
4 >>> ringo = Author.objects.create(name="Ringo")
5 >>> entry.authors.add(john, paul, george, ringo)

检索对象(Retrieve objects)

1 >>> Blog.objects
2 <django.db.models.manager.Manager object at ...>
3 >>> b = Blog(name='Foo', tagline='Bar')
4 >>> b.objects
5 Traceback:
6     ...
7 AttributeError: "Manager isn't accessible via Blog instances."
1 >>> all_entries = Entry.objects.all()
1 Entry.objects.filter(pub_date__year=2006)
1 >>> Entry.objects.filter(
2 ...     headline__startswith='What'
3 ... ).exclude(
4 ...     pub_date__gte=datetime.date.today()
5 ... ).filter(
6 ...     pub_date__gte=datetime(2005, 1, 30)
7 ... )
1 one_entry = Entry.objects.get(pk=1)
1 >>> Entry.objects.all()[:5]
2 >>> Entry.objects.all()[:10:2]
1 Entry.objects.order_by('headline')[0]

查询域(Field lookup)

类似于检索对象,主要以双下划线的形式实现。

1 >>> Entry.objects.filter(pub_date__lte='2006-01-01')
2 >>> Entry.objects.get(headline__exact="Man bites dog")
3 >>> Blog.objects.get(name__iexact="beatles blog")
4 >>> Entry.objects.get(headline__contains='Lennon')

此外,还有icontains, startswith, endswith, istartswith, iendswith等。

可以多次使用双下划线,来扩展关系,比如:

1 Blog.objects.filter(entry__headline__contains='Lennon')

可以使用F表达式来进行不同域之间的比较:

1 >>> from django.db.models import F
2 >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))
3 >>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))
4 >>> Entry.objects.filter(authors__name=F('blog__name'))

编码时注意缓冲区(Cache)可以减少内存消耗,此处略过。

可以使用Q表达式进行复杂的查询功能,配合使用&,|,~三个运算符:

1 from django.db.models import Q
2 Q(question__startswith='What')
3 Q(question__startswith='Who') | ~Q(pub_date__year=2005)

比较和删除对象:

1 >>> some_entry == other_entry
2 >>> some_entry.id == other_entry.id
3 >>> e.delete()
4 >>> Entry.objects.filter(pub_date__year=2005).delete()

拷贝模型:

1 blog = Blog(name='My blog', tagline='Blogging is easy')
2 blog.save() # blog.pk == 1
3 
4 blog.pk = None
5 blog.save() # blog.pk == 2

更复杂一点的拷贝模型:

1 class ThemeBlog(Blog):
2     theme = models.CharField(max_length=200)
3 
4 django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python')
5 django_blog.save() # django_blog.pk == 3
6 
7 django_blog.pk = None
8 django_blog.id = None
9 django_blog.save() # django_blog.pk == 4

更新对象:

1 Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

关系对象:

1 >>> e = Entry.objects.get(id=2)
2 >>> e.blog # Returns the related Blog object.

———————————————————————————————————————————————————————————————————————————————————————————

9. 整合(Aggregation)

整合和队列功能类似,适合在求平均,总和时使用。

 1 from django.db import models
 2 
 3 class Author(models.Model):
 4     name = models.CharField(max_length=100)
 5     age = models.IntegerField()
 6 
 7 class Publisher(models.Model):
 8     name = models.CharField(max_length=300)
 9     num_awards = models.IntegerField()
10 
11 class Book(models.Model):
12     name = models.CharField(max_length=300)
13     pages = models.IntegerField()
14     price = models.DecimalField(max_digits=10, decimal_places=2)
15     rating = models.FloatField()
16     authors = models.ManyToManyField(Author)
17     publisher = models.ForeignKey(Publisher)
18     pubdate = models.DateField()
19 
20 class Store(models.Model):
21     name = models.CharField(max_length=300)
22     books = models.ManyToManyField(Book)
23     registered_users = models.PositiveIntegerField()

以上面这个模型为例:

 1 # Total number of books.
 2 >>> Book.objects.count()
 3 # Total number of books with publisher=BaloneyPress
 4 >>> Book.objects.filter(publisher__name='BaloneyPress').count()
 5 
 6 # Average price across all books.
 7 >>> from django.db.models import Avg
 8 >>> Book.objects.all().aggregate(Avg('price'))
 9 {'price__avg': 34.35}
10 
11 # Max price across all books.
12 >>> from django.db.models import Max
13 >>> Book.objects.all().aggregate(Max('price'))
14 {'price__max': Decimal('81.20')}
15 
16 # Cost per page
17 >>> Book.objects.all().aggregate(
18 ...    price_per_page=Sum(F('price')/F('pages'), output_field=FloatField()))
19 {'price_per_page': 0.4470664529184653}
20 
21 # All the following queries involve traversing the Book<->Publisher
22 # many-to-many relationship backward
23 
24 # Each publisher, each with a count of books as a "num_books" attribute.
25 >>> from django.db.models import Count
26 >>> pubs = Publisher.objects.annotate(num_books=Count('book'))
27 >>> pubs
28 [<Publisher BaloneyPress>, <Publisher SalamiPress>, ...]
29 >>> pubs[0].num_books
30 
31 # The top 5 publishers, in order by number of books.
32 >>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
33 >>> pubs[0].num_books

———————————————————————————————————————————————————————————————————————————————————————————

10. 管理器(Managers)

每个Django应用中都有管理器,创建队列一节中已经解释了管理器的工作原理,这节介绍自定义管理器行为。

管理器可以重设名称:

1 # Person.people.all() will provide a list of all Person objects.
2 
3 from django.db import models
4 
5 class Person(models.Model):
6     #...
7     people = models.Manager()

额外添加管理器方法:

 1 from django.db import models
 2 
 3 class PollManager(models.Manager):
 4     def with_counts(self):
 5         from django.db import connection
 6         cursor = connection.cursor()
 7         cursor.execute("""
 8             SELECT p.id, p.question, p.poll_date, COUNT(*)
 9             FROM polls_opinionpoll p, polls_response r
10             WHERE p.id = r.poll_id
11             GROUP BY p.id, p.question, p.poll_date
12             ORDER BY p.poll_date DESC""")
13         result_list = []
14         for row in cursor.fetchall():
15             p = self.model(id=row[0], question=row[1], poll_date=row[2])
16             p.num_responses = row[3]
17             result_list.append(p)
18         return result_list
19 
20 class OpinionPoll(models.Model):
21     question = models.CharField(max_length=200)
22     poll_date = models.DateField()
23     objects = PollManager()
24 
25 class Response(models.Model):
26     poll = models.ForeignKey(OpinionPoll)
27     person_name = models.CharField(max_length=50)
28     response = models.TextField()

 修改初始管理器查询集:

 1 # First, define the Manager subclass.
 2 class DahlBookManager(models.Manager):
 3     def get_queryset(self):
 4         return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl')
 5 
 6 # Then hook it into the Book model explicitly.
 7 class Book(models.Model):
 8     title = models.CharField(max_length=100)
 9     author = models.CharField(max_length=50)
10 
11     objects = models.Manager() # The default manager.
12     dahl_objects = DahlBookManager() # The Dahl-specific manager.

也可以在模型中多次调用管理器,这里略过。

此外,可以自定义查询集方法,并在管理器调用:

 1 class PersonQuerySet(models.QuerySet):
 2     def authors(self):
 3         return self.filter(role='A')
 4 
 5     def editors(self):
 6         return self.filter(role='E')
 7 
 8 class PersonManager(models.Manager):
 9     def get_queryset(self):
10         return PersonQuerySet(self.model, using=self._db)
11 
12     def authors(self):
13         return self.get_queryset().authors()
14 
15     def editors(self):
16         return self.get_queryset().editors()
17 
18 class Person(models.Model):
19     first_name = models.CharField(max_length=50)
20     last_name = models.CharField(max_length=50)
21     role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor'))))
22     people = PersonManager()

如果想同时自定义查询集和管理器,可以使用from_queryset()方法:

 1 class BaseManager(models.Manager):
 2     def manager_only_method(self):
 3         return
 4 
 5 class CustomQuerySet(models.QuerySet):
 6     def manager_and_queryset_method(self):
 7         return
 8 
 9 class MyModel(models.Model):
10     objects = BaseManager.from_queryset(CustomQueryset)()

管理器可以随类继承,多重继承时需小心,此处略过。

可以通过use_for_related_fields方法设置自定义管理器为默认管理器:

1 class MyManager(models.Manager):
2     use_for_related_fields = True
3     # ...

———————————————————————————————————————————————————————————————————————————————————————————

11. 使用原始SQL队列(Performing raw SQL queries)

在Django提供的语句不足以实现复杂的SQL时,可以使用Manager.raw()来编写原始队列。比如对于以下模型:

1 class Person(models.Model):
2     first_name = models.CharField(...)
3     last_name = models.CharField(...)
4     birth_date = models.DateField(...)

可以以如下方式执行:

1 >>> for p in Person.objects.raw('SELECT * FROM myapp_person'):
2 ...     print(p)
3 John Smith
4 Jane Jones

也可以运用Connection实现原始SQL查询:

 1 from django.db import connection
 2 
 3 def my_custom_sql(self):
 4     cursor = connection.cursor()
 5 
 6     cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
 7 
 8     cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
 9     row = cursor.fetchone()
10 
11     return row

关于Connection和Cursor的具体用法,可以参见Python DB-API的内容。

———————————————————————————————————————————————————————————————————————————————————————————

12. 数据库事务(Database transactions)

处理网页事务的方法是将每个请求放入一个事务中,同时在数据库的配置(Configuration)中设置ATOMIC_REQUESTS为True。

当ATOMIC_REQUESTS激活时,可以使用non_atomic_requests来阻止某视图在事务中运行。比如:

1 from django.db import transaction
2 
3 @transaction.non_atomic_requests
4 def my_view(request):
5     do_stuff()
6 
7 @transaction.non_atomic_requests(using='other')
8 def my_other_view(request):
9     do_stuff_on_the_other_database()

可以使用atomic来将代码块设置为事务,如果事务运行成功则操作数据库,否则,会执行回滚。例如:

 1 # as a decorator
 2 
 3 from django.db import transaction
 4 
 5 @transaction.atomic
 6 def viewfunc(request):
 7     # This code executes inside a transaction.
 8     do_stuff()
 9 
10 # as a context manager
11 
12 from django.db import transaction
13 
14 def viewfunc(request):
15     # This code executes in autocommit mode (Django's default).
16     do_stuff()
17 
18     with transaction.atomic():
19         # This code executes inside a transaction.
20         do_more_stuff()

以下代码在部分代码出现错误时,也会执行事务操作:

 1 from django.db import IntegrityError, transaction
 2 
 3 @transaction.atomic
 4 def viewfunc(request):
 5     create_parent()
 6 
 7     try:
 8         with transaction.atomic():
 9             generate_relationships()
10     except IntegrityError:
11         handle_exception()
12 
13     add_children()

事务以任意一种方式结束:commit或者rollback。

事务中savepoint的使用如下:

 1 from django.db import transaction
 2 
 3 # open a transaction
 4 @transaction.atomic
 5 def viewfunc(request):
 6 
 7     a.save()
 8     # transaction now contains a.save()
 9 
10     sid = transaction.savepoint()
11 
12     b.save()
13     # transaction now contains a.save() and b.save()
14 
15     if want_to_keep_b:
16         transaction.savepoint_commit(sid)
17         # open transaction still contains a.save() and b.save()
18     else:
19         transaction.savepoint_rollback(sid)
20         # open transaction now contains only a.save()

———————————————————————————————————————————————————————————————————————————————————————————

13. 多个数据库

在settings.py设置多个数据库:

 1 DATABASES = {
 2     'default': {
 3         'NAME': 'app_data',
 4         'ENGINE': 'django.db.backends.postgresql_psycopg2',
 5         'USER': 'postgres_user',
 6         'PASSWORD': 's3krit'
 7     },
 8     'users': {
 9         'NAME': 'user_data',
10         'ENGINE': 'django.db.backends.mysql',
11         'USER': 'mysql_user',
12         'PASSWORD': 'priv4te'
13     }
14 }

同步数据库:

1 $ ./manage.py migrate
2 $ ./manage.py migrate --database=users

数据库路由,假设有如下多个数据库:

 1 DATABASES = {
 2     'auth_db': {
 3         'NAME': 'auth_db',
 4         'ENGINE': 'django.db.backends.mysql',
 5         'USER': 'mysql_user',
 6         'PASSWORD': 'swordfish',
 7     },
 8     'primary': {
 9         'NAME': 'primary',
10         'ENGINE': 'django.db.backends.mysql',
11         'USER': 'mysql_user',
12         'PASSWORD': 'spam',
13     },
14     'replica1': {
15         'NAME': 'replica1',
16         'ENGINE': 'django.db.backends.mysql',
17         'USER': 'mysql_user',
18         'PASSWORD': 'eggs',
19     },
20     'replica2': {
21         'NAME': 'replica2',
22         'ENGINE': 'django.db.backends.mysql',
23         'USER': 'mysql_user',
24         'PASSWORD': 'bacon',
25     },
26 }

路由的实现如下:

 1 class AuthRouter(object):
 2     """
 3     A router to control all database operations on models in the
 4     auth application.
 5     """
 6     def db_for_read(self, model, **hints):
 7         """
 8         Attempts to read auth models go to auth_db.
 9         """
10         if model._meta.app_label == 'auth':
11             return 'auth_db'
12         return None
13 
14     def db_for_write(self, model, **hints):
15         """
16         Attempts to write auth models go to auth_db.
17         """
18         if model._meta.app_label == 'auth':
19             return 'auth_db'
20         return None
21 
22     def allow_relation(self, obj1, obj2, **hints):
23         """
24         Allow relations if a model in the auth app is involved.
25         """
26         if obj1._meta.app_label == 'auth' or 
27            obj2._meta.app_label == 'auth':
28            return True
29         return None
30 
31     def allow_migrate(self, db, app_label, model=None, **hints):
32         """
33         Make sure the auth app only appears in the 'auth_db'
34         database.
35         """
36         if app_label == 'auth':
37             return db == 'auth_db'
38         return None
 1 import random
 2 
 3 class PrimaryReplicaRouter(object):
 4     def db_for_read(self, model, **hints):
 5         """
 6         Reads go to a randomly-chosen replica.
 7         """
 8         return random.choice(['replica1', 'replica2'])
 9 
10     def db_for_write(self, model, **hints):
11         """
12         Writes always go to primary.
13         """
14         return 'primary'
15 
16     def allow_relation(self, obj1, obj2, **hints):
17         """
18         Relations between objects are allowed if both objects are
19         in the primary/replica pool.
20         """
21         db_list = ('primary', 'replica1', 'replica2')
22         if obj1._state.db in db_list and obj2._state.db in db_list:
23             return True
24         return None
25 
26     def allow_migrate(self, db, app_label, model=None, **hints):
27         """
28         All non-auth models end up in this pool.
29         """
30         return True

最后设置:

1 DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']

此外,可以使用using属性手动操作Database。

———————————————————————————————————————————————————————————————————————————————————————————

14. 表空间(Tablespace)及数据库接入优化(Database access optimization)

使用表空间可以优化数据库运行。略过。

数据库接入优化。略过。

-- The End -- 

原文地址:https://www.cnblogs.com/py-drama/p/4600969.html