【Django】Django ORM - Define Model

Posted by 西维蜀黍 on 2019-11-10, Last Modified on 2021-09-21

Define Models

Quick example

Although you can use Django without a database, it comes with an object-relational mapper in which you describe your database layout in Python code.

The data-model syntax offers many rich ways of representing your models – so far, it’s been solving many years’ worth of database-schema problems.

Here’s a quick example:

#[app name]/models.py
from django.db import models

class Reporter(models.Model):
    full_name = models.CharField(max_length=70)

    def __str__(self):
        return self.full_name

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

    def __str__(self):
        return self.headline

first_name and last_name are fields of the model. Each field is specified as a class attribute, and each attribute maps to a database column.

The above Person model would create a database table like this:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

Some technical notes:

  • The name of the table, myapp_person, is automatically derived from some model metadata but can be overridden. See Table names for more details.
  • An id field is added automatically, but this behavior can be overridden. See Automatic primary key fields.
  • The CREATE TABLE SQL in this example is formatted using PostgreSQL syntax, but it’s worth noting Django uses SQL tailored to the database backend specified in your settings file.

Overriding Defaults

Django requires that all models have a primary key to support update operations (more on this later). To use a name other than id, define it explicitly in the model:

class Employee(models.Model):  
	employee_id = models.AutoField(primary_key=True)

This results in the following table structure:

CREATE TABLE organization_employee ( 
  employee_id BIGINT AUTO_INCREMENT PRIMARY KEY NOT NULL
)

You can override Django’s naming scheme for the table by specifying it in an inner Meta class:

class Employee(models.Model):  
  # ... (field definitions)   
  class Meta(object):    
    db_table = "employee_tab"

类型

models.CharField
models.DateTimeField
models.TextField()
models.ForeignKey(Reporter, on_delete=models.CASCADE)

Fields are defined as class attributes. The following table illustrates some common types of fields, and the MySQL data type they will map to.

Django Field MySQL Type Python Type Notes
CharField VARCHAR unicode max_length must be set. Django assumes the empty value is a blank string (""), not None.
IntegerField INT int
SmallIntegerField SMALLINT int
BigIntegerField BIGINT int
DateField DATE datetime.date auto_now_add and auto_now can help to automatically initialize the column upon creation and update respectively.Django will attempt to return a timezone-naive date regardless of whether Django was configured to use timezones..
DateTimeField DATETIME datetime.datetime Django will attempt to return a timezone-aware datetime if Django is configured to use timezones. Warnings will also be raised if timezone-naive datetimes are used with this field.Otherwise, same as DateField.
AutoField INT AUTO_INCREMENT int primary_key must be True.
TextField TEXT unicode Django assumes the empty value is a blank string (""), not None.
PositiveIntegerField INT int This field only forces the minimum value to be 0, it does not declare an unsigned column. (Django 1.6)
BooleanField BOOL or TINYINT(1) bool There is no default support in Django for BIT(1).
FloatField FLOAT float
DecimalField DECIMAL decimal.Decimal max_digits must be at least the value of decimal_places.

属性

Apart from certain unique arguments, fields also have a common set of optional keyword arguments that can be set. The table below describes these arguments:

Keyword argument Purpose Notes
blank Whether the value of the column can be blank, i.e. “”. Although a common keyword argument, it loses any usefulness for non-string fields.
db_column The actual name of the column in the database table in SQL. Defaults to the field name.
db_index If set to true, the column will be indexed. Only takes effect upon table creation, and has no impact on queries during run-time.
default The default value of the column. Can be set to a function, but not a lambda. Functions allow the default to be set to a mutable-typed object, like a dict.
help_text Help text to be used with any form widgets linked to the model. Even though the model might not be used in forms directly, this can be useful as a standardized form of documentation.
null Whether the value of the column can be NULL.
primary_key If set to true, the column will be the primary key of the table. Only one column in the model can be the primary key.
unique If set to true, the column must be unique in the table. Not valid on ManyToManyField, OneToOneField, and FileField. Also implies db_index due to the nature of databases.
verbose_name A human-readable name for the column. Automatically uses a formatted version of the model class name, e.g. TitleCase becomes title_case.

Fields that should be indexed need to be provided with the db_index keyword argument set to True, or unique for unique columns. This only takes effect upon table creation, and has no impact on queries during run-time.

For more details, see https://docs.djangoproject.com/en/2.2/ref/models/fields/.

choice

from django.db import models

