模型字段参考 — Django 文档

来自菜鸟教程
Django/docs/3.2.x/ref/models/fields
跳转至:导航、​搜索

模型字段参考

本文档包含 Field 的所有 API 参考,包括 Django 提供的 field optionsfield types

也可以看看

如果内置字段不起作用,您可以尝试 django-localflavordocumentation),其中包含对特定国家和文化有用的各种代码。

此外,您可以轻松地 编写自己的自定义模型字段


笔记

从技术上讲,这些模型在 django.db.models.fields 中定义,但为了方便起见,它们被导入到 django.db.models 中; 标准约定是使用 from django.db import models 并将字段称为 models.<Foo>Field


字段选项

以下参数可用于所有字段类型。 都是可选的。

null

Field.null

如果是 True,Django 将在数据库中将空值存储为 NULL。 默认值为 False

避免在基于字符串的字段上使用 null,例如 CharFieldTextField。 如果基于字符串的字段具有 null=True,则意味着“无数据”有两个可能的值:NULL 和空字符串。 在大多数情况下,“无数据”有两个可能的值是多余的; Django 约定是使用空字符串,而不是 NULL。 一个例外是 CharField 同时设置了 unique=Trueblank=True。 在这种情况下,需要 null=True 以避免在保存具有空白值的多个对象时违反唯一约束。

对于基于字符串和非基于字符串的字段,如果您希望在表单中允许空值,您还需要设置 blank=True,因为 null 参数仅影响数据库存储(见 空白 )。

笔记

当使用 Oracle 数据库后端时,值 NULL 将被存储以表示空字符串,而不管该属性如何。


blank

Field.blank

如果是True,则该字段可以为空。 默认值为 False

请注意,这与 null 不同。 null 纯粹与数据库相关,而 blank 与验证相关。 如果字段具有 blank=True,则表单验证将允许输入空值。 如果字段具有 blank=False,则该字段将是必需的。


choices

Field.choices

一个 序列 由恰好两个项目的迭代组成(例如 [(A, B), (A, B) ...]) 用作此字段的选项。 如果给出了选择,则它们由 模型验证 强制执行,并且默认表单小部件将是带有这些选择的选择框,而不是标准文本字段。

每个元组中的第一个元素是要在模型上设置的实际值,第二个元素是人类可读的名称。 例如:

YEAR_IN_SCHOOL_CHOICES = [
    ('FR', 'Freshman'),
    ('SO', 'Sophomore'),
    ('JR', 'Junior'),
    ('SR', 'Senior'),
    ('GR', 'Graduate'),
]

通常,最好在模型类中定义选择,并为每个值定义一个适当命名的常量:

from django.db import models

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

    def is_upperclass(self):
        return self.year_in_school in {self.JUNIOR, self.SENIOR}

尽管您可以在模型类之外定义一个选择列表然后引用它,但是在模型类中定义每个选择的选择和名称会保留使用它的类的所有信息,并有助于引用这些选择(例如, Student.SOPHOMORE 将在任何已导入 Student 模型的地方工作)。

您还可以将可用选项收集到可用于组织目的的命名组中:

MEDIA_CHOICES = [
    ('Audio', (
            ('vinyl', 'Vinyl'),
            ('cd', 'CD'),
        )
    ),
    ('Video', (
            ('vhs', 'VHS Tape'),
            ('dvd', 'DVD'),
        )
    ),
    ('unknown', 'Unknown'),
]

每个元组中的第一个元素是应用于组的名称。 第二个元素是一个 2 元组的可迭代对象,每个 2 元组包含一个值和一个人类可读的选项名称。 分组选项可以与单个列表中的未分组选项组合(例如本示例中的 'unknown' 选项)。

对于每个设置了 choices 的模型字段,Django 将添加一个方法来检索字段当前值的可读名称。 请参阅数据库 API 文档中的 get_FOO_display()

请注意,选择可以是任何序列对象——不一定是列表或元组。 这使您可以动态构建选择。 但是,如果您发现自己将 choices 修改为动态,则最好使用带有 ForeignKey 的适当数据库表。 choices 用于不会发生太大变化的静态数据,如果有的话。

笔记

每次 choices 的顺序更改时,都会创建一个新的迁移。


除非 blank=Falsedefault 一起在字段上设置,那么包含 "---------" 的标签将与选择框一起呈现。 要覆盖此行为,请向包含 Nonechoices 添加一个元组; 例如 (None, 'Your String For Display')。 或者,您可以使用空字符串而不是 None ,这是有意义的 - 例如在 CharField 上。

枚举类型

此外,Django 提供了枚举类型,您可以将其子类化以简洁的方式定义选项:

from django.utils.translation import gettext_lazy as _

class Student(models.Model):

    class YearInSchool(models.TextChoices):
        FRESHMAN = 'FR', _('Freshman')
        SOPHOMORE = 'SO', _('Sophomore')
        JUNIOR = 'JR', _('Junior')
        SENIOR = 'SR', _('Senior')
        GRADUATE = 'GR', _('Graduate')

    year_in_school = models.CharField(
        max_length=2,
        choices=YearInSchool.choices,
        default=YearInSchool.FRESHMAN,
    )

    def is_upperclass(self):
        return self.year_in_school in {
            self.YearInSchool.JUNIOR,
            self.YearInSchool.SENIOR,
        }

这些工作类似于 Python 标准库中的 enum,但有一些修改:

  • 枚举成员值是构造具体数据类型时要使用的参数元组。 Django 支持在这个元组的末尾添加一个额外的字符串值,用作人类可读的名称,或 labellabel 可以是一个懒惰的可翻译字符串。 因此,在大多数情况下,成员值将是一个 (value, label) 二元组。 请参阅下面的 使用更复杂数据类型的子类化选项 的示例。 如果未提供元组,或者最后一项不是(懒惰)字符串,则 label从成员名称自动生成的
  • .label 属性被添加到值上,以返回人类可读的名称。
  • 许多自定义属性添加到枚举类 - .choices.labels.values.names - 以便更容易访问这些列表枚举的单独部分。 使用 .choices 作为合适的值传递给字段定义中的 choices
  • 强制使用 enum.unique() 以确保值不能被多次定义。 这在一个领域的选择中是不太可能预料到的。

请注意,使用 YearInSchool.SENIORYearInSchool['SENIOR']YearInSchool('SR') 来访问或查找枚举成员按预期工作,.name.value 也是如此成员的属性。

如果您不需要翻译人类可读的名称,您可以从成员名称推断它们(用空格替换下划线并使用标题大小写):

>>> class Vehicle(models.TextChoices):
...     CAR = 'C'
...     TRUCK = 'T'
...     JET_SKI = 'J'
...
>>> Vehicle.JET_SKI.label
'Jet Ski'

由于枚举值需要为整数的情况非常普遍,Django 提供了一个 IntegerChoices 类。 例如:

class Card(models.Model):

    class Suit(models.IntegerChoices):
        DIAMOND = 1
        SPADE = 2
        HEART = 3
        CLUB = 4

    suit = models.IntegerField(choices=Suit.choices)

也可以使用 Enum Functional API,但需要注意标签是自动生成的,如上所示:

>>> MedalType = models.TextChoices('MedalType', 'GOLD SILVER BRONZE')
>>> MedalType.choices
[('GOLD', 'Gold'), ('SILVER', 'Silver'), ('BRONZE', 'Bronze')]
>>> Place = models.IntegerChoices('Place', 'FIRST SECOND THIRD')
>>> Place.choices
[(1, 'First'), (2, 'Second'), (3, 'Third')]

如果您需要支持 intstr 以外的具体数据类型,您可以将 Choices 和所需的具体数据类型子类化,例如 date 用于 DateField

