模型字段参考

本文档包含所有 Field 的 API 参考,包括 Django 提供的 字段选项字段类型

另请参阅

如果内置字段无法满足您的需求,您可以尝试使用 django-localflavor (文档),其中包含适用于特定国家和地区的各种代码。

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

注意

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

字段选项

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

null

Field.null

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

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

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

注意

当使用 Oracle 数据库后端时,无论此属性如何,都会存储值 NULL 来表示空字符串。

blank

Field.blank

如果为 True,则允许该字段为空。默认值为 False

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

提供缺失值

blank=True 可与具有 null=False 的字段一起使用,但这将需要在模型上实现 clean() 以便以编程方式提供任何缺失值。

choices

Field.choices

一个映射或可迭代对象,格式如下所示,用作此字段的选择。如果提供了选择,它们将通过 模型验证 强制执行,并且默认表单小部件将是一个选择框,其中包含这些选择,而不是标准文本字段。

如果提供了映射,则键元素是将要设置在模型上的实际值,第二个元素是人类可读的名称。例如

YEAR_IN_SCHOOL_CHOICES = {
    "FR": "Freshman",
    "SO": "Sophomore",
    "JR": "Junior",
    "SR": "Senior",
    "GR": "Graduate",
}

您还可以传递一个 sequence,它本身包含恰好两个项目的可迭代对象(例如 [(A1, B1), (A2, B2), …])。元组中的第一个元素是将要设置在模型上的实际值,第二个元素是人类可读的名称。例如

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

choices 也可以定义为一个可调用对象,它不接受任何参数并返回上面描述的任何格式。例如

def get_currencies():
    return {i: i for i in settings.CURRENCIES}


class Expense(models.Model):
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    currency = models.CharField(max_length=3, choices=get_currencies)

choices 传递一个可调用对象在以下情况下特别有用,例如,选择是

  • I/O 绑定操作(可能被缓存)的结果,例如查询同一数据库或外部数据库中的表,或从静态文件访问选择。
  • 一个列表,该列表基本上是稳定的,但可能会随着时间或项目而有所不同。此类别的示例包括使用提供知名值库存的第三方应用程序,例如货币、国家/地区、语言、时区等。
在 Django 5.0 中更改

添加了对映射和可调用对象的支持。

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

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",
}

映射的键是要应用于组的名称,值是该组中的选择,包括字段值和选项的人类可读名称。分组选项可以与单个映射中的非分组选项组合(例如,此示例中的 "unknown" 选项)。

您还可以使用序列,例如 2 元组列表

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

请注意,选择可以是任何序列对象 - 不一定是列表或元组。这使您可以动态构建选择。但是,如果您发现自己正在修改 choices 以使其动态,那么您可能最好使用具有 ForeignKey 的适当数据库表。 choices 旨在用于静态数据,这些数据很少或根本不会更改。

注意

每次 choices 的顺序发生变化时,都会创建一个新的迁移。

对于每个具有 choices 设置的模型字段,Django 将将选择规范化为 2 元组列表,并添加一个方法来检索字段当前值的人类可读名称。请参阅数据库 API 文档中的 get_FOO_display()

除非在字段上设置了 blank=False 以及 default,否则将使用包含 "---------" 的标签渲染选择框。要覆盖此行为,请将包含 None 的元组添加到 choices 中;例如 (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,
        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) 2 元组。有关使用更复杂数据类型 子类化选择的示例,请参见下文。如果未提供元组,或最后一个项目不是(延迟)字符串,则 label自动从成员名称生成

  • 在值上添加了一个 .label 属性,以返回人类可读的名称。

  • 在枚举类中添加了许多自定义属性 - .choices.labels.values.names - 以便更轻松地访问枚举的这些独立部分的列表。

    警告

    这些属性名称不能用作成员名称,因为它们会发生冲突。

  • 强制使用 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)

也可以使用 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)"

还有一些需要注意的额外注意事项。

  • 枚举类型不支持 命名组

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

    class Answer(models.IntegerChoices):
        NO = 0, _("No")
        YES = 1, _("Yes")
    
        __empty__ = _("(Unknown)")
    
在 Django 5.0 中更改

