模型字段参考

本文档包含所有 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[source]

下面描述的格式的映射或可迭代对象,用作此字段的选项。如果给出选项,则它们由 模型验证 强制执行,并且默认表单小部件将是具有这些选项的选择框,而不是标准文本字段。

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

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,否则选择框将显示包含 "---------" 的标签。要覆盖此行为,请向 choices 添加一个包含 None 的元组;例如 (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 函数式 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

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_default 但未设置 default,并且未为该字段赋值,则在未保存的模型实例上,DatabaseDefault 对象作为字段值返回。保存模型实例时,数据库将确定该字段的实际值。

db_index

Field.db_index

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

请改用 indexes 选项。

尽可能使用 Meta.indexes 选项。在几乎所有情况下,indexes 提供比 db_index 更强大的功能。db_index 未来可能会被弃用。

db_tablespace

Field.db_tablespace[source]

为此字段索引使用的 数据库表空间 的名称(如果此字段已编入索引)。默认值为项目的 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这样的映射到模型实例的字段,默认值应该是它们引用的字段的值(除非设置了to_field,否则为pk),而不是模型实例。

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

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

editable

Field.editable

如果为False,则该字段不会显示在管理员界面或任何其他ModelForm中。在模型验证期间也会跳过它们。默认为True

error_messages

Field.error_messages[source]

使用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[source]

如果为True,则此字段在整个表中必须唯一。

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

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

请注意,当uniqueTrue时,您不需要指定db_index,因为unique暗示创建索引。

unique_for_date

Field.unique_for_date

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

例如,如果您有一个具有unique_for_date="pub_date"的字段title,那么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

字段的可读名称。如果没有提供verbose_name,Django将自动使用字段的属性名创建它,并将下划线转换为空格。参见Verbose field names

validators

Field.validators[source]

为此字段运行的验证器列表。有关更多信息,请参见validators documentation

字段类型

AutoField

class AutoField(**options)[source]

一个IntegerField,根据可用的ID自动递增。通常不需要直接使用它;如果未另行指定,则主键字段将自动添加到您的模型中。参见Automatic primary key fields

BigAutoField

class BigAutoField(**options)[source]

一个64位整数,非常类似于AutoField,不同之处在于它保证可以容纳从19223372036854775807的数字。

BigIntegerField

class BigIntegerField(**options)[source]

一个64位整数,非常类似于IntegerField,不同之处在于它保证可以容纳从-92233720368547758089223372036854775807的数字。此字段的默认表单小部件是NumberInput

BinaryField

class BinaryField(max_length=None, **options)[source]

用于存储原始二进制数据的字段。可以赋值bytesbytearraymemoryview

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

BinaryField.max_length

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

滥用BinaryField

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

BooleanField

class BooleanField(**options)[source]

一个真/假字段。

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

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

CharField

class CharField(max_length=None, **options)[source]

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

对于大量文本,请使用TextField

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

CharField 有以下额外参数

CharField.max_length

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

注意

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

CharField.db_collation

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

注意

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

Oracle

只有当MAX_STRING_SIZE数据库初始化参数设置为EXTENDED时,Oracle才支持排序规则。

DateField

class DateField(auto_now=False, auto_now_add=False, **options)[source]

日期,在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的转换。

警告

始终将DateFielddatetime.date实例一起使用。

如果您有datetime.datetime实例,建议先将其转换为datetime.date。如果不这样做,DateField会将datetime.datetime本地化到默认时区并将其转换为datetime.date实例,从而去除其时间部分。这对于存储和比较都是正确的。

DateTimeField

class DateTimeField(auto_now=False, auto_now_add=False, **options)[source]

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

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

警告

始终将DateTimeFielddatetime.datetime实例一起使用。

如果您有datetime.date实例,建议先将其转换为datetime.datetime。如果不这样做,DateTimeField将使用默认时区中的午夜作为时间部分。这对于存储和比较都是正确的。要将DateTimeField的日期部分与datetime.date实例进行比较,请使用date查找。

DecimalField

class DecimalField(max_digits=None, decimal_places=None, **options)[source]

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

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

DecimalField.max_digits

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

DecimalField.decimal_places

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

例如,要以2位小数的精度存储高达999.99的数字,可以使用

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)[source]

用于存储时间段的字段——在 Python 中由timedelta建模。在 PostgreSQL 上使用时,使用的數據類型是 interval,在 Oracle 上使用的數據類型是 INTERVAL DAY(9) TO SECOND(6)。否则使用表示微秒的bigint

注意

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

EmailField

class EmailField(max_length=254, **options)[source]

一个CharField,它使用EmailValidator检查值是否为有效的电子邮件地址。

FileField

class FileField(upload_to='', storage=None, max_length=100, **options)[source]

文件上传字段。