class MoonLandings(datetime.date, models.Choices):
    APOLLO_11 = 1969, 7, 20, 'Apollo 11 (Eagle)'
    APOLLO_12 = 1969, 11, 19, 'Apollo 12 (Intrepid)'
    APOLLO_14 = 1971, 2, 5, 'Apollo 14 (Antares)'
    APOLLO_15 = 1971, 7, 30, 'Apollo 15 (Falcon)'
    APOLLO_16 = 1972, 4, 21, 'Apollo 16 (Orion)'
    APOLLO_17 = 1972, 12, 11, 'Apollo 17 (Challenger)'

还有一些额外的警告需要注意:

  • 枚举类型不支持 [X33X] 命名组 。

  • 由于具有具体数据类型的枚举需要所有值都与该类型匹配,因此无法通过创建值为 None 的成员来覆盖 空白标签 。 相反,在类上设置 __empty__ 属性:

    class Answer(models.IntegerChoices):
        NO = 0, _('No')
        YES = 1, _('Yes')
    
        __empty__ = _('(Unknown)')


db_column

Field.db_column

用于此字段的数据库列的名称。 如果没有给出,Django 将使用该字段的名称。

如果您的数据库列名称是 SQL 保留字,或者包含 Python 变量名称中不允许的字符(尤其是连字符),那也没关系。 Django 在幕后引用列名和表名。


db_index

Field.db_index

如果是 True,将为此字段创建数据库索引。


db_tablespace

Field.db_tablespace

用于该字段索引的 数据库表空间 的名称(如果该字段已编入索引)。 默认是项目的 :setting:`DEFAULT_INDEX_TABLESPACE` 设置(如果已设置)或模型的 db_tablespace(如果有)。 如果后端不支持索引表空间,则忽略此选项。


default

Field.default

字段的默认值。 这可以是值或可调用对象。 如果可调用,则每次创建新对象时都会调用它。

默认值不能是可变对象(模型实例、listset 等),因为对该对象的同一实例的引用将用作所有对象的默认值新模型实例。 相反,将所需的默认值包装在一个可调用对象中。 例如,如果要为 JSONField 指定默认的 dict,请使用函数:

def contact_default():
    return {"email": "to1@example.com"}

contact_info = JSONField("ContactInfo", default=contact_default)

lambdas 不能用于像 default 这样的字段选项,因为它们不能被迁移 序列化 。 有关其他注意事项,请参阅该文档。

对于像 ForeignKey 这样映射到模型实例的字段,默认值应该是它们引用的字段的值(pk,除非设置了 to_field)而不是模型实例。

在创建新模型实例并且未为该字段提供值时使用默认值。 当字段为主键时,字段设置为None时也使用默认值。


editable

Field.editable

如果是 False,该字段将不会显示在 admin 或任何其他 ModelForm 中。 在 模型验证 期间也会跳过它们。 默认值为 True


error_messages

Field.error_messages

error_messages 参数允许您覆盖该字段将引发的默认消息。 传入一个字典,其键与要覆盖的错误消息匹配。

错误信息键包括 nullblankinvalidinvalid_choiceuniqueunique_for_date。 在下面的 字段类型 部分中为每个字段指定了其他错误消息键。

这些错误消息通常不会传播到表单。 请参阅 关于模型的 error_messages 的注意事项。


help_text

Field.help_text

与表单小部件一起显示的额外“帮助”文本。 即使您的字段未在表单上使用,它也可用于文档。

请注意,此值在自动生成的表单中是 而非 HTML 转义。 如果您愿意,这允许您在 help_text 中包含 HTML。 例如:

help_text="Please use the following format: <em>YYYY-MM-DD</em>."

或者,您可以使用纯文本和 django.utils.html.escape() 来转义任何 HTML 特殊字符。 确保您对可能来自不受信任用户的任何帮助文本进行转义以避免跨站点脚本攻击。


primary_key

Field.primary_key

如果是 True,则该字段是模型的主键。

如果您没有为模型中的任何字段指定 primary_key=True,Django 将自动添加一个字段来保存主键,因此您无需在任何字段上设置 primary_key=True除非您想覆盖默认的主键行为。 可以在 AppConfig.default_auto_field 中为每个应用程序指定自动创建的主键字段的类型,也可以在 :setting:`DEFAULT_AUTO_FIELD` 设置中全局指定。 有关更多信息,请参阅 自动主键字段

primary_key=True 意味着 null=Falseunique=True。 一个对象上只允许有一个主键。

主键字段是只读的。 如果您在现有对象上更改主键的值然后保存它,则会在旧对象旁边创建一个新对象。

3.2 版更改: 在旧版本中,自动创建的主键字段始终为 AutoField


unique

Field.unique

如果是 True,则该字段在整个表中必须是唯一的。

这是在数据库级别和模型验证中强制执行的。 如果您尝试在 unique 字段中保存具有重复值的模型,模型的 save() 方法将引发 django.db.IntegrityError .

此选项对除 ManyToManyFieldOneToOneField 之外的所有字段类型都有效。

注意,当 uniqueTrue 时,不需要指定 db_index,因为 unique 意味着创建索引。


unique_for_date

Field.unique_for_date

将此设置为 DateFieldDateTimeField 的名称,以要求此字段对于日期字段的值是唯一的。

例如,如果您有一个字段 title 具有 unique_for_date="pub_date",那么 Django 将不允许输入具有相同 titlepub_date 的两条记录.

请注意,如果您将其设置为指向 DateTimeField,则只会考虑该字段的日期部分。 此外,当 :setting:`USE_TZ`True 时,将在对象保存时的 当前时区 中进行检查。

这是在模型验证期间由 Model.validate_unique() 强制执行的,但不是在数据库级别执行的。 如果任何 unique_for_date 约束涉及不属于 ModelForm 的字段(例如,如果其中一个字段在 exclude 中列出或具有 editable= False), Model.validate_unique() 将跳过对该特定约束的验证。


unique_for_month

Field.unique_for_month

unique_for_date 类似,但要求该字段相对于月份而言是唯一的。


unique_for_year

Field.unique_for_year

unique_for_dateunique_for_month


verbose_name

Field.verbose_name

字段的可读名称。 如果没有给出详细名称,Django 将使用字段的属性名称自动创建它,将下划线转换为空格。 请参阅 详细字段名称


validators

Field.validators

要为此字段运行的验证器列表。 有关更多信息,请参阅 验证器文档

注册和获取查找

Field 实现了 查找注册 API。 API 可用于自定义字段类可用的查找,以及如何从字段中获取查找。


字段类型

AutoField

class AutoField(**options)

IntegerField 根据可用 ID 自动递增。 您通常不需要直接使用它; 如果您没有另外指定,主键字段将自动添加到您的模型中。 请参阅 自动主键字段


BigAutoField

class BigAutoField(**options)

一个 64 位整数,很像 AutoField,除了它保证适合从 19223372036854775807 的数字。


BigIntegerField

class BigIntegerField(**options)

一个 64 位整数,很像 IntegerField,除了它保证适合从 -92233720368547758089223372036854775807 的数字。 此字段的默认表单小部件是 NumberInput


BinaryField

class BinaryField(max_length=None, **options)

存储原始二进制数据的字段。 可以分配 bytesbytearraymemoryview

默认情况下,BinaryFieldeditable 设置为 False,在这种情况下,它不能包含在 ModelForm 中。

BinaryField 有一个额外的可选参数:

BinaryField.max_length
字段的最大长度(以字节为单位)。 最大长度在 Django 的验证中使用 MaxLengthValidator 强制执行。

滥用 BinaryField

尽管您可能会考虑将文件存储在数据库中,但请考虑在 99% of 的情况下这是糟糕的设计。 该字段是 不是 替代正确的 静态文件 处理。


BooleanField

class BooleanField(**options)

真/假字段。

此字段的默认表单小部件是 CheckboxInput,或 NullBooleanSelect 如果 null=True

Field.default 未定义时,BooleanField 的默认值为 None


