模型
字段类型
- BigIntegerField
一个64位整数, 类似于一个? IntegerField ,它的值的范围 是? -9223372036854775808 到 9223372036854775807 之间. 这个字段默认的表 单组件是一个 TextInput . - BinaryField
这是一个用来存储原始二进制码的Field. 只支持 bytes 赋值 - BooleanField
true/false 字段。 此字段的默认表单挂件是一个 CheckboxInput . 如果你需要设置 null 值,则使用 NullBooleanField 来代替BooleanField。 如果 Field.default 没有指定的话, BooleanField 的默认值是 None 。 - CommaSeparatedIntegerField
一个逗号分隔的整数字段。像 CharField 一样, 需要一个 max_length 参数 - DateField
datetime.date 实例表示的日期。
- DateField.auto_now 每次保存对象时,自动设置该字段为当前时间。
- DateField.auto_now_add 当对象第一次被创建时自动设置当前时间。
- auto_now and auto_now_add 这两个设置会在对象创建或更新的时刻,总是使 用default timezone(默认时区)的日期。可以重写save()方法改变
- DateTimeField 日期和时间
- DecimalField 十进制数。必须要有max_digits(该值大于等于此限制)decimal_places(小数点后的数量)
- DurationField 存储一段时间。类似Python中的 timedelta
- FileField 一个上传文件的字段。不支持 primary_key 和 unique 参数
字段选项
- null
如果为 True ,Django 将用 NULL 来在数据库中存储空值。 默认值是 False。此选项是数据库对于空字符串存储的定义,与python层无关 - blan
如果为 True ,该字段允许不填。默认为 False 。 要注意,这与 null 不同。 null 纯粹是数据库范畴的,而 blank 是数据验证 范畴的。如果一个字段的 blank=True ,表单的验证将允许该字段是空值。如果 字段的 blank=False ,该字段就是必填的。 - choices
提供一个二元组,更改admin表单为选择框。调用get_FOO_display 方法(这里的 FOO 就是choices 字段的名称 )可以显示名称
请注意choices可以是任何可迭代的对象 – 不是必须是列表或者元组。from django.db import models class Person(models.Model): SHIRT_SIZES = ( ('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), ) name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=1, choices=SHIRT_SI ZES) >>> p = Person(name="Fred Flintstone", shirt_size="L") >>> p.save() >>> p.shirt_size 'L' >>> p.get_shirt_size_display() 'Large'
- default
提供字段默认值 - help_text
表单部件额外显示的帮助内容。即使字段不在表单中使用,它对生成文档也很有 用。 - primary_key 为true则代表声明为主键
- unique 如果该值设置为 True , 这个数据字段的值在整张表中必须是唯一的
- db_column
数据库中用来表示该字段的名称。如果未指定,那么Django将会使用Field名作为字段名. - db_index 设置为true即为此创建索引
- db_tablespace
名称将作为该字段的索引名。 如 果 DEFAULT_INDEX_TABLESPACE 已经设置,则默认值是由 DEFAULT_INDEX_TABLESPACE指定, 如果没有设置则由 db_tablespace 指 定,如果后台数据库不支持表空间,或者索引,则该选项被忽略 - editable 如果设为 False admin后台不能改写
- error_messages
重写默认抛出的错误信息。通过指定 key 来确认你要重写的错误信息。key 值包括 null , blank , invalid , invalid_choice , unique , 和 unique_for_date - unique_for_date,unique_for_month,unique_for_year
当设为 DateField 和 DateTimeField 字段的名称时,三个选项分别代表日期字段唯一,月份字段唯一,年份字段唯一 。 - validators
和表单验证有关
关系
- ForeignKey
多对一关系。声明ForeignKey的为‘一’,关联对象为‘多’。可添加自己‘self’做自身关联,如关联后声明对象,需要填写字符串形式的名字
参数:- limit_choices_to
当这个字段使用 模型表单 或者Admin 渲染时(默认情况下,查询集中的所有对象
都可以使用),为这个字段设置一个可用的选项。它可以是一个字典、一个 Q 对
象或者一个返回字典或 Q 对象的可调用对象。
将使得 模型表单 中对应的字段只列出 is_staff=True 的 Usersstaff_member = models.ForeignKey(User, limit_choices_to={'is_sta ff': True})
- related_query_name
这个名称用于目标模型的反向过滤,默认值为模型的名称# Declare the ForeignKey with related_query_name class Tag(models.Model): article = models.ForeignKey(Article, related_name="tags", re lated_query_name="tag") name = models.CharField(max_length=255) # That's now the name of the reverse filter Article.objects.filter(tag__name="important")
- to_field 关联到的关联对象的字段名称。默认地,Django 使用关联对象的主键
- db_constraint 控制是否在数据库中为这个外键创建约束。默认值为 True
- on_delete
- CASCADE 级联删除;默认值。
- PROTECT 抛出 ProtectedError 以阻止被引用对象的删除,它 是 django.db.IntegrityError 的一个子类。
- SET_NULL 把 ForeignKey 设置为null; null 参数为 True 时才可以这样做。
- SET_DEFAULT ForeignKey 值设置成它的默认值;此时必须设置 ForeignKey 的default参数。
- SET ()
自定义动作
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(userna me='deleted')[0] class MyModel(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel_user))
- DO_NOTHING 不做动作
- limit_choices_to
当这个字段使用 模型表单 或者Admin 渲染时(默认情况下,查询集中的所有对象
都可以使用),为这个字段设置一个可用的选项。它可以是一个字典、一个 Q 对
象或者一个返回字典或 Q 对象的可调用对象。
- ManyToManyField
通常, ManyToManyField 实例应该位于可以编辑的表单中。-
中介模型
例如,有这样一个应用,它记录音乐家所属的音乐小组。我们可以用一 个 ManyToManyField 表示小组和成员之间的多对多关系。但是,有时你可能想知 道更多成员关系的细节,比如成员是何时加入小组的。对于这些情况,Django 允许你指定一个模型来定义多对多关系。 你可以将其他字 段放在中介模型里面。使用 through 参数指向中介模型.from django.db import models class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): # __unicode__ on Python 2 return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through='Membership ') def __str__(self): # __unicode__ on Python 2 return self.name class Membership(models.Model): person = models.ForeignKey(Person) group = models.ForeignKey(Group) date_joined = models.DateField() invite_reason = models.CharField(max_length=64)
- 中介模型必须有且只有一个外键到源模型(上面例子中的 Group ),或者你必须使用 ManyToManyField.through_fields 显式指定Django 应该使用的外键。如果你的模型中存在超个一个的外键,并且 through_fields 没有指定,将会触发一个无效的错误。 对目标模型的外键有相同的限制(上面例子中的 Person )。
- 对于通过中介模型与自己进行多对多关联的模型,允许存在到同一个模型的两个外键,但它们将被作为多对多关联关系的两个(不同的)方面。如果有超过两个外键,同样你必须像上面一样指定 through_fields ,否则将引发一个验证错误。
- 使用中介模型定义与自身的多对多关系时,你必须设置symmetrical=False
-
参数
- related_name,related_query_name,limit_choices_to 与 ForeignKey 参数相同
- symmetrical
只用于与自身进行关联的ManyToManyField。例如下面的模型:
设置 symmetrical 为 False 。这会强制让Django 添加一个描述器给反向的关联关系,以使得 ManyToManyField 的关联关系不是对称的from django.db import models class Person(models.Model): friends = models.ManyToManyField("self")
- through 指定中介表
- through_fields
Membership 有两个 外键指向 Person ( person 和 inviter ),这使得关联关系含混不清并让Django 不知道使用哪一个。在这种情况下,你必须使用 through_fields 明确指定Django 应该使用哪些外键,就像上面例子一样。through_fields 接收一个二元组 (‘field1’, ‘field2’) ,其中 field1 为指向定义 ManyToManyField 字段的模型的外键名称(本例中为 group ), field2 为指向目标模型的外键的名称(本例中为 person )。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) person = models.ForeignKey(Person) inviter = models.ForeignKey(Person, related_name="membership_invites") invite_reason = models.CharField(max_length=64)
- db_constraint 控制中间表中的外键是否创建约束。默认为 True ,而且这是几乎就是你想要的;设置为 False 对数据完整性将非常糟糕。
-
- OneToOneField
当某个对象想扩展自另一个对象时,最常用的方式就是在这个对象的主键上添加一对一关系。例如,你想建一个“places” 数据库,里面有一些常用的字段,比如address、
phone number 等等。接下来,如果你想在Place数据库的基础上建立一个Restaurant 数据库,而不想将已有的字段复制到 Restaurant模型,那你可以在Restaurant 添加一个 OneToOneField 字段,这个字段指向 Place (因为Restaurant本身就是一个Place;事实上,在处理这个问题的时候,你应该使用一个典型的 继承,它隐含一个一对一关系)。
- 参数 OneToOneField 除了接收 ForeignKey 接收的所有额外的参数之外,还 有另外一个参数:OneToOneField.parent_link.当它为 True 并在继承自另一个具体模型 的模型中使用时,表示该字段应该用于 反查的父类的链接,而不是在子类化时隐式创建的 OneToOneField 。
模型继承
在Django 中有3中风格的继承。
- 通常,你只想使用父类来持有一些通用信息,你不想在每个子模型中都敲一遍。这 个类永远不会单独使用,也不会生成数据库文件,所以你使用抽象基类。
- 如果你继承一个已经存在的模型且想让每个模型具有它自己的数据库表,那么 应该使用多表继承。
- 最后,如果你只是想改变模块Python 级别的行为,而不用修改模型的字段,你 可以使用代理模型。
-
抽象基类
当你想将一些常见信息存储到很多model的时候,抽象化类是十分有用的。在 Meta类中设置 abstract=True ,该类就不能创建任何数据表。如果抽象化基础类和它的子类有相同的项,那么将会出现error(并且Django将 返回一个exception)。from django.db import models class CommonInfo(models.Model): name = models.CharField(max_length=100) age = models.PositiveIntegerField() class Meta: abstract = True class Student(CommonInfo): home_group = models.CharField(max_length=5)
如果子类想 要扩展父类 的,可以继承父类的 Meta 即可.继承时,Django 会对基类的 Meta类做一个调整:在安装 Meta属性之前,Django 会设置 abstract=False.对于抽象基类而言,有些属性放在 Meta 内嵌类里面是没有意义的。例如,包含 db_table 将意味着所有的子类(是指那些没有指定自己的 Meta 类的子类)都使用 同一张数据表,一般来说,这并不是我们想要的。
在抽象基类中使用related_name时,名称 中就要包含 ‘%(app_label)s’ 和 ‘%(class)s -
多表继承 使用这种继承方式时,同一层级下的每个子 model 都是一个真正意义上完整的 model 。 每个子 model 都有专属的数据表,都 可以查询和创建数据表。 继承关系在子 model 和它的每个父类之间都添加一个链 接 (通过一个自动创建的 OneToOneField 来实现)。 例如:
from django.db import models class Place(models.Model): name = models.CharField(max_length=50) address = models.CharField(max_length=80) class Restaurant(Place): serves_hot_dogs = models.BooleanField(default=False) serves_pizza = models.BooleanField(default=False)
- 两个模型中声明的字段都是相互有效的,只不过数据存在另外一张表中。如果你有一个Place队像,那么他同时也是一个Restaurant对象,使用object.restaurant即可获得相应的Restaurant对象。
- 在多表继承中,子类继承父类的 Meta类是没什么意义的。所以子 model 并不能访问它父类的 Meta 类。但是在某些受限的情况下,子类可以 从父类继承某些 Meta :如果子类没有指定 ordering 属性或 get_latest_by 属性,它就会从父类中继承这些属性。如果父类有了排序设置,而你并不想让子类有任何排序设置,你就可以显式地禁用 排序:
class ChildModel(ParentModel): # ... class Meta: # Remove parent's ordering effect ordering = []
- 因为多表继承使用了一个隐含的 OneToOneField 来链接子类与父类,所以象上例 那样,你可以用父类来指代子类。但是这个 OnetoOneField 字段默认的 related_name 值与 ForeignKey 和 ManyToManyField 默认的反向名称相 同。如果你与其他 model 的子类做多对一或是多对多关系,你就必须在每个多对一 和多对多字段上强制指定 related_name 。如果你没这么做,Django 就会在你运 行 验证(validation) 时抛出异常。
-
代理模型
更改 model 在 Python 层的行为实现。比如:更改默认的 manager ,或是添加一个新方法。你可以创 建,删除,更新代理 model 的实例,而且所有的数据都可以象使用原始 model 一 样被保存。 不同之处在于:你可以在代理 model 中改变默认的排序设置和默认的 manager ,更不会对原始 model 产生影响。设置 Meta 类中 proxy 的值 为 True ,就完成了对代理 model 的声明。from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) class MyPerson(Person): class Meta: proxy = True def do_something(self): # ... pass
MyPerson 类和它的父类 Person 操作同一个数据表。特别的是, Person 的 任何实例也可以通过 MyPerson 访问,反之亦然
元选项
可用的元选项
- abstract
为true即为基类 - app_label
所属app - db_table
使用的数据库表名 - db_tablespace
当前模型使用的表空间名字 - default_related_name
这个名字会默认被用于一个关联对象到当前对象的关系。默认为 _set。由于一个字段的反转名称应该是唯一的,当你给你的模型设计子类时,要格外小心。为了规避名称冲突,名称的一部分应该含有’%(app_label)s’和’%(model_name)s’,它们会被应用标签的名称和模型的名称替换,二者都是小写的。详见抽象模型的关联名称。 - get_latest_by 它指定了Manager的latest()和earliest()中使用的默认字段
- managed
默认为True,意思是Django在migrate命令中创建合适的数据表,并且会在 flush 管理命令中移除它们。换句话说,Django会管理这些数据表的生命周期。如果是False,Django 就不会为当前模型创建和删除数据表。如果当前模型表示一个已经存在的,通过其它方法建立的数据库视图或者数据表,这会相当有用 - order_with_respect_to
按照给定的字段把这个对象标记为”可排序的“。这一属性通常用到关联对象上面,使它在父对象中有序。比如,如果Answer和 Question相关联,一个问题有至少一个答案,并且答案的顺序非常重要,你可以这样做:
当order_with_respect_to 设置之后,模型会提供两个用于设置和获取关联对象顺序的方法:get_RELATED_order() 和set_RELATED_order(),其中RELATED是小写的模型名称。例如,假设一Question 对象有很多相关联的Answer对象,返回的列表中含有相关联Answer对象的主键:from django.db import models class Question(models.Model): text = models.TextField() # ... class Answer(models.Model): question = models.ForeignKey(Question) # ... class Meta: order_with_respect_to = 'question'
>>> question = Question.objects.get(id=1) >>> question.get_answer_order() [1, 2, 3] >>> question.set_answer_order([3, 1, 2]) #通过传入一格包含Answer 主键的列表来设置排序
- ordering
对象的默认顺序,前面没有“-”的字段表示正序。使用"?“来表示随机排序。可以传入多个。ordering = ['-pub_date', 'author']
- permissions
设置创建对象时权限表中额外的权限。增加、删除和修改权限会自动为每个模型创建。这个例子指定了一种额外的权限,can_deliver_pizzas:permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
- default_permissions
默认为(‘add’, ‘change’, ‘delete’)。 - select_on_save 决定是否使用1.6版本的更新算法,即先执行select
- unique_together
用来设置的不重复的字段组合,它是一个元组的元组,组合起来的时候必须是唯一的unique_together = (("driver", "restaurant"),)
- index_together 用来设置带有索引的字段组合,列表中的字段将会建立索引(例如,会在CREATE INDEX语句中被使用)
模型类
objects 每个非抽象的 Model 类必须给自己添加一个 Manager 实例。Django 确保在你的 模型类中至少有一个默认的 Manager 。如果你没有添加自己的 Manager , Django 将添加一个属性 objects ,它包含默认的 Manager 实例。如果你添加自 己的 Manager 实例的属性,默认值则不会出现:
from django.db import models
class Person(models.Model):
# Add manager with another name
people = models.Manager()