注意

不支持 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

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

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

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

  1. 在你的设置文件中,你需要将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 类参考和文件管理主题指南。

注意

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

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

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

另请注意,即使是上传的 HTML 文件,由于浏览器可以执行它(但服务器不能执行),也可能会带来相当于 XSS 或 CSRF 攻击的安全威胁。

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

FileFieldFieldFile

class FieldFile[source]

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

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

除了从 File 继承的 API(例如 read()write())之外,FieldFile 还包含一些可用于与底层文件交互的方法。

警告

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

FieldFile.name

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

FieldFile.path[source]

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

FieldFile.size[source]

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

FieldFile.url[source]

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

FieldFile.open(mode='rb')[source]

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

由于访问底层文件时会隐式打开它,因此可能不需要调用此方法,除非要将指针重置到底层文件或更改 mode

FieldFile.close()[source]

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

FieldFile.save(name, content, save=True)[source]

此方法接收文件名和文件内容,并将它们传递给字段的存储类,然后将存储的文件与模型字段关联。如果您想手动将文件数据与模型上的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)[source]

删除与此实例关联的文件,并清除字段上的所有属性。注意:如果在调用delete()时文件恰好处于打开状态,此方法将关闭该文件。

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

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

FilePathField

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

一个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

可选。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)[source]

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

此字段的默认表单小部件是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)[source]

一个始终基于模型中其他字段计算的字段。此字段由数据库本身管理和更新。使用 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)[source]

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

IPv6 地址规范化遵循 RFC 4291 第 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)[source]

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

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

为了方便对这些属性进行查询,ImageField 具有以下可选参数

ImageField.height_field

每次设置图像对象时,自动填充图像高度的模型字段名称。

ImageField.width_field

每次设置图像对象时,自动填充图像宽度的模型字段名称。

需要 pillow 库。

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

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

IntegerField

class IntegerField(**options)[source]

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

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

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

JSONField

class JSONField(encoder=None, decoder=None, **options)[source]

用于存储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)[source]

类似于PositiveIntegerField,但仅允许小于某个(取决于数据库)点的值。09223372036854775807 的值在 Django 支持的所有数据库中都是安全的。

PositiveIntegerField

class PositiveIntegerField(**options)[source]

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

PositiveSmallIntegerField

class PositiveSmallIntegerField(**options)[source]

类似于PositiveIntegerField,但仅允许小于某个(取决于数据库)点的值。032767 的值在 Django 支持的所有数据库中都是安全的。

SlugField

class SlugField(max_length=50, **options)[source]

Slug 是新闻术语。Slug 是事物的简短标签,仅包含字母、数字、下划线或连字符。它们通常用于 URL。

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

意味着将Field.db_index设置为True

通常情况下,根据其他字段的值自动填充 SlugField 非常有用。您可以使用 prepopulated_fields在admin中自动执行此操作。

它使用validate_slugvalidate_unicode_slug进行验证。

SlugField.allow_unicode

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

SmallAutoField

class SmallAutoField(**options)[source]

类似于AutoField,但仅允许小于某个(取决于数据库)限制的值。在 Django 支持的所有数据库中,132767的值都是安全的。

SmallIntegerField

class SmallIntegerField(**options)[source]

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

TextField

class TextField(**options)[source]

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

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

TextField.db_collation

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

注意

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

Oracle

Oracle 不支持 TextField 的排序规则。

TimeField

class TimeField(auto_now=False, auto_now_add=False, **options)[source]

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

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

URLField

class URLField(max_length=200, **options)[source]

一个用于 URL 的CharField,由URLValidator验证。

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

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

UUIDField

class UUIDField(**options)[source]

用于存储通用唯一标识符的字段。使用 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)[source]

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

from django.db import models


class Manufacturer(models.Model):
    name = models.TextField()


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

第一个位置参数可以是具体的模型类或对模型类的 延迟引用。还支持 递归关系,其中模型与其自身具有关系。

有关第二个位置参数的详细信息,请参阅 ForeignKey.on_delete

数据库索引会自动在 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[source]

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

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

  • PROTECT[source]

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

  • RESTRICT[source]

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

    即使这意味着删除 AlbumSong 引用了它),也可以删除 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[source]

    ForeignKey 设置为 null;只有当 nullTrue 时才有可能。

  • SET_DEFAULT[source]

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

  • SET()[source]

    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[source]

    无需执行任何操作。如果您的数据库后端强制执行参照完整性,除非您手动向数据库字段添加 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 object(这对于 复杂查询 非常有用),那么它只会影响管理员中可用的选择,前提是该字段未列在模型的 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_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 使用相关对象的 primary key。如果引用其他字段,则该字段必须具有 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)[source]

多对多关系。需要一个位置参数:模型相关的类,其工作方式与 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