CharField

class CharField(max_length=None, **options)

一个字符串字段,用于从小到大的字符串。

对于大量文本,请使用 TextField

此字段的默认表单小部件是 TextInput

CharField 有两个额外的参数:

CharField.max_length

必需的。 字段的最大长度(以字符为单位)。 max_length 在数据库级别和 Django 的验证中使用 MaxLengthValidator 强制执行。

笔记

如果您正在编写一个必须可移植到多个数据库后端的应用程序,您应该注意某些后端对 max_length 的限制。 详情请参考数据库后端笔记

CharField.db_collation

3.2 版中的新功能。

可选的。 字段的数据库排序规则名称。

笔记

排序规则名称未标准化。 因此,这将无法跨多个数据库后端移植。

甲骨文

Oracle 仅在 MAX_STRING_SIZE 数据库初始化参数设置为 EXTENDED 时才支持排序规则。


DateField

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

一个日期,在 Python 中由 datetime.date 实例表示。 有一些额外的可选参数:

DateField.auto_now

每次保存对象时自动将字段设置为现在。 对“上次修改”时间戳很有用。 注意当前日期是 always used; 它不仅仅是您可以覆盖的默认值。

该字段仅在调用 Model.save() 时自动更新。 以其他方式(例如 QuerySet.update())更新其他字段时,该字段不会更新,但您可以在这样的更新中为该字段指定自定义值。

DateField.auto_now_add
首次创建对象时自动将字段设置为现在。 用于创建时间戳。 注意当前日期是 always used; 它不仅仅是您可以覆盖的默认值。 所以即使你在创建对象时为这个字段设置了一个值,它也会被忽略。 如果您希望能够修改此字段,请设置以下内容而不是 auto_now_add=True

此字段的默认表单小部件是 DateInput。 管理员添加了一个 JavaScript 日历和一个“今天”的快捷方式。 包括一个额外的 invalid_date 错误消息密钥。

选项 auto_now_addauto_nowdefault 是互斥的。 这些选项的任何组合都会导致错误。

笔记

按照目前的实施,将 auto_nowauto_now_add 设置为 True 将导致字段设置为 editable=Falseblank=True


笔记

auto_nowauto_now_add 选项将始终使用创建或更新时 默认时区 中的日期。 如果您需要不同的东西,您可能需要考虑使用自己的可调用默认值或覆盖 save() 而不是使用 auto_nowauto_now_add; 或者使用 DateTimeField 而不是 DateField 并决定如何在显示时间处理从日期时间到日期的转换。


DateTimeField

class DateTimeField(auto_now=False, auto_now_add=False, **options)

日期和时间,在 Python 中由 datetime.datetime 实例表示。 采用与 DateField 相同的额外参数。

此字段的默认表单小部件是单个 DateTimeInput。 管理员使用两个单独的 TextInput 小部件和 JavaScript 快捷方式。


DecimalField

class DecimalField(max_digits=None, decimal_places=None, **options)

一个固定精度的十进制数,在 Python 中由 Decimal 实例表示。 它使用 DecimalValidator 验证输入。

有两个 required 参数:

DecimalField.max_digits
号码中允许的最大位数。 请注意,此数字必须大于或等于 decimal_places
DecimalField.decimal_places
与数字一起存储的小数位数。

例如,要以 2 个小数位的分辨率存储高达 999 的数字,您可以使用:

models.DecimalField(..., max_digits=5, decimal_places=2)

并以 10 位小数的分辨率存储多达约 10 亿的数字:

models.DecimalField(..., max_digits=19, decimal_places=10)

localizeFalseTextInput 时,此字段的默认表单小部件为 NumberInput

笔记

有关两者之间差异的更多信息浮动字段十进制字段类,请看 FloatField 对比 十进制字段 . 您还应该了解十进制字段的 SQLite 限制


DurationField

class DurationField(**options)

用于存储时间段的字段 - 由 timedelta 在 Python 中建模。 在 PostgreSQL 上使用时,使用的数据类型是 interval,而在 Oracle 上,数据类型是 INTERVAL DAY(9) TO SECOND(6)。 否则使用微秒的 bigint

笔记

使用 DurationField 的算术在大多数情况下都有效。 但是,在除 PostgreSQL 之外的所有数据库上,将 DurationField 的值与 DateTimeField 实例上的算术进行比较将无法按预期工作。


EmailField

class EmailField(max_length=254, **options)

CharField 使用 EmailValidator 检查值是否是有效的电子邮件地址。


FileField

class FileField(upload_to=None, max_length=100, **options)

文件上传字段。

笔记

不支持 primary_key 参数,如果使用会引发错误。


有两个可选参数:

FileField.upload_to

该属性提供了一种设置上传目录和文件名的方式,可以通过两种方式进行设置。 在这两种情况下,值都会传递给 Storage.save() 方法。

如果你指定一个字符串值或一个Path,它可能包含strftime()格式,它将被文件上传的日期/时间替换(这样上传的文件不会填满给定目录)。 例如:

class MyModel(models.Model):
    # file will be uploaded to MEDIA_ROOT/uploads
    upload = models.FileField(upload_to='uploads/')
    # or...
    # file will be saved to MEDIA_ROOT/uploads/2015/01/30
    upload = models.FileField(upload_to='uploads/%Y/%m/%d/')

如果您使用默认的 FileSystemStorage,则字符串值将附加到您的 :setting:`MEDIA_ROOT` 路径以形成本地文件系统上将存储上传文件的位置。 如果您使用不同的存储,请查看该存储的文档以了解它如何处理 upload_to

upload_to 也可以是可调用的,例如函数。 这将被调用以获取上传路径,包括文件名。 这个可调用对象必须接受两个参数并返回要传递给存储系统的 Unix 样式路径(带正斜杠)。 这两个论点是:

论据

说明

instance

定义了 FileField 的模型实例。 更具体地说,这是附加当前文件的特定实例。

在大多数情况下,这个对象还没有被保存到数据库中,所以如果它使用默认的 AutoField,它的主键字段 可能还没有值。

filename

最初赋予文件的文件名。 在确定最终目的地路径时,可能会或可能不会考虑这一点。

例如:

def user_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
    return 'user_{0}/{1}'.format(instance.user.id, filename)

class MyModel(models.Model):
    upload = models.FileField(upload_to=user_directory_path)
FileField.storage

存储对象,或返回存储对象的可调用对象。 这将处理文件的存储和检索。 有关如何提供此对象的详细信息,请参阅 管理文件

3.1 版更改: 添加了提供可调用对象的功能。

此字段的默认表单小部件是 ClearableFileInput

在模型中使用 FileFieldImageField(见下文)需要几个步骤:

  1. 在您的设置文件中,您需要将 :setting:`MEDIA_ROOT` 定义为您希望 Django 存储上传文件的目录的完整路径。 (为了性能,这些文件不存储在数据库中。)将 :setting:`MEDIA_URL` 定义为该目录的基本公共 URL。 确保该目录可由 Web 服务器的用户帐户写入。
  2. FileFieldImageField 添加到您的模型中,定义 upload_to 选项以指定要使用的 :setting:`MEDIA_ROOT` 的子目录对于上传的文件。
  3. 所有将存储在您的数据库中的是文件的路径(相对于 :setting:`MEDIA_ROOT`)。 您很可能希望使用 Django 提供的便利 url 属性。 例如,如果您的 ImageField 被称为 mug_shot,您可以使用 模板:Object.mug shot.url 在模板中获取图像的绝对路径。

例如,假设您的 :setting:`MEDIA_ROOT` 设置为 '/home/media',而 upload_to 设置为 'photos/%Y/%m/%d'upload_to'%Y/%m/%d'部分为strftime()格式; '%Y' 是四位数年份,'%m' 是两位数月份,'%d' 是两位数日。 如果您在 1 月上传文件 2007 年 15 月 15 日,它将保存在目录 /home/media/photos/2007/01/15 中。

