Data model best practices recommended by two scoops Django

Time:2020-4-18

Add or modify the data model can not be sloppy, the operation of the data should be carefully considered.

Recommended Django data model related packages:

  1. django-model-utils: use its timestampedmodel
  2. django-extensions: use its administrative commandsshell_plus, which automatically loads the data model of all installed applications

Basics

Split applications with many data models

No more than 5 data models are recommended for each application. If there are too many data models in an application, it means that the application has done too many things and needs to be split.

Choose data model inheritance method carefully

Django supports three inheritance methods:

  1. Abstract base class
  2. Multi table inheritance
  3. surrogate model

Django abstract base class is different from Python abstract base class! They have different purposes and behaviors.

Advantages and disadvantages of various inheritance methods:

Inheritance mode Advantage shortcoming
Abstract base class: only inherited child data models can create data tables It can define common items in abstract parent class to reduce repeated input and the overhead of additional data table and join operation without multi table inheritance Parent cannot be used alone
Multi table inheritance: both parent and child classes create corresponding data tables. There is an implicitOneToOneFieldRelation Because each data model has a table, the parent and child can be queried separately. At the same time throughparent.childAccess child objects directly from parent A query on a child table will have a join operation with all its parent tables.Multi table inheritance is not recommended!
Proxy model: create data tables only for the original data model You can create an alias for the original data model and add different Python behaviors Cannot modify data model item

How to determine which inheritance method should be used:

  • If the amount of overlap is small (only one or two items), inheritance is not needed, but only needs to be defined in both data models
  • If there are more duplicates between the two, you should refactor the code and place the same item in an abstract base class
  • The proxy model can be useful sometimes, but it’s very different from the other two models
  • Multi table inheritance should be avoided because it increases both complexity and performance overhead. Can useOneToOneFieldandForeignKeysInstead.

Data model inheritance practice: timestampedmodel

Add in data modelcreatedandmodifiedTwo timestamp items are a common requirement. You can write a timestampedmodel base class as follows:

# core/models.py
from django.db import models

class TimeStampedModel(models.Model):
    """
    An abstract base class model that provides self-
    updating ``created`` and ``modified`` fields.
    """
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

Then all data models inherited from the abstract base class will have these two items:

# flavors/models.py
from django.db import models
from core.models import TimeStampedModel

class Flavor(TimeStampedModel):
    title = models.CharField(max_length=200)

Database migration

Django has a powerful built-in database modification conduction library calledmigrationsThat is to saydjango.db.migrations

Suggestions for creating migrations:

  • Once an application or data model is created, the initial django.db.migrations should be created for the new data model. In fact, we only needpython manage.py makemigrationsCommand can be completed
  • Check the generated migration code before running, especially when complex modifications are involved. Simultaneous usesqlmigrateCommand to verify the actual SQL statements used
  • UseMIGRATION_MODULESConfiguration items to manage the migration of third-party applications
  • Don’t worry about the number of migrations generated. We can usesquashmigrationsCommand to merge it

Deployment and management migrations:

  • Before deployment, check whether the migrations can be rolled back.
  • If there are millions of data in the table, the data of this magnitude should be tested on the staging server. Migrations on a real database can take much longer than expected!
  • If MySQL is used:

    • It must be backed up before schema changes are involved. MySQL does not provide transaction support for schema modification, so rollback is not possible
    • If possible, items should be placed in theread-onlyPattern
    • Schema changes to a large number of tables can take a lot of time. Not seconds, not minutes, but hours!

Django data model design

Standardize the database

A data model should not contain data that has been saved in other data models.

Related resources:

  • http://en.wikipedia.org/wiki/Database_normalization
  • http://en.wikibooks.org/wiki/Relational_Database_Design/Normalization

Caching should be done before denormalization

Only when it is absolutely necessary can we carry out inverse normalization

When to use null and blank

Data item type Set null = true Set blank = true
CharField, TextField, SlugField, EmailField, CommaSeparatedIntegerField, UUIDField Do not set this. The tradition of Django is to save the null value as an empty string, and the obtained null or empty value is parsed as an empty string Can be set. If you allow its corresponding form item to accept null values.
FileField, ImageField Do not set this. Django will justMEDIA_ROOTThe path to the file is saved in charfield, so the rule is the same as above You can set the rules like charfield
BooleanField Do not set this. Do not use this field, use nullboolfield Don’t set it like this
Integerfield, floatfield, decimalfield, durationfield, etc If you allow null to be stored in the database, you can set it as follows If you allow its corresponding form component to accept null values, you can set this, and set null = true at the same time
Datefieldfield, DateField, timefield, etc If you allow null to be stored in the database, you can set it as follows If you allow the corresponding form component to accept null values, or use theauto_nowauto_now_addThis can be set. Set null = true at the same time
ForeignKey, ManyToManyField, OneToOneField You can set it like this You can set it like this
GenericIPAddressField You can set it like this You can set it like this
IPAddressField This type is not recommended and is obsolete in Django 1.7 This type is not recommended