仅用于自身的多对多字段定义。考虑以下模型

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 模型。

此选项最常见的用途是当您想要将 额外数据与多对多关系关联 时。

注意

如果您不希望在相同实例之间存在多个关联,请添加一个包含 from 和 to 字段的 UniqueConstraint。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)[source]

一对一关系。从概念上讲,这类似于 ForeignKey 加上 unique=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 的使用方法示例,请参阅 一对一关系

延迟关系

延迟关系允许通过其名称(作为字符串)引用模型或创建递归关系。字符串可用作任何关系字段中的第一个参数,以延迟地引用模型。延迟引用可以是 递归的相对的绝对的

递归

要定义模型引用自身的关联关系,请使用 "self" 作为关系字段的第一个参数

from django.db import models


class Manufacturer(models.Model):
    name = models.TextField()
    suppliers = models.ManyToManyField("self", symmetrical=False)

抽象模型 中使用时,递归关系的解析方式使得每个具体子类都引用自身。

相对

当需要使用尚未定义的模型创建关系时,可以使用其名称而不是模型对象本身来引用它

from django.db import models


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


class Manufacturer(models.Model):
    name = models.TextField()
    suppliers = models.ManyToManyField("self", symmetrical=False)

抽象模型 上以此方式定义的关系在将模型作为具体模型进行子类化时解析,并且与抽象模型的 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):
    name = models.TextField()


class Car(AbstractCar):
    pass

在此示例中,Car.manufacturer 关系将解析为 production.Manufacturer,因为它指向 production/models.py 文件中定义的具体模型。

具有相对引用的可重用模型

相对引用允许创建具有关系的可重用抽象模型,这些关系可以在不同应用程序的不同子类中解析为引用的模型的不同实现。

绝对

绝对引用使用其 app_label 和类名指定模型,允许跨不同应用程序进行模型引用。这种类型的延迟关系还可以帮助解决循环导入。

例如,如果 Manufacturer 模型在另一个名为 thirdpartyapp 的应用程序中定义,则可以将其引用为

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

即使在 抽象模型 中使用,绝对引用也始终指向同一模型。

字段 API 参考

class Field[source]

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

因此,字段是不同 Django API 中的基本组成部分,特别是 modelsquerysets

在模型中,字段被实例化为类属性,并表示特定的表列,请参阅 模型。它具有诸如 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()[source]

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

有关在自定义字段中使用的信息,请参阅模拟内置字段类型

db_type(connection)[source]

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

有关在自定义字段中使用的信息,请参阅自定义数据库类型

rel_db_type(connection)[source]

返回指向Field的字段(例如ForeignKeyOneToOneField)的数据库列数据类型,同时考虑connection

有关在自定义字段中使用的信息,请参阅自定义数据库类型

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

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

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

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

查询时,使用get_db_prep_value()get_prep_value()

get_prep_value(value)[source]

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

有关用法的详细信息,请参阅将 Python 对象转换为查询值

get_db_prep_value(value, connection, prepared=False)[source]

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)[source]

get_db_prep_value()相同,但在必须将字段值保存到数据库时调用。默认情况下返回get_db_prep_value()

pre_save(model_instance, add)[source]

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

model_instance是此字段所属的实例,add表示是否第一次将实例保存到数据库。

它应该返回此字段的model_instance中相应属性的值。属性名称位于self.attname中(由Field设置)。

有关用法的详细信息,请参阅保存前预处理值

字段通常以不同的类型接收其值,这些值来自序列化或表单。

to_python(value)[source]

将值转换为正确的 Python 对象。它充当value_to_string()的反向操作,也称为clean()

有关用法的详细信息,请参阅将值转换为 Python 对象

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

value_from_object(obj)[source]

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

此方法通常由value_to_string()使用。

value_to_string(obj)[source]

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

有关用法的详细信息,请参阅转换用于序列化的字段数据

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

formfield(form_class=None, choices_form_class=None, **kwargs)[source]

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

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

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

deconstruct()[source]

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

  1. 模型上字段的名称。

  2. 字段的导入路径(例如 "django.db.models.IntegerField")。这应该是最可移植的版本,因此不太具体的版本可能更好。

  3. 位置参数列表。

  4. 关键字参数字典。

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

注册和获取查找

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

字段属性参考

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

字段属性

Field.auto_created

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

Field.concrete

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

Field.hidden

布尔标志,指示字段是否隐藏,并且默认情况下不应由 Options.get_fields() 返回。例如,对于以 '+' 开头的 related_nameForeignKey 的反向字段。

Field.is_relation

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

Field.model

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

具有关系的字段属性

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

Field.many_to_many

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

Field.many_to_one

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

Field.one_to_many

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

Field.one_to_one

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

Field.related_model

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

返回顶部