如果要检索上传文件的磁盘文件名或文件大小,可以分别使用 namesize 属性; 有关可用属性和方法的更多信息,请参阅 File 类参考和 Managing files 主题指南。

笔记

该文件作为在数据库中保存模型的一部分而保存,因此在保存模型之前不能依赖磁盘上使用的实际文件名。


上传文件的相对 URL 可以通过 url 属性获取。 在内部,这会调用底层 Storage 类的 url() 方法。

请注意,无论何时处理上传的文件,都应密切注意上传文件的位置和文件类型,以避免出现安全漏洞。 验证所有上传的文件,以便您确定这些文件是您认为的那样。 例如,如果您盲目地让某人在未经验证的情况下将文件上传到您的 Web 服务器文档根目录中的目录,那么有人可以上传 CGI 或 PHP 脚本并通过访问其在您站点上的 URL 来执行该脚本。 不允许这样。

还要注意的是,即使是上传的 HTML 文件,由于它可以由浏览器执行(尽管不能由服务器执行),因此也可能造成相当于 XSS 或 CSRF 攻击的安全威胁。

FileField 实例在您的数据库中创建为 varchar 列,默认最大长度为 100 个字符。 与其他字段一样,您可以使用 max_length 参数更改最大长度。

FileField 和 FieldFile

class FieldFile

当您访问模型上的 FileField 时,您将获得一个 FieldFile 实例作为访问底层文件的代理。

FieldFile 的 API 与 File 的 API 相同,有一个关键区别:类包装的对象不一定是 Python 内置文件对象的包装器。 ] 相反,它是 Storage.open() 方法的结果的包装器,它可能是一个 File 对象,或者它可能是 的自定义存储实现]文件 API。

除了继承自 File 的 API,如 read()write()FieldFile 还包括几个可以用来与底层文件交互的方法:

警告

该类的两个方法save()delete(),默认将关联的FieldFile的模型对象保存在数据库中。


FieldFile.name

文件的名称,包括从相关 FileFieldStorage 的根的相对路径。

FieldFile.path

通过调用底层 Storage 类的 path() 方法访问文件的本地文件系统路径的只读属性。

FieldFile.size

底层 Storage.size() 方法的结果。

FieldFile.url

通过调用底层 Storage 类的 url() 方法访问文件的相对 URL 的只读属性。

FieldFile.open(mode='rb')

在指定的 mode 中打开或重新打开与此实例关联的文件。 与标准 Python open() 方法不同,它不返回文件描述符。

由于底层文件在访问时是隐式打开的,因此除了重置指向底层文件的指针或更改mode之外,可能没有必要调用此方法。

FieldFile.close()

行为类似于标准 Python file.close() 方法并关闭与此实例关联的文件。

FieldFile.save(name, content, save=True)

此方法获取文件名和文件内容,并将它们传递给字段的存储类,然后将存储的文件与模型字段相关联。 如果您想手动将文件数据与模型上的 FileField 实例相关联,可以使用 save() 方法来保存该文件数据。

接受两个必需的参数:name 是文件名,content 是一个包含文件内容的对象。 可选的 save 参数控制在更改与此字段关联的文件后是否保存模型实例。 默认为 True

请注意, content 参数应该是 django.core.files.File 的实例,而不是 Python 的内置文件对象。 您可以从现有的 Python 文件对象构造一个 File,如下所示:

from django.core.files import File
# Open an existing file using Python's built-in open()
f = open('/path/to/hello.world')
myfile = File(f)

或者,您可以从 Python 字符串中构造一个,如下所示:

from django.core.files.base import ContentFile
myfile = ContentFile("hello world")

有关更多信息,请参阅 管理文件

FieldFile.delete(save=True)

删除与此实例关联的文件并清除该字段的所有属性。 注意:如果在调用 delete() 时碰巧打开了该文件,则此方法将关闭该文件。

可选的 save 参数控制在删除与此字段关联的文件后是否保存模型实例。 默认为 True

请注意,删除模型时,不会删除相关文件。 如果您需要清理孤立文件,则需要自己处理(例如,使用自定义管理命令可以手动运行或安排定期运行,例如 cron)。


FilePathField

class FilePathField(path=, match=None, recursive=False, allow_files=True, allow_folders=False, max_length=100, **options)

A CharField 其选择仅限于文件系统上某个目录中的文件名。 有一些特殊的参数,其中第一个是 required

FilePathField.path

必需的。 此 FilePathField 应从中获取其选择的目录的绝对文件系统路径。 示例:"/home/images"

path 也可能是一个可调用的,比如一个在运行时动态设置路径的函数。 例子:

import os
from django.conf import settings
from django.db import models

def images_path():
    return os.path.join(settings.LOCAL_FILE_DIR, 'images')

class MyModel(models.Model):
    file = models.FilePathField(path=images_path)
FilePathField.match
可选的。 FilePathField 将用于过滤文件名的正则表达式,作为字符串。 请注意,正则表达式将应用于基本文件名,而不是完整路径。 示例:"foo.*\.txt$",它将匹配名为 foo23.txt 但不匹配 bar.txtfoo23.png 的文件。
FilePathField.recursive
可选的。 TrueFalse。 默认值为 False。 指定是否应包含 path 的所有子目录
FilePathField.allow_files
可选的。 TrueFalse。 默认值为 True。 指定是否应包含指定位置的文件。 此或 allow_folders 必须为 True
FilePathField.allow_folders
可选的。 TrueFalse。 默认值为 False。 指定是否应包括指定位置的文件夹。 此或 allow_files 必须为 True

一个潜在的问题是 match 适用于基本文件名,而不是完整路径。 所以,这个例子:

FilePathField(path="/home/images", match="foo.*", recursive=True)

...将匹配 /home/images/foo.png 但不匹配 /home/images/foo/bar.png,因为 match 适用于基本文件名(foo.pngbar.png)。

FilePathField 实例在您的数据库中创建为 varchar 列,默认最大长度为 100 个字符。 与其他字段一样,您可以使用 max_length 参数更改最大长度。


FloatField

class FloatField(**options)

Python 中由 float 实例表示的浮点数。

localizeFalseTextInput 时,此字段的默认表单小部件为 NumberInput

FloatField 对比 DecimalField

FloatField 类有时会与 DecimalField 类混淆。 虽然它们都代表实数,但它们代表这些数字的方式不同。 FloatField 在内部使用 Python 的 float 类型,而 DecimalField 使用 Python 的 Decimal 类型。 有关两者之间的区别的信息,请参阅 decimal 模块的 Python 文档。


ImageField

class ImageField(upload_to=None, height_field=None, width_field=None, max_length=100, **options)

FileField 继承所有属性和方法,但也验证上传的对象是有效的图像。

除了可用于 FileField 的特殊属性外,ImageField 还具有 heightwidth 属性。

为了方便查询这些属性,ImageField 有两个额外的可选参数:

ImageField.height_field
模型字段的名称,每次保存模型实例时都会自动填充图像的高度。
ImageField.width_field
模型字段的名称,每次保存模型实例时都会自动填充图像的宽度。

需要 枕头 库。

ImageField 实例在您的数据库中创建为 varchar 列,默认最大长度为 100 个字符。 与其他字段一样,您可以使用 max_length 参数更改最大长度。

此字段的默认表单小部件是 ClearableFileInput


IntegerField

class IntegerField(**options)

一个整数。 从 -21474836482147483647 的值在 Django 支持的所有数据库中都是安全的。

它使用 MinValueValidatorMaxValueValidator 根据默认数据库支持的值验证输入。

localizeFalseTextInput 时,此字段的默认表单小部件为 NumberInput


GenericIPAddressField

class GenericIPAddressField(protocol='both', unpack_ipv4=False, **options)