When to use binaryfield

This type is added in Django 1.8 to hold raw binary data, orbytes。 Filter, exclude, or other SQL operations cannot be performed on this type of item. But it works when:

  • Message pack content
  • Sensor raw data
  • Compressed data. For example, sentry is saved as BLOB data, but Base64 encoding is required due to historical reasons

Binary data strings can be large, which slows down the database. In this case, you should save the content in a file, and then use filefield to reference it.

Never provide file services through binaryfield

  • Reading and writing to the database is slower than the file system
  • Your database will become larger and smaller, and thus lower and lower performance
  • At this time, the access file needs to go through Django application layer and database layer.

Try to avoid using generic association models.field.genericforeignkey

Using genericforeignkey will make the foreign key not subject to integrity constraints. There are the following problems:

  • Query speed will be reduced due to lack of index between models
  • The data table may refer to a nonexistent record, and the data may be damaged

The advantage is that without integrity constraints, a data item can be associated with different types of records. Most of them are used in voiting, tagging and ratings.

have access toForeignKeyandManyToManyTo achieveGenericForeignKeyIt not only ensures the integrity of the data, but also improves the performance.

Therefore,

  • Try to avoid using common associations andGenericForeignKey
  • If general association is needed, try whether it can be solved by adjusting data model design or using new PostgreSQL items
  • If you have to, it’s best to use an off the shelf third-party application

PostgreSQL specific items: when to use null and blank

Data item type Set null = true Set blank = true
ArrayField Can set Can set
HStoreField Can set Can set
Integerrangefield, bigintegerrangefield and floatrangefield Can be set. If you want to store null in the database Can be set. If you allow its corresponding form component to accept null values. Set null = true at the same time
Datatimerangefield and daterangefield Ditto Ditto

Data model_meta API

_metaOnly used internally before Django 1.8. The interface is now public.

_metaUses:

  • Get the list of items in the data model
  • Gets the class (or inheritance chain or other derived information) of a specific item in the data model
  • You can make sure that the way you get this information will not change in future Django releases

Use example:

  • A introspective tool for creating a Django data model
  • Create a custom form library
  • Create a tool similar to admin to edit or interact with data in the Django data model
  • Create a visualization or analysis library, such as analyzing information about items starting with “foo”

Data model manager

The data model manager is used to restrict all possible data records of a data model class. Django provides a default manager for each data model class.

We can define our own data model manager, such as:

from django.db import models
from django.utils import timezone

class PublishedManager(models.Manager):

    use_for_related_fields = True

    def published(self, **kwargs):
        return self.filter(pub_date__lte=timezone.now(), **kwargs)


class FlavorReview(models.Model):
    review = models.CharField(max_length=255)
    pub_date = models.DateTimeField()

    # add our custom model manager
    objects = PublishedManager()

At this time, if we want to find out the number of all comments first and then the number of comments that have been published, we can do this:

>>> from reviews.models import FlavorReview
>>> FlavorReview.objects.count()
35
>>> FlavorReview.objects.published().count()
31

For the default manager that replaces the data model, take special care:

  • First, when using data model inheritance, the subclass of abstract base class will receive the data model manager of its parent class, but the subclass using multi table inheritance will not
  • Second, the first data model manager that applies to a data model class is treated as the default manager. This is very different from the normal Python mode, which will make the returned query result different from the expected one

Therefore, theobjects = models.Manager()Before all custom data model managers.

Understanding fat data model

fat modelsThe concept is: do not scatter the data related code in views and templates, but encapsulate these logic in methods, class methods, properties and even manager methods of the data model. This way, all views and tasks can reuse the code.

The disadvantage of this method: it will make the data model more and more code, so it is difficult to maintain and understand.

Therefore, when the amount of code in the data model becomes very large and complex, the relevant repeated code should be separated and placed in theModel BehaviororHelper FunctionsMedium.

Behaviors of data model, also known as mixins

Behaviors of data model follow the idea of combination and encapsulation by using mixins.

Related resources: use even to reduce duplicate code

Stateless helper functions

The logic is placed in the set of utility functions to separate them, making testing easier. The disadvantage: because these functions are stateless, all parameters need to be passed.

Reference: two scoops of Django: Best Practices for Django 1.8

Recommended Today

Blog based on beego, go blog

Go Blog A beego based development, can quickly create personal blog, CMS system Include functions see Official website of go bloggo-blog.cn Demo siteleechan.online Update log time function January 23, 2020 New top post function February 2, 2020 New custom navigation function February 4, 2020 New site announcement function February 6, 2020 New link module February […]