添加了对直接在 choices 中使用枚举类型的支持。

db_column

Field.db_column

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

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

db_comment

Django 4.2 中的新增功能。
Field.db_comment

用于此字段的数据库列上的注释。它对于为可能没有查看您的 Django 代码的直接数据库访问人员记录字段很有用。例如

pub_date = models.DateTimeField(
    db_comment="Date and time when the article was published",
)

db_default

Django 5.0 中的新增功能。
Field.db_default

此字段的数据库计算默认值。这可以是文字值或数据库函数,例如 Now

created = models.DateTimeField(db_default=Now())

可以使用更复杂的表达式,只要它们由文字和数据库函数组成。

month_due = models.DateField(
    db_default=TruncMonth(
        Now() + timedelta(days=90),
        output_field=models.DateField(),
    )
)

数据库默认值不能引用其他字段或模型。例如,这是无效的

end = models.IntegerField(db_default=F("start") + 50)

如果同时设置了 db_defaultField.default,则在 Python 代码中创建实例时,default 将优先。 db_default 仍将在数据库级别设置,并在 ORM 之外插入行或在迁移中添加新字段时使用。

db_index

Field.db_index

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

使用 indexes 选项代替。

在可能的情况下,使用 Meta.indexes 选项代替。在几乎所有情况下,indexes 提供比 db_index 更多的功能。 db_index 可能会在将来被弃用。

db_tablespace

Field.db_tablespace

用于此字段索引的 数据库表空间 的名称,如果此字段被索引。默认值为项目的 DEFAULT_INDEX_TABLESPACE 设置(如果已设置),或者模型的 db_tablespace(如果有)。如果后端不支持索引的表空间,则会忽略此选项。

default

Field.default

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

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

def contact_default():
    return {"email": "[email protected]"}


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

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

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

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

默认值也可以使用 Field.db_default 在数据库级别设置。

editable

Field.editable

如果为 False,则该字段不会显示在管理界面或任何其他 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 中为每个应用程序指定自动创建的主键字段类型,或者在 DEFAULT_AUTO_FIELD 设置中全局指定。有关更多信息,请参阅 自动主键字段

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

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

删除 对象时,主键字段将设置为 None

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,则只考虑字段的日期部分。此外,当 USE_TZTrue 时,检查将在对象保存时的 当前时区 中执行。

这是通过模型验证期间的 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

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

字段类型

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.max_length

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

滥用 BinaryField

虽然您可能想在数据库中存储文件,但请考虑在 99% 的情况下,这是一种糟糕的设计。此字段不是对适当的 静态文件 处理的替代。

BooleanField

class BooleanField(**options)

一个真/假字段。

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

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

CharField

class CharField(max_length=None, **options)

一个字符串字段,用于存储大小不一的字符串。

对于大量文本,请使用 TextField

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

CharField 具有以下额外参数

CharField.max_length

字段的最大长度(以字符为单位)。max_length 在数据库级别和 Django 的验证中使用 MaxLengthValidator 强制执行。它对于 Django 包含的所有数据库后端都是必需的,除了 PostgreSQL,它支持无限的 VARCHAR 列。

注意

如果您正在编写必须移植到多个数据库后端的应用程序,您应该注意,某些后端对 max_length 存在限制。有关详细信息,请参阅 数据库后端说明

Django 4.2 中的更改

在 PostgreSQL 上添加了对无限 VARCHAR 列的支持。

CharField.db_collation

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

注意

排序规则名称没有标准化。因此,这在多个数据库后端之间不可移植。

Oracle

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

DateField

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

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

DateField.auto_now

每次保存对象时,自动将字段设置为当前时间。对于“最后修改”时间戳很有用。请注意,始终使用当前日期;它不仅仅是您可以覆盖的默认值。

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

DateField.auto_now_add

首次创建对象时,自动将字段设置为当前时间。对于创建时间戳很有用。请注意,始终使用当前日期;它不仅仅是您可以覆盖的默认值。因此,即使您在创建对象时为该字段设置了一个值,它也会被忽略。如果您希望能够修改此字段,请设置以下内容,而不是 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,并在显示时决定如何处理从 datetime 到 date 的转换。

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 验证输入。