字符串格式的 IPv4 或 IPv6 地址(例如 192.0.2.302a02:42fe::4)。 此字段的默认表单小部件是 TextInput

IPv6 地址规范化遵循 RFC 4291#section-2.2 第 2.2 节,包括使用该节第 3 段中建议的 IPv4 格式,如 ::ffff:192.0.2.0。 例如,2001:0::0:01 将归一化为 2001::1,而 ::ffff:0a0a:0a0a 将归一化为 ::ffff:10.10.10.10。 所有字符都转换为小写。

GenericIPAddressField.protocol
将有效输入限制为指定协议。 可接受的值为 'both'(默认)、'IPv4''IPv6'。 匹配不区分大小写。
GenericIPAddressField.unpack_ipv4
解压缩 IPv4 映射地址,如 ::ffff:192.0.2.1。 如果启用此选项,该地址将被解压缩到 192.0.2.1。 默认为禁用。 仅当 protocol 设置为 'both' 时才能使用。

如果允许空值,则必须允许空值,因为空值存储为空值。


JSONField

class JSONField(encoder=None, decoder=None, **options)

3.1 版中的新功能。


用于存储 JSON 编码数据的字段。 在 Python 中,数据以其 Python 原生格式表示:字典、列表、字符串、数字、布尔值和 None

JSONField 支持 MariaDB 10.2.7+、MySQL 5.7.8+、Oracle、PostgreSQL 和 SQLite(启用了 JSON1 扩展)。

JSONField.encoder

一个可选的 json.JSONEncoder 子类,用于序列化标准 JSON 序列化器不支持的数据类型(例如 datetime.datetimeUUID)。 例如,您可以使用 DjangoJSONEncoder 类。

默认为 json.JSONEncoder

JSONField.decoder

一个可选的 json.JSONDecoder 子类,用于反序列化从数据库中检索到的值。 该值将采用自定义编码器选择的格式(通常是字符串)。 您的反序列化可能需要考虑到您无法确定输入类型的事实。 例如,您冒着返回 datetime 的风险,该字符串实际上是一个恰好与为 datetime 选择的格式相同的字符串。

默认为 json.JSONDecoder

如果给字段一个 default,请确保它是一个不可变对象,例如 str,或每次返回一个新的可变对象的可调用对象,例如 dict ] 或函数。 提供一个可变的默认对象,如 default={}default=[] 在所有模型实例之间共享一个对象。

在数据库中查询JSONField,参见查询JSONField

索引

IndexField.db_index 都创建了 B 树索引,这在查询 JSONField 时不是特别有用。 仅在 PostgreSQL 上,您可以使用更适合的 GinIndex


PostgreSQL 用户

PostgreSQL 有两种基于 JSON 的原生数据类型:jsonjsonb。 它们之间的主要区别在于它们的存储方式和查询方式。 PostgreSQL 的 json 字段存储为 JSON 的原始字符串表示形式,并且必须在基于键查询时即时解码。 jsonb 字段基于允许索引的 JSON 的实际结构进行存储。 权衡是写入 jsonb 字段的少量额外成本。 JSONField 使用 jsonb


甲骨文用户

Oracle 数据库不支持存储 JSON 标量值。 仅支持 JSON 对象和数组(在 Python 中使用 dictlist 表示)。


NullBooleanField

class NullBooleanField(**options)

BooleanFieldnull=True

自 3.1 版起已弃用:NullBooleanField 已弃用,取而代之的是 BooleanField(null=True)


PositiveBigIntegerField

class PositiveBigIntegerField(**options)

3.1 版中的新功能。


PositiveIntegerField,但只允许某个(依赖于数据库的)点下的值。 从 09223372036854775807 的值在 Django 支持的所有数据库中都是安全的。


PositiveIntegerField

class PositiveIntegerField(**options)

类似于 IntegerField,但必须为正数或零 (0)。 从 02147483647 的值在 Django 支持的所有数据库中都是安全的。 出于向后兼容性的原因,接受值 0


PositiveSmallIntegerField

class PositiveSmallIntegerField(**options)

PositiveIntegerField,但只允许某个(依赖于数据库的)点下的值。 从 032767 的值在 Django 支持的所有数据库中都是安全的。


SlugField

class SlugField(max_length=50, **options)

Slug 是一个报纸术语。 slug 是某物的短标签,仅包含字母、数字、下划线或连字符。 它们通常用于 URL。

与 CharField 一样,您可以指定 max_length(也请阅读该部分中有关数据库可移植性和 max_length 的说明)。 如果未指定 max_length,Django 将使用默认长度 50。

意味着将 Field.db_index 设置为 True

根据某些其他值的值自动预填充 SlugField 通常很有用。 您可以使用 prepopulated_fields 在管理员中自动执行此操作。

它使用 validate_slugvalidate_unicode_slug 进行验证。

SlugField.allow_unicode
如果是 True,则该字段除 ASCII 字母外还接受 Unicode 字母。 默认为 False


SmallAutoField

class SmallAutoField(**options)

AutoField,但只允许在特定(依赖于数据库)限制下的值。 从 132767 的值在 Django 支持的所有数据库中都是安全的。


SmallIntegerField

class SmallIntegerField(**options)

类似于 IntegerField,但只允许某个(依赖于数据库的)点下的值。 从 -3276832767 的值在 Django 支持的所有数据库中都是安全的。


TextField

class TextField(**options)

一个大文本字段。 此字段的默认表单小部件是 Textarea

如果您指定 max_length 属性,它将反映在自动生成的表单字段的 Textarea 小部件中。 但是,它不会在模型或数据库级别强制执行。 为此使用 CharField

TextField.db_collation

3.2 版中的新功能。

字段的数据库排序规则名称。

笔记

排序规则名称未标准化。 因此,这将无法跨多个数据库后端移植。

甲骨文

Oracle 不支持 TextField 的排序规则。


TimeField

class TimeField(auto_now=False, auto_now_add=False, **options)

时间,在 Python 中由 datetime.time 实例表示。 接受与 DateField 相同的自动填充选项。

此字段的默认表单小部件是 TimeInput。 管理员添加了一些 JavaScript 快捷方式。


URLField

class URLField(max_length=200, **options)

URL 的 CharField,由 URLValidator 验证。

此字段的默认表单小部件是 URLInput

与所有 CharField 子类一样,URLField 采用可选的 max_length 参数。 如果未指定 max_length,则使用默认值 200。


UUIDField

class UUIDField(**options)

用于存储通用唯一标识符的字段。 使用 Python 的 UUID 类。 在 PostgreSQL 上使用时,它存储在 uuid 数据类型中,否则存储在 char(32) 中。

对于 primary_key,通用唯一标识符是 AutoField 的一个很好的替代方案。 数据库不会为你生成UUID,所以建议使用default

import uuid
from django.db import models

class MyUUIDModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    # other fields

请注意,一个可调用对象(省略括号)被传递给 default,而不是 UUID 的实例。

在 PostgreSQL 上查找

使用 :lookup:`iexact`, :lookup:`contains`, :lookup:`icontains`, :lookup:`startswith`[ X116X]、:lookup:`istartswith`:lookup:`endswith`:lookup:`iendswith` 在 PostgreSQL 上的查找不起作用没有连字符的值,因为 PostgreSQL 将它们存储在带连字符的 uuid 数据类型中。


关系字段

Django 还定义了一组表示关系的字段。

ForeignKey

class ForeignKey(to, on_delete, **options)

多对一的关系。 需要两个位置参数:与模型相关的类和 on_delete 选项。

要创建递归关系——一个与自身具有多对一关系的对象——使用 models.ForeignKey('self', on_delete=models.CASCADE)

如果需要在尚未定义的模型上创建关系,可以使用模型的名称,而不是模型对象本身:

from django.db import models

class Car(models.Model):
    manufacturer = models.ForeignKey(
        'Manufacturer',
        on_delete=models.CASCADE,
    )
    # ...