class Student(models.Model):
    FRESHMAN = 'FR'
    SOPHOMORE = 'SO'
    JUNIOR = 'JR'
    SENIOR = 'SR'
    YEAR_IN_SCHOOL_CHOICES = [
        (FRESHMAN, 'Freshman'),
        (SOPHOMORE, 'Sophomore'),
        (JUNIOR, 'Junior'),
        (SENIOR, 'Senior'),
    ]
    year_in_school = models.CharField(
        max_length=2,
        choices=YEAR_IN_SCHOOL_CHOICES,
        default=FRESHMAN,
    )

null和blank

db_column

default

The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.

The default can’t be a mutable object (model instance, list, set, etc.), as a reference to the same instance of that object would be used as the default value in all new model instances. Instead, wrap the desired default in a callable.

primary_key

If True, this field is the primary key for the model.

If you don’t specify primary_key=True for any field in your model, Django will automatically add an AutoField to hold the primary key, so you don’t need to set primary_key=True on any of your fields unless you want to override the default primary-key behavior. For more, see Automatic primary key fields.

primary_key=True implies null=False and unique=True. Only one primary key is allowed on an object.

The primary key field is read-only. If you change the value of the primary key on an existing object and then save it, a new object will be created alongside the old one.

unique

If True, this field must be unique throughout the table.

This is enforced at the database level and by model validation. If you try to save a model with a duplicate value in a unique field, a django.db.IntegrityError will be raised by the model’s save() method.

This option is valid on all field types except ManyToManyField and OneToOneField.

Note that when unique is True, you don’t need to specify db_index, because unique implies the creation of an index.

Field

DateField

  • class DateField(auto_now=False, auto_now_add=False, **options)

A date, represented in Python by a datetime.date instance. Has a few extra, optional arguments:

  • DateField.auto_now

    Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps. Note that the current date is always used; it’s not just a default value that you can override.The field is only automatically updated when calling Model.save(). The field isn’t updated when making updates to other fields in other ways such as QuerySet.update(), though you can specify a custom value for the field in an update like that.

  • DateField.auto_now_add

    Automatically set the field to now when the object is first created. Useful for creation of timestamps. Note that the current date is always used; it’s not just a default value that you can override. So even if you set a value for this field when creating the object, it will be ignored. If you want to be able to modify this field, set the following instead of auto_now_add=True:For DateField: default=date.today - from datetime.date.today()For DateTimeField: default=timezone.now - from django.utils.timezone.now()

The default form widget for this field is a TextInput. The admin adds a JavaScript calendar, and a shortcut for “Today”. Includes an additional invalid_date error message key.

The options auto_now_add, auto_now, and default are mutually exclusive. Any combination of these options will result in an error.

Defining Meta Data

As described in Overriding Defaults, you can override the table name by defining an optional Meta inner class. The following example lists the directives that can be defined within the inner class:

class Person(models.Model):  
  # ... (field definitions) 
  age = models.PositiveSmallIntegerField()  
  height = models.PositiveIntegerField()  
  weight = models.PositiveIntegerField()   
  
  class Meta(object):    
    db_table = "person_tab" 
    # Table name. Will be app name + "_" + lowercase class name by default.    
    ordering = ["-height", "weight"] # Queries will order by height descending and weight ascending by default.    
    verbose_name = "person" # The human-readable name. Will be the TitleCase class name split into lowercase words by default.    
    verbose_name_plural = "people" # The plural human-readable name. Will be verbose_name + "s" by default.    
    index_together = [("height", "weight"), ("age", "height", "weight")] # A list of composite indices.

Defining Foreign Key Relationships

Django supports multiple types of foreign key relationships through special Fields. The table below describes the different types of fields, and the type of foreign key relationship they represent:

Field Type Notes
ForeignKeyField One-to-many Defined in the “one” side of the relationship.
OneToOneField One-to-one Can be defined in either side of the relationship.
ManyToManyField Many-to-many Can be defined in either side of the relationship.

Foreign key fields must be given the name of the target model as the first positional argument. It is also recommended that the related_name and related_query_name keyword arguments be provided as well.

This lesson will not cover foreign key relationships in detail. If you wish to know more, you can refer to the official Django documentation.

Install it

Next, run the Django command-line utilities to create the database tables automatically:

$ python manage.py makemigrations
$ python manage.py migrate

The makemigrations command looks at all your available models and creates migrations for whichever tables don’t already exist. migrate runs the migrations and creates tables in your database, as well as optionally providing much richer schema control.

Reference