具有以下 **必需** 参数

DecimalField.max_digits

数字中允许的最大位数。请注意,此数字必须大于或等于 decimal_places

DecimalField.decimal_places

要与数字一起存储的小数位数。

例如,要存储最大为 999.99 且精度为 2 位小数的数字,可以使用

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

要存储最大为大约十亿且精度为 10 位小数的数字

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

此字段的默认表单小部件是 NumberInput(当 localizeFalse 时)或 TextInput(否则)。

注意

有关 FloatFieldDecimalField 类之间差异的更多信息,请参阅 FloatField 与 DecimalField。您还应该了解 SQLite 对十进制字段的限制

DurationField

class DurationField(**options)

用于存储时间段的字段 - 在 Python 中由 timedelta 建模。在 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='', storage=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,字符串值将附加到您的 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

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

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

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

  1. 在您的 settings 文件中,您需要定义 MEDIA_ROOT 作为 Django 要存储上传文件的目录的完整路径。(出于性能考虑,这些文件不会存储在数据库中。)定义 MEDIA_URL 作为该目录的公共基本 URL。确保此目录可由 Web 服务器的用户帐户写入。
  2. FileFieldImageField 添加到您的模型,定义 upload_to 选项以指定 MEDIA_ROOT 的子目录,用于存储上传的文件。
  3. 数据库中只会存储文件的路径(相对于 MEDIA_ROOT)。你很可能想要使用 Django 提供的便利 url 属性。例如,如果你的 ImageField 被称为 mug_shot,你可以在模板中使用 {{ object.mug_shot.url }} 获取图像的绝对路径。

例如,假设你的 MEDIA_ROOT 设置为 '/home/media',并且 upload_to 设置为 'photos/%Y/%m/%d'upload_to 中的 '%Y/%m/%d' 部分是 strftime() 格式化;'%Y' 是四位数的年份,'%m' 是两位数的月份,'%d' 是两位数的日期。如果你在 2007 年 1 月 15 日上传了一个文件,它将被保存在 /home/media/photos/2007/01/15 目录中。

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

注意

文件在保存数据库中的模型时被保存,因此在模型保存后才能依赖磁盘上使用的实际文件名。

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

请注意,无论何时处理上传的文件,都应密切注意上传文件的位置以及文件类型,以避免安全漏洞。验证所有上传的文件,以确保文件是你认为的文件。例如,如果你盲目地让某人上传文件,而没有验证,到 web 服务器文档根目录中的目录,那么某人可以上传 CGI 或 PHP 脚本,并通过访问你网站上的 URL 来执行该脚本。不要允许这样做。

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

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

FileFieldFieldFile

class FieldFile

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

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

除了从 File 继承的 API(如 read()write())之外,FieldFile 还包括几个可用于与底层文件交互的方法

警告

此类的两个方法,save()delete(),默认情况下会将关联的 FieldFile 的模型对象保存到数据库中。

FieldFile.name

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

FieldFile.path

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

FieldFile.size

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

FieldFile.url

一个只读属性,通过调用底层 url() 方法的 Storage 类来访问文件的相对 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)

一个 CharField,其选择范围限于文件系统上某个目录中的文件名。具有一些特殊参数,其中第一个是必需的

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

可选。要么是 True 要么是 False。默认值为 False。指定是否应包含 path 的所有子目录

FilePathField.allow_files

可选。要么是 True 要么是 False。默认值为 True。指定是否应包含指定位置中的文件。要么是这个,要么是 allow_folders 必须为 True

FilePathField.allow_folders

可选。要么是 True 要么是 False。默认值为 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 实例表示。

此字段的默认表单小部件是 NumberInput(当 localizeFalse 时)或 TextInput(否则)。

FloatFieldDecimalField

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

GeneratedField

Django 5.0 中的新增功能。
class GeneratedField(expression, output_field, db_persist=None, **kwargs)

一个始终根据模型中的其他字段计算的字段。此字段由数据库本身管理和更新。使用 GENERATED ALWAYS SQL 语法。

有两种类型的生成列:存储的和虚拟的。存储的生成列在写入(插入或更新)时计算,并占用存储空间,就像它是常规列一样。虚拟生成列不占用任何存储空间,并在读取时计算。因此,虚拟生成列类似于视图,而存储的生成列类似于物化视图。

