Django丨模版层 - 4. 字段参数
Django丨模版层 - 4. 字段参数
所有的模型字段都可以接收一定数量的参数,比如:
CharField
至少需要一个max_length
参数。
下面的这些参数是所有字段都可以使用的,并且是可选的。
1. null
该值为True
时,Django在数据库用NULL
保存空值。默认值为False
。
对于保存字符串类型数据的字段,请尽量避免将此参数设为True
,那样会导致两种没有数据
的情况,一种是NULL
,另一种是空字符串''
。Django 的惯例是使用空字符串而不是NULL
。
2. blank
该值为True
时,字段可以为空。默认值为False
。
和null
参数不同的是,null
是纯数据库层面的,而blank
是验证相关的,它与表单验证是否允许输入框内为空有关,与数据库无关。所以要小心一个null
为False
,blank
为True
的字段接收到一个空值可能会出bug或异常。
3. choices
用于页面上的选择框标签,需要先提供一个二维的二元元组,第一个元素表示存在数据库内真实的值,第二个表示页面上显示的具体内容。在浏览器页面上将显示第二个元素的值。
例如:
1 | YEAR_IN_SCHOOL_CHOICES = ( |
一般来说,最好将选项定义在类里,并取一个直观的名字,如下所示:
1 | from django.db import models |
注意:每当choices
的顺序变动时将会创建新的迁移。
如果一个模型中有多个字段需要设置choices
,可以将这些二维元组组合起来,显得更加整洁优雅,例如下面的做法:
1 | MEDIA_CHOICES = [ |
反过来,要获取一个choices
的第二元素的值,可以使用get_FOO_display()
方法,其中的FOO
用字段名代替。对于下面的例子:
1 | from django.db import models |
使用方法:
1 | >>> p = Person(name="Fred Flintstone", shirt_size="L") |
从Django3.0开始,新增了TextChoices
、IntegerChoices
和Choices
三个类,用来达到类似Python的enum
枚举库的作用,下面是一个例子:
1 | from django.utils.translation import gettext_lazy as _ |
简要解释一下:
- 第一句导入是废话,搞国际化翻译的,和本例的内容其实没关系
- 核心在
Student
模型中创建了个内部类YearInSchool
YearInSchool
继承了Django新增的TextChoices
类TextChoices
中没定义别的,只定义了一些类变量,这些类变量看起来和我们前面使用的二维二元元组本质上是一个套路Student
模型中有一个year_in_school
字段,其中定义了choices
参数,参数的值是YearInSchool.choices
year_in_school
字段还定义了default
参数,值是YearInSchool.FRESHMAN
- 从本质上来说,这和我们开始使用
choice
的方式是一样的,只不过换成了类的方式,而不是二维元组 - 吐个槽,这么设计除了增加学习成本有什么好处?有多少
Choice
选项需要你非得用类的形式管理起来封装起来?二维元组它就不香吗?新手学习就不累吗?
吐槽归吐槽,该介绍的还得介绍,否则是不敬业。
如果你不需要人类可读的帮助文本,那么类似的YearInSchool
还可以写成下面的方式:
1 | class Vehicle(models.TextChoices): |
哎,我都写内部类了,还差这点吗?
另外,由于使用整数作为选项的场景太常见了,Django除了提供TextChoices
还提供了一个IntegerChoices
,例子如下:
1 | class Card(models.Model): |
实际上,Django为这几个类提供了一些属性,典型的有下面的:
.label
.choices
.values
.name
读者可以多尝试,看看每个的意义。
参考用法:
1 | 'MedalType', 'GOLD SILVER BRONZE') MedalType = models.TextChoices( |
如果文本或数字类型不满足你的要求,你也可以继承Choice
类,自己写。比如下面就创建了一个时间类型选项的choices
类:
1 | class MoonLandings(datetime.date, models.Choices): |
最后,如果想设置空标签,可以参考下面的做法:
1 | class Answer(models.IntegerChoices): |
4. db_column
该参数用于定义当前字段在数据表内的列名。如果未指定,Django将使用字段名作为列名。
5. db_index
该参数接收布尔值。如果为True
,数据库将为该字段创建索引。
6. db_tablespace
用于字段索引的数据库表空间的名字,前提是当前字段设置了索引。默认值为工程的DEFAULT_INDEX_TABLESPACE设置。如果使用的数据库不支持表空间,该参数会被忽略。
7. default
字段的默认值,可以是值或者一个可调用对象。如果是可调用对象,那么每次创建新对象时都会调用。设置的默认值不能是一个可变对象,比如列表、集合等等。lambda
匿名函数也不可用于default
的调用对象,因为匿名函数不能被migrations
序列化。
注意:在某种原因不明的情况下将default
设置为None
,可能会引发intergyerror:not null constraint failed
,即非空约束失败异常
,导致python manage.py migrate
失败,此时可将None
改为False
或其它的值,只要不是None
就行。
8. editable
如果设为False
,那么当前字段将不会在admin
后台或者其它的ModelForm
表单中显示,同时还会被模型验证功能跳过。参数默认值为True
。
9. error_messages
用于自定义错误信息。参数接收字典类型的值。字典的键可以是null、 blank、 invalid、 invalid_choice、 unique和unique_for_date其中的一个。
10. help_text
额外显示在表单部件上的帮助文本。即便你的字段未用于表单,它对于生成文档也是很有用的。
该帮助文本默认情况下是可以带HTML
代码的,具有风险:
help_text="Please use the following format: <em>YYYY-MM-DD</em>."
所以使用时请注意转义为纯文本,防止脚本攻击。
11. primary_key
如果你没有给模型的任何字段设置这个参数为True
,Django将自动创建一个AutoField
自增字段,名为id
,并设置为主键。也就是id = models.AutoField
(primary_key=True
)。
如果你为某个字段设置了primary_key=True
,则当前字段变为主键,并关闭Django自动生成id
主键的功能。
primary_key=True
隐含null=False
和unique=True
的意思。一个模型中只能有一个主键字段!
另外,主键字段不可修改,如果你给某个对象的主键赋个新值实际上是创建一个新对象,并不会修改原来的对象。
1 | from django.db import models |
12. unique
设为True
时,在整个数据表内该字段的数据不可重复。
注意:对于ManyToManyField
和OneToOneField
关系类型,该参数无效。
注意: 当unique=True
时,db_index
参数无须设置,因为unqiue
隐含了索引。
13. unique_for_date
日期唯一。可能不太好理解。举个栗子,如果你有一个名叫title
的字段,并设置了参数unique_for_date="pub_date"
,那么Django将不允许有两个模型对象具备同样的title
和pub_date
。有点类似联合约束。
14. unique_for_month
同上,只是月份唯一。
15. unique_for_year
同上,只是年份唯一。
16. verbose_name
为字段设置一个人类可读,更加直观的别名。
对于每一个字段类型,除了ForeignKey
、ManyToManyField
和OneToOneField
这三个特殊的关系类型,其第一可选位置参数都是verbose_name
。如果没指定这个参数,Django会利用字段的属性名自动创建它,并将下划线转换为空格。
下面这个例子的verbose name
是"person’s first name"
:
1 | first_name = models.CharField("person's first name", max_length=30) |
下面这个例子的verbose name
是"first name"
:
1 | first_name = models.CharField(max_length=30) |
对于外键、多对多和一对一字字段,由于第一个参数需要用来指定关联的模型,因此必须用关键字参数verbose_name
来明确指定。如下:
1 | poll = models.ForeignKey( |
另外,你无须大写verbose_name
的首字母,Django自动为你完成这一工作。
17. validators
运行在该字段上的验证器的列表。