跳转至

模型

定义

models.py 中定义模型,模型都是 django.db.models.Model 的子类:

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()
    # 外键,Article 和 Reporter 是多对一关系,且规定删除 Reporter 时 删除对应的 Article
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

    def __str__(self):
        return self.headline

数据字段

常见的字段类型有:

  • BinaryField
  • BooleanField
  • CharField
    • EmailFieldFilePathFieldURLField
  • TextField
  • DateFieldDateTimeFieldDurationFieldTimeField
  • DecimalFieldFloatField
  • FileField
    • ImageField
  • JSONField

还有不少字段类型,设置特殊字段时值得看看,说不定有对应的,甚至还能自定义字段类型。

关系字段

关系字段有:

  1. ForeignField:多对一
  2. ManyToManyField:多对多
  3. OneToOneField:一对一

此处只以 ForeignField 为例简单介绍。

from django.db import models

class Author(models.Model):
    pass

class Book(models.Model):
    # 外键到 Author,删除时 CASCADE
    author = models.ForeignKey(to=Author, on_delete=models.CASCADE)

on_delete 可能的值:

  • CASCADEto 被删除时,该对象也被删除
  • PROTECT:防止 to 被删除
  • RESTRICT:有点复杂,见文档
  • SET_NULLto 被删除时,设置外键为空
  • SET_DEFAULTto 被删除时,设置外键为默认值
  • SET()
  • DO_NOTHING

注意 on_delete 不依赖数据库实现而是依赖 Django 实现。

字段选项

一些通用的字段选项,且都是可选的。

选项 默认值 说明
blank False 是否可以为空,这个只是表单端
null False 空值实际存储为 NULL,例如字符串默认空值为空字符串,就不建议设置 nullTrue
choices 提供选项,类似枚举,详见文档
db_column 数据库列名
db_index 为该字段创建索引
db_tablespace 字段索引使用的的表空间
default 字段默认值,可以是一个函数
editable True 若为否,则会跳过模型验证,也不会在管理界面或 ModelForm 中出现
error_messages 自定义错误信息
help_text 帮助文本
primary_key 设置为模型主键,且 null=False, unique=True
unique 保证唯一性,且自动创建索引
unique_for_date 另一个字段(DateFieldDateTimeField)的名称,从而保证该字段和另一个字段的日期部分不同,注意时间部分忽略哦
unique_for_month 同上
unique_for_year 同上
verbose_name 人类可读名称,不设置的话 Django 会自动设置
validators 验证器

元数据 Meta

在模型中嵌套一个 Meta 类,用于定义模型的元数据,如排序、数据库表名等,见文档

使用

# 代码高亮不太对,不要在意

# 导入模型
>>> from news.models import Article, Reporter

# 全部 Reporter
>>> Reporter.objects.all()
<QuerySet []>

# 创建 Reporter 并保存
>>> r = Reporter(full_name='John Smith')
>>> r.save()

>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>

>>> r.id
1
>>> r.full_name
'John Smith'

# 根据字段查询
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Reporter matching query does not exist.

# 创建 Article 并保存,注意 reporter 是之前的 r
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
...     content='Yeah.', reporter=r)
>>> a.save()

>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>

# 从 a 得到 reporter r
>>> r = a.reporter
>>> r.full_name
'John Smith'

# 查询 r 的所有 Article 得到 article a
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>

# 查询所有 reporter 的全名以 John 开始的 Article
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>

# 更改 r 的全名
>>> r.full_name = 'Billy Goat'
>>> r.save()

# 删除 r
>>> r.delete()

Migration 相关命令

python manage.py makemigrations
python manage.py sqlmigrate
python manage.py migrate <app_label> <migration_name> [--backwards]