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 asQuerySet.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
:ForDateField
:default=date.today
- fromdatetime.date.today()
ForDateTimeField
:default=timezone.now
- fromdjango.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
- https://juejin.im/post/5b588b656fb9a04fba6e8681
- https://docs.djangoproject.com/en/2.2/topics/db/models/
- https://docs.djangoproject.com/en/2.2/ref/models/querysets/
- https://confluence.shopee.io/pages/viewpage.action?pageId=28539581
- https://code.ziqiangxuetang.com/django/django-queryset-api.html
- https://stackoverflow.com/questions/7503241/django-models-selecting-single-field