class Manufacturer(models.Model):
    # ...
    pass

当模型被子类化为具体模型并且与抽象模型的 app_label 无关时,在 抽象模型 上以这种方式定义的关系会得到解析:

产品/模型.py

from django.db import models

class AbstractCar(models.Model):
    manufacturer = models.ForeignKey('Manufacturer', on_delete=models.CASCADE)

    class Meta:
        abstract = True

生产/模型.py

from django.db import models
from products.models import AbstractCar

class Manufacturer(models.Model):
    pass

class Car(AbstractCar):
    pass

# Car.manufacturer will point to `production.Manufacturer` here.

要引用在另一个应用程序中定义的模型,您可以明确指定具有完整应用程序标签的模型。 例如,如果上面的 Manufacturer 模型是在另一个名为 production 的应用程序中定义的,则您需要使用:

class Car(models.Model):
    manufacturer = models.ForeignKey(
        'production.Manufacturer',
        on_delete=models.CASCADE,
    )

这种称为惰性关系的引用在解决两个应用程序之间的循环导入依赖关系时非常有用。

ForeignKey 上自动创建数据库索引。 您可以通过将 db_index 设置为 False 来禁用此功能。 如果您创建外键是为了一致性而不是连接,或者您将创建替代索引(如部分或多列索引),您可能希望避免索引的开销。

数据库表示

在幕后,Django 将 "_id" 附加到字段名称以创建其数据库列名称。 在上面的例子中,Car 模型的数据库表将有一个 manufacturer_id 列。 (您可以通过指定 db_column 来显式更改此设置)但是,除非您编写自定义 SQL,否则您的代码永远不必处理数据库列名。 您将始终处理模型对象的字段名称。


参数

ForeignKey 接受定义关系如何工作的细节的其他参数。

ForeignKey.on_delete

ForeignKey 引用的对象被删除时,Django 将模拟由 on_delete 参数指定的 SQL 约束的行为。 例如,如果您有一个可以为 null 的 ForeignKey 并且您希望在删除引用的对象时将其设置为 null:

user = models.ForeignKey(
    User,
    models.SET_NULL,
    blank=True,
    null=True,
)

on_delete 不会在数据库中创建 SQL 约束。 支持数据库级级联选项 :ticket:`可能会在以后实施 <21961>` .

on_delete 的可能值在 django.db.models 中找到:

  • CASCADE

    级联删除。 Django 模拟 SQL 约束 ON DELETE CASCADE 的行为,并删除包含 ForeignKey 的对象。

    Model.delete() 不会在相关模型上调用,但会为所有已删除的对象发送 pre_deletepost_delete 信号。

  • PROTECT

    通过引发 ProtectedErrordjango.db.IntegrityError 的子类)来防止删除引用的对象。

  • RESTRICT

    3.1 版中的新功能。

    通过引发 RestrictedErrordjango.db.IntegrityError 的子类)来防止删除引用的对象。 与 PROTECT 不同,如果引用的对象还引用了在同一操作中被删除的不同对象,但通过 CASCADE 关系,则允许删除引用的对象。

    考虑这组模型:

    class Artist(models.Model):
        name = models.CharField(max_length=10)
    
    class Album(models.Model):
        artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
    
    class Song(models.Model):
        artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
        album = models.ForeignKey(Album, on_delete=models.RESTRICT)

    Artist 可以被删除,即使这意味着删除 Song 引用的 Album,因为 Song 也引用 Artist 本身通过级联关系。 例如:

    >>> artist_one = Artist.objects.create(name='artist one')
    >>> artist_two = Artist.objects.create(name='artist two')
    >>> album_one = Album.objects.create(artist=artist_one)
    >>> album_two = Album.objects.create(artist=artist_two)
    >>> song_one = Song.objects.create(artist=artist_one, album=album_one)
    >>> song_two = Song.objects.create(artist=artist_one, album=album_two)
    >>> album_one.delete()
    # Raises RestrictedError.
    >>> artist_two.delete()
    # Raises RestrictedError.
    >>> artist_one.delete()
    (4, {'Song': 2, 'Album': 1, 'Artist': 1})
  • SET_NULL

    设置 ForeignKey 为空; 这仅在 nullTrue 时才有可能。

  • SET_DEFAULT

    ForeignKey 设置为其默认值; 必须设置 ForeignKey 的默认值。

  • SET()

    ForeignKey 设置为传递给 SET() 的值,或者如果传入的是 callable,则为调用它的结果。 在大多数情况下,需要传递一个可调用对象以避免在导入 models.py 时执行查询:

    from django.conf import settings
    from django.contrib.auth import get_user_model
    from django.db import models
    
    def get_sentinel_user():
        return get_user_model().objects.get_or_create(username='deleted')[0]
    
    class MyModel(models.Model):
        user = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.SET(get_sentinel_user),
        )
  • DO_NOTHING

    不采取行动。 如果您的数据库后端强制执行参照完整性,除非您手动向数据库字段添加 SQL ON DELETE 约束,否则这将导致 IntegrityError

ForeignKey.limit_choices_to

当使用 ModelForm 或管理员呈现此字段时,为该字段的可用选项设置限制(默认情况下,查询集中的所有对象都可供选择)。 可以使用字典、Q 对象或返回字典或 Q 对象的可调用对象。

例如:

staff_member = models.ForeignKey(
    User,
    on_delete=models.CASCADE,
    limit_choices_to={'is_staff': True},
)

导致 ModelForm 上的相应字段仅列出具有 is_staff=TrueUsers。 这可能对 Django 管理员有所帮助。

例如,当与 Python datetime 模块结合使用以按日期范围限制选择时,可调用表单会很有帮助。 例如:

def limit_pub_date_choices():
    return {'pub_date__lte': datetime.date.today()}

limit_choices_to = limit_pub_date_choices

如果 limit_choices_to 是或返回一个 Q 对象 ,这对 复杂查询 很有用,那么它只会影响 admin 中可用的选项未在该模型的 ModelAdmin 中的 raw_id_fields 中列出。

笔记

如果可调用对象用于 limit_choices_to,则每次实例化新表单时都会调用它。 它也可以在模型被验证时调用,例如通过管理命令或管理员。 管理员构建查询集以在各种边缘情况下多次验证其表单输入,因此您的可调用对象可能会被多次调用。

ForeignKey.related_name

用于从相关对象返回到此对象的关系的名称。 它也是 related_query_name(用于来自目标模型的反向过滤器名称的名称)的默认值。 有关完整说明和示例,请参阅 相关对象文档 。 注意在抽象模型上定义关系时必须设置这个值; 当你这样做时 一些特殊的语法 可用。

如果您不希望 Django 创建反向关系,请将 related_name 设置为 '+' 或以 '+' 结束。 例如,这将确保 User 模型不会与此模型具有向后关系:

user = models.ForeignKey(
    User,
    on_delete=models.CASCADE,
    related_name='+',
)
ForeignKey.related_query_name

用于来自目标模型的反向过滤器名称的名称。 如果设置,则默认为 related_namedefault_related_name 的值,否则默认为模型名称:

# Declare the ForeignKey with related_query_name
class Tag(models.Model):
    article = models.ForeignKey(
        Article,
        on_delete=models.CASCADE,
        related_name="tags",
        related_query_name="tag",
    )
    name = models.CharField(max_length=255)

# That's now the name of the reverse filter
Article.objects.filter(tag__name="important")

related_name一样,related_query_name通过一些特殊语法支持应用标签和类插值。

ForeignKey.to_field
关系所指向的相关对象上的字段。 默认情况下,Django 使用相关对象的主键。 如果您引用不同的字段,则该字段必须具有 unique=True
ForeignKey.db_constraint