GeneratedField.expression

一个 Expression,数据库使用它在每次更改模型时自动设置字段值。

表达式应是确定性的,并且仅引用模型内的字段(在同一个数据库表中)。生成字段不能引用其他生成字段。数据库后端可能会施加更多限制。

GeneratedField.output_field

一个模型字段实例,用于定义字段的数据类型。

GeneratedField.db_persist

确定数据库列是否应占用存储空间,就像它是真实列一样。如果为 False,则该列充当虚拟列,不占用数据库存储空间。

PostgreSQL 仅支持持久化列。Oracle 仅支持虚拟列。

刷新数据

由于数据库始终计算值,因此在 save() 之后,必须重新加载对象才能访问新值,例如,通过使用 refresh_from_db()

数据库限制

Django 不会验证生成的字段的许多数据库特定限制,数据库可能会引发错误,例如 PostgreSQL 要求在生成的列中引用的函数和运算符标记为 IMMUTABLE

您应该始终检查 expression 是否在您的数据库中受支持。查看 MariaDBMySQLOraclePostgreSQLSQLite 文档。

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' 时使用。

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

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

模型字段的名称,每次保存模型实例时,该字段将自动填充图像的宽度。

需要 Pillow 库。

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

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

IntegerField

class IntegerField(**options)

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

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

此字段的默认表单小部件是 NumberInput(当 localizeFalse 时)或 TextInput(否则)。

JSONField

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

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

JSONField 在 MariaDB、MySQL、Oracle、PostgreSQL 和 SQLite(启用 JSON1 扩展)上受支持。

JSONField.encoder

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

默认为 json.JSONEncoder

JSONField.decoder

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

默认为 json.JSONDecoder

要查询数据库中的 JSONField,请参阅 查询 JSONField

默认值

如果您为字段提供 default,请确保它是一个可调用对象,例如 dict 类或每次返回一个新对象的函数。不正确地使用可变对象,例如 default={}default=[],会创建一个可变的默认值,该默认值在所有实例之间共享。

索引

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

PostgreSQL 用户

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

Oracle 用户

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

PositiveBigIntegerField

class PositiveBigIntegerField(**options)

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

PositiveIntegerField

class PositiveIntegerField(**options)

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

PositiveSmallIntegerField

class PositiveSmallIntegerField(**options)

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

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,但只允许小于某个(依赖于数据库)的值。在 Django 支持的所有数据库中,从 132767 的值都是安全的。

SmallIntegerField

class SmallIntegerField(**options)

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

TextField

class TextField(**options)

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

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

TextField.db_collation

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

注意

排序规则名称没有标准化。因此,这在多个数据库后端之间不可移植。

Oracle

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 和 MariaDB 10.7+ 上使用时,它存储在 uuid 数据类型中,否则存储在 char(32) 中。

通用唯一标识符是 AutoField 的良好替代方案,用于 primary_key。数据库不会为您生成 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 和 MariaDB 10.7+ 上查找

在 PostgreSQL 上使用 iexactcontainsicontainsstartswithistartswithendswithiendswith 查找对没有连字符的值不起作用,因为 PostgreSQL 和 MariaDB 10.7+ 将它们存储在带连字符的 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 无关

products/models.py
from django.db import models


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

    class Meta:
        abstract = True
production/models.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 约束的行为。例如,如果您有一个可为空的 ForeignKey,并且您希望在引用对象被删除时将其设置为 null

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

on_delete 不会在数据库中创建 SQL 约束。对数据库级级联选项的支持 可能在以后实现

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

  • CASCADE

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

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

  • PROTECT

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

  • RESTRICT

    通过引发 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)
    

    即使这意味着删除由 Song 引用的 Album,也可以删除 Artist,因为 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 设置为 null;这只有在 nullTrue 时才可能。

  • SET_DEFAULT

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

  • SET()

    ForeignKey 设置为传递给 SET() 的值,或者如果传递了可调用对象,则为调用它的结果。在大多数情况下,传递可调用对象将是必要的,以避免在导入 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

    无需采取任何操作。如果您的数据库后端强制执行引用完整性,这将导致 IntegrityError,除非您手动将 SQL ON DELETE 约束添加到数据库字段。

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 object,这对于 复杂查询 很有用,那么它只会影响管理界面中可用的选择,前提是该字段未在 raw_id_fields 中列出,该字段位于模型的 ModelAdmin 中。

注意

如果对 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_name 的值或 default_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 创建的迁移将始终引用您指定的精确模型(因此,如果用户尝试运行不支持的用户模型,例如,它将硬性失败)。

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

ManyToManyField

class ManyToManyField(to, **options)

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

可以使用字段的 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 相同。

ManyToManyField.symmetrical

仅在自身上的 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 会自动生成一个表来管理多对多关系。但是,如果您想手动指定中间表,您可以使用 through 选项来指定您要使用的表示中间表的 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)

MembershipPerson 有 *两个* 外键(personinviter),这使得关系变得模棱两可,Django 无法知道使用哪个。在这种情况下,您必须使用 through_fields 显式指定 Django 应该使用哪些外键,如上面的示例所示。

through_fields 接受一个 2 元组 ('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 不支持 validators

null 没有效果,因为没有办法在数据库级别要求关系。

OneToOneField

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

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

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

需要一个位置参数:模型将关联到的类。这与 ForeignKey 的工作方式完全相同,包括有关 递归延迟 关系的所有选项。

如果您没有为 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 指定的监督者

try:
    user.supervisor_of
except User.supervisor_of.RelatedObjectDoesNotExist:
    pass

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

当为 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 中使用(例如 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)

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

请参见 自定义数据库类型,了解在自定义字段中的用法。

rel_db_type(connection)

返回指向 Field 的字段(如 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=True,则返回 value,如果为 False,则返回 get_prep_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() 相同,但在必须将字段值保存到数据库时调用。默认情况下返回 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 转换为字符串。用于序列化字段的值。

有关用法,请参见 将字段数据转换为序列化

当使用 model forms 时,Field 需要知道它应该由哪个表单字段表示。

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

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

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

有关用法,请参见 为模型字段指定表单字段

deconstruct()

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

  1. 模型上字段的名称。
  2. 字段的导入路径(例如 "django.db.models.IntegerField")。这应该是最便携的版本,因此不太具体的版本可能更好。
  3. 位置参数列表。
  4. 关键字参数字典。

此方法必须在 1.7 之前添加到字段中,以便使用 迁移 迁移其数据。

注册和获取查找

Field 实现 查找注册 API。API 可用于自定义哪些查找可用于字段类及其实例,以及如何从字段获取查找。

Django 4.2 中的更改

添加了对 Field 实例上的查找注册的支持。

字段属性引用

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

字段属性

Field.auto_created

布尔标志,指示字段是否为自动创建的,例如模型继承使用的 OneToOneField

Field.concrete

布尔标志,指示字段是否具有与之关联的数据库列。

Field.hidden

布尔标志,指示字段是否隐藏,并且默认情况下不应由 Options.get_fields() 返回。一个例子是 ForeignKey 的反向字段,其 related_name'+' 开头。

Field.is_relation

布尔标志,指示字段是否包含对一个或多个其他模型的引用以实现其功能(例如 ForeignKeyManyToManyFieldOneToOneField 等)。

Field.model

返回定义字段的模型。如果字段在模型的超类上定义,则 model 将引用超类,而不是实例的类。

具有关系的字段属性

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

Field.many_to_many

布尔标志,如果字段具有多对多关系,则为 True;否则为 False。Django 中包含的唯一字段,其中此字段为 TrueManyToManyField

Field.many_to_one

布尔标志,如果字段具有多对一关系(例如 ForeignKey),则为 True;否则为 False

Field.one_to_many

布尔标志,如果字段具有一对多关系(例如 GenericRelationForeignKey 的反向),则为 True;否则为 False

Field.one_to_one

布尔标志,如果字段具有一对一关系(例如 OneToOneField),则为 True;否则为 False

Field.related_model

指向字段所关联的模型。例如,AuthorForeignKey(Author, on_delete=models.CASCADE) 中。GenericForeignKeyrelated_model 始终为 None

返回顶部