控制是否应在数据库中为此外键创建约束。 默认值为 True,这几乎肯定是您想要的; 将此设置为 False 可能对数据完整性非常不利。 也就是说,以下是您可能想要执行此操作的一些场景:

  • 您拥有无效的旧数据。

  • 您正在对数据库进行分片。

如果将其设置为 False,则访问不存在的相关对象将引发其 DoesNotExist 异常。

ForeignKey.swappable

如果此 ForeignKey 指向可交换模型,则控制迁移框架的反应。 如果它是 True - 默认值 - 那么如果 ForeignKey 指向与 settings.AUTH_USER_MODEL(或其他可交换模型设置)的当前值匹配的模型,则关系将使用对设置的引用而不是直接对模型的引用存储在迁移中。

如果您确定您的模型应始终指向换入模型,您只想将其覆盖为 False - 例如,如果它是专为您的自定义用户模型设计的配置文件模型。

将其设置为 False 并不意味着您可以引用可交换模型,即使它被换出 - False 意味着使用此 ForeignKey 进行的迁移将始终引用您指定的确切模型(因此它例如,如果用户尝试使用您不支持的 User 模型运行,则会失败)。

如果有疑问,请将其保留为默认值 True


ManyToManyField

class ManyToManyField(to, **options)

多对多的关系。 需要一个位置参数:与模型相关的类,其工作方式与 ForeignKey 完全相同,包括 recursivelazy 关系。

可以使用字段的 RelatedManager 添加、删除或创建相关对象。

数据库表示

在幕后,Django 创建了一个中间连接表来表示多对多关系。 默认情况下,此表名称是使用多对多字段的名称和包含它的模型的表名称生成的。 由于某些数据库不支持超过一定长度的表名,这些表名将被自动截断并使用唯一性哈希,例如 author_books_9cdf。 您可以使用 db_table 选项手动提供连接表的名称。


参数

ManyToManyField 接受一组额外的参数——都是可选的——控制关系如何运作。

ManyToManyField.related_name
ForeignKey.related_name 相同。
ManyToManyField.related_query_name
ForeignKey.related_query_name 相同。
ManyToManyField.limit_choices_to

ForeignKey.limit_choices_to 相同。

limit_choices_to 在使用 参数指定的自定义中间表的 ManyToManyField 上使用时无效。

ManyToManyField.symmetrical

仅用于对 self 的 ManyToManyFields 的定义。 考虑以下模型:

from django.db import models

class Person(models.Model):
    friends = models.ManyToManyField("self")

当 Django 处理这个模型时,它识别出它自己有一个 ManyToManyField,因此它不会向 Person 类添加 person_set 属性。 相反,假设 ManyToManyField 是对称的——也就是说,如果我是你的朋友,那么你就是我的朋友。

如果您不想在与 self 的多对多关系中对称,请将 symmetrical 设置为 False。 这将强制 Django 添加反向关系的描述符,允许 ManyToManyField 关系是非对称的。

ManyToManyField.through

Django 会自动生成一张表来管理多对多关系。 但是,如果要手动指定中间表,则可以使用 选项指定代表要使用的中间表的 Django 模型。

此选项最常见的用途是将 额外数据与多对多关系 相关联。

笔记

如果您不希望相同实例之间有多个关联,请添加一个 UniqueConstraint,包括 from 和 to 字段。 Django 自动生成的多对多表包含这样的约束。

笔记

使用中间模型的递归关系无法确定反向访问器名称,因为它们是相同的。 您需要将 related_name 设置为至少其中之一。 如果您不希望 Django 创建反向关系,请将 related_name 设置为 '+'

如果您不指定显式 through 模型,仍然有一个隐式 through 模型类,您可以使用它直接访问为保存关联而创建的表。 它有三个字段来链接模型。

如果源模型和目标模型不同,则会生成以下字段:

  • id:关系的主键。

  • <containing_model>_id:声明ManyToManyField的型号的id

  • <other_model>_idManyToManyField指向的型号的id

如果 ManyToManyField 指向和指向同一模型,则会生成以下字段:

  • id:关系的主键。

  • from_<model>_id:指向模型的实例的id(即 源实例)。

  • to_<model>_id:关系指向的实例的id(即 目标模型实例)。

此类可用于像普通模型一样查询给定模型实例的关联记录:

Model.m2mfield.through.objects.all()
ManyToManyField.through_fields

仅在指定自定义中介模型时使用。 Django 通常会确定使用中间模型的哪些字段以自动建立多对多关系。 但是,请考虑以下模型:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=50)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(
        Person,
        through='Membership',
        through_fields=('group', 'person'),
    )

class Membership(models.Model):
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    inviter = models.ForeignKey(
        Person,
        on_delete=models.CASCADE,
        related_name="membership_invites",
    )
    invite_reason = models.CharField(max_length=64)

Membership两个外键到Personpersoninviter),这使得关系模糊,Django无法知道使用哪一个。 在这种情况下,您必须使用 through_fields 明确指定 Django 应该使用哪些外键,如上例所示。

through_fields 接受一个二元组 ('field1', 'field2'),其中 field1 是模型的外键名称 ManyToManyField 在 (group 在这种情况下),以及 field2 目标模型的外键名称(在这种情况下为 person)。

当您在一个中间模型上有多个外键指向参与多对多关系的任何(甚至两个)模型时,您 必须 指定 through_fields。 这也适用于 递归关系 当使用中间模型并且模型有两个以上的外键时,或者您想明确指定应该使用哪两个 Django。

ManyToManyField.db_table
要创建的用于存储多对多数据的表的名称。 如果未提供,Django 将假定基于以下名称的默认名称:定义关系的模型表和字段本身的名称。
ManyToManyField.db_constraint

控制是否应在数据库中为中间表中的外键创建约束。 默认值为 True,这几乎肯定是您想要的; 将此设置为 False 可能对数据完整性非常不利。 也就是说,以下是您可能想要执行此操作的一些场景:

  • 您拥有无效的旧数据。

  • 您正在对数据库进行分片。

通过 db_constraintthrough 都是错误的。

ManyToManyField.swappable

如果此 ManyToManyField 指向可交换模型,则控制迁移框架的反应。 如果它是 True - 默认值 - 那么如果 ManyToManyField 指向的模型与 settings.AUTH_USER_MODEL(或其他可交换模型设置)的当前值匹配,则该关系将使用对设置的引用而不是直接对模型的引用存储在迁移中。

如果您确定您的模型应始终指向换入模型,您只想将其覆盖为 False - 例如,如果它是专为您的自定义用户模型设计的配置文件模型。

如果有疑问,请将其保留为默认值 True

ManyToManyField 不支持 验证器

null 不起作用,因为无法在数据库级别要求关系。


OneToOneField

class OneToOneField(to, on_delete, parent_link=False, **options)

一对一的关系。 从概念上讲,这类似于具有 unique=TrueForeignKey,但关系的“反向”侧将直接返回单个对象。

这是作为模型的主键最有用的,它以某种方式“扩展”了另一个模型; 多表继承例如通过添加从子模型到父模型的隐式一对一关系来实现。

需要一个位置参数:与模型相关的类。 这与 ForeignKey 的工作方式完全相同,包括所有关于 recursivelazy 关系的选项。

如果您没有为 OneToOneField 指定 related_name 参数,Django 将使用当前模型的小写名称作为默认值。

使用以下示例:

from django.conf import settings
from django.db import models

class MySpecialUser(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    supervisor = models.OneToOneField(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='supervisor_of',
    )

您生成的 User 模型将具有以下属性:

>>> user = User.objects.get(pk=1)
>>> hasattr(user, 'myspecialuser')
True
>>> hasattr(user, 'supervisor_of')
True

如果相关表中的条目不存在,则在访问反向关系时会引发 RelatedObjectDoesNotExist 异常。 这是目标模型的 Model.DoesNotExist 异常的子类。 例如,如果用户没有由 MySpecialUser 指定的主管:

>>> user.supervisor_of
Traceback (most recent call last):
    ...
RelatedObjectDoesNotExist: User has no supervisor_of.

此外, OneToOneField 接受 ForeignKey 接受的所有额外参数,以及一个额外参数:

OneToOneField.parent_link
True 用于从另一个 具体模型 继承的模型中时,表明该字段应用作返回父类的链接,而不是额外的 OneToOneField ] 通常由子类化隐式创建。

有关 OneToOneField 的使用示例,请参阅 一对一关系


字段 API 参考

class Field

Field 是代表数据库表列的抽象类。 Django 使用字段来创建数据库表 (db_type()),将 Python 类型映射到数据库 (get_prep_value()),反之亦然 (from_db_value() ])。

因此,字段是不同 Django API 中的基本部分,尤其是 modelsquerysets

在模型中,字段被实例化为类属性并表示特定的表列,请参阅 Models。 它具有 nullunique 等属性,以及 Django 用于将字段值映射到数据库特定值的方法。

FieldRegisterLookupMixin 的子类,因此 TransformLookup 都可以在其上注册以用于 QuerySet ]s(例如 field_name__exact="foo")。 默认情况下已注册所有 内置查找

Django 的所有内置字段,例如 CharField,都是 Field 的特定实现。 如果您需要自定义字段,您可以对任何内置字段进行子类化,也可以从头开始编写 Field。 无论哪种情况,请参阅 编写自定义模型字段

description

字段的详细描述,例如 对于 django.contrib.admindocs 应用程序。

描述可以是以下形式:

description = _("String (up to %(max_length)s)")

其中参数是从字段的 __dict__ 插入的。

descriptor_class

一个实现 描述符协议 的类,它被实例化并分配给模型实例属性。 构造函数必须接受一个参数,即 Field 实例。 覆盖此类属性允许自定义获取和设置行为。

要将 Field 映射到特定于数据库的类型,Django 公开了几种方法:

get_internal_type()

返回命名此字段的字符串以用于后端特定目的。 默认情况下,它返回类名。

有关自定义字段的用法,请参阅 模拟内置字段类型

db_type(connection)

返回 字段 的数据库列数据类型,同时考虑 connection

有关自定义字段中的用法,请参阅 自定义数据库类型

rel_db_type(connection)

返回指向 字段ForeignKeyOneToOneField 等字段的数据库列数据类型,同时考虑 connection

有关自定义字段中的用法,请参阅 自定义数据库类型

Django 需要与数据库后端和字段进行交互的主要有以下三种情况:

  • 当它查询数据库时(Python 值 -> 数据库后端值)

  • 当它从数据库加载数据时(数据库后端值 -> Python 值)

  • 当它保存到数据库时(Python 值 -> 数据库后端值)

查询时使用get_db_prep_value()get_prep_value()

get_prep_value(value)

value 是模型属性的当前值,该方法应以已准备好用作查询中的参数的格式返回数据。

有关用法,请参阅 将 Python 对象转换为查询值

get_db_prep_value(value, connection, prepared=False)

value 转换为后端特定的值。 默认情况下,如果 prepared=Trueget_prep_value() 如果是 False,它会返回 value

有关用法,请参阅 将查询值转换为数据库值

加载数据时,使用from_db_value()

from_db_value(value, expression, connection)

将数据库返回的值转换为 Python 对象。 与 get_prep_value() 相反。

此方法不用于大多数内置字段,因为数据库后端已经返回正确的 Python 类型,或者后端本身进行了转换。

expressionself 相同。

有关用法,请参阅 将值转换为 Python 对象

笔记

出于性能原因,from_db_value 没有在不需要它的字段(所有 Django 字段)上实现为无操作。 因此,您不能在定义中调用 super

保存时使用pre_save()get_db_prep_save()

get_db_prep_save(value, connection)

get_db_prep_value() 相同,但在字段值必须 saved 到数据库时调用。 默认返回 get_db_prep_value()

pre_save(model_instance, add)

get_db_prep_save() 之前调用的方法在保存之前准备值(例如 对于 DateField.auto_now)。

model_instance为该字段所属的实例,add为该实例是否第一次存入数据库。

它应该从 model_instance 为该字段返回适当属性的值。 属性名称在 self.attname 中(这是由 Field 设置的)。

请参阅 保存前的预处理值 以了解用法。

字段通常从序列化或表单中接收不同类型的值。

to_python(value)

将值转换为正确的 Python 对象。 它的作用与 value_to_string() 的相反,也在 clean() 中调用。

有关用法,请参阅 将值转换为 Python 对象

除了保存到数据库,字段还需要知道如何序列化它的值:

value_from_object(obj)

返回给定模型实例的字段值。

这个方法经常被 value_to_string() 使用。

value_to_string(obj)

obj 转换为字符串。 用于序列化字段的值。

有关用法,请参阅 转换字段数据以进行序列化

当使用模型表单时,Field需要知道它应该用哪个表单字段表示:

formfield(form_class=None, choices_form_class=None, **kwargs)

ModelForm 返回此字段的默认 django.forms.Field

默认情况下,如果 form_classchoices_form_class 都是 None,则使用 CharField。 如果该字段具有 choices 且未指定 choices_form_class,则使用 TypedChoiceField

有关用法,请参阅 指定模型字段的表单字段

deconstruct()

返回一个包含足够信息来重新创建字段的 4 元组:

  1. 模型上字段的名称。

  2. 字段的导入路径(例如 "django.db.models.IntegerField")。 这应该是最便携的版本,所以不那么具体可能会更好。

  3. 位置参数列表。

  4. 关键字参数的字典。

必须将此方法添加到 1.7 之前的字段中才能使用 Migrations 迁移其数据。


字段属性参考

每个 Field 实例都包含几个允许自省其行为的属性。 当您需要编写依赖于字段功能的代码时,请使用这些属性而不是 isinstance 检查。 这些属性可以与 Model._meta API 一起使用,以缩小特定字段类型的搜索范围。 自定义模型字段应实现这些标志。

字段的属性

Field.auto_created
指示字段是否自动创建的布尔标志,例如模型继承使用的 OneToOneField
Field.concrete
指示字段是否具有与其关联的数据库列的布尔标志。
Field.hidden

布尔标志,指示一个字段是否用于支持另一个非隐藏字段的功能(例如 content_typeobject_id 字段组成 GenericForeignKey)。 hidden 标志用于区分模型上字段的公共子集与模型上的所有字段。

笔记

Options.get_fields() 默认排除隐藏字段。 传入 include_hidden=True 返回结果中的隐藏字段。

Field.is_relation
指示字段是否包含对其功能的一个或多个其他模型的引用的布尔标志(例如 ForeignKeyManyToManyFieldOneToOneField 等)。
Field.model
返回定义字段的模型。 如果在模型的超类上定义了字段,则 model 将引用超类,而不是实例的类。


具有关系的字段的属性

这些属性用于查询关系的基数和其他详细信息。 这些属性存在于所有字段中; 但是,如果字段是关系类型 (Field.is_relation=True),它们将只有布尔值(而不是 None)。

Field.many_to_many
如果字段具有多对多关系,则布尔标志为 TrueFalse 否则。 Django 中唯一包含 True 的字段是 ManyToManyField
Field.many_to_one
如果字段具有多对一关系,则为 True 的布尔标志,例如 ForeignKeyFalse 否则。
Field.one_to_many
如果字段具有一对多关系,则布尔标志为 True,例如 GenericRelationForeignKey 的反向; False 否则。
Field.one_to_one
如果字段具有一对一关系,则为 True 的布尔标志,例如 OneToOneFieldFalse 否则。
Field.related_model
指向与该字段相关的模型。 例如,ForeignKey(Author, on_delete=models.CASCADE) 中的 AuthorGenericForeignKeyrelated_model 始终为 None