购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.3 Django模型的字段

Django模型中最重要并且也是唯一必须执行的就是字段定义。字段在类中进行定义,对应于实体数据库的字段。另外,定义模型字段名时为了避免冲突,不建议使用模型API中已经定义的关键字。

3.3.1 字段类型

字段类型用以指定数据库的数据类型,例如Integer、VARCHAR和TEXT这几种比较常用的数据类型。在Django模型定义中,字段类型均派生自Field类的实例。Django框架中的Field类是一个抽象类,专门用于定义数据库表的列表项。

Django模型一共内置了多种字段类型,基本能够满足一般的设计需求。Django模型的主要字段类型说明如下:

· AutoField:一个自动增加的Integer类型。一般情况下,AutoField类型是不需要直接使用的,域的主键会自动被添加到模型中。

· BigAutoField:类似AutoField类型,一个自动增加的长Integer(64-bit)类型(1~9223372036854775807)。

· IntegerField:一个Integer类型(−2147483648~2147483647)。

· BigIntegerField:一个长Integer类型(−9223372036854775808~9223372036854775807)。

· SmallIntegerField:一个Small Integer类型(−32768~32767)。

· BinaryField:一个用来存储二进制数据的类型。

· BooleanField:一个用来存储布尔值(True / False)的类型。

· NullBooleanField:类似BooleanField(null=True)类型。

· FloatField:一个用来存储浮点型数据的类型,表示Python语言中的float实例。

· CharField:一个用来存储字符串的类型。CharField类型必须额外定义一个表示最大长度的参数——CharField.max_length。

· DateField:一个用来存储日期的类型,表示Python语言中的datetime.date实例。CharField类型可以额外定义两个可选参数——DateField.auto_now和DateField.auto_now_add。其中,DateField.auto_now参数用于自动获取当前时间,DateField.auto_now_add参数用于在对象第一次创建时自动获取当前时间。

· DateTimeField:一个用来存储日期和时间的类型,表示Python语言中的datetime.datetime实例。

· TimeField:一个用来存储时间的类型,表示Python语言中的datetime.time实例。

· DecimalField:一个用来存储十进制数据的类型,表示Python语言中的Decimal实例。DecimalField类型需要定义两个必选参数——DecimalField.max_digits和DecimalField.decimal_places。其中,DecimalField.max_digits参数表示最大数值,DecimalField.decimal_places参数表示存储位置。

· DurationField:一个用来存储时间间隔的类型,表示Python语言中的timedelta。

· EmailField:一个CharField类型的域,用于表示电子邮件类型。

· FileField:一个用于文件上传的类型。FileField类型需要定义两个必选参数——FileField.upload_to和FileField.storage。其中,FileField.upload_to参数表示存储路径,FileField.storage参数表示存储对象。

· TextField:一个用于存储文本的类型,在表单域中默认使用TextArea小部件(Widget)。

· ImageField:一个用来存储Image文件的类型,继承自FileField类型。ImageField类型需要定义两个必选参数——ImageField.height_field和ImageField.width_field。其中,ImageField.height_field参数表示Image文件的高度,ImageField.width_field参数表示Image文件的宽度。

· GenericIPAddressField:一个用来存储原生IP(IPv4或IPv6)地址的类型,在表单域中默认使用TextInput小部件(Widget)。

· URLField:一个用来存储URL的类型,继承自CharField类型,在表单域中默认使用TextInput小部件(Widget)。

3.3.2 字段选项

每一种字段类型都需要指定一些特定的参数。例如,CharField(及其子类)需要接收一个max_length参数,用以指定数据库存储VARCHAR数据时的字节数。

一些可选的参数是通用的,可以用于任何字段类型,下面具体介绍一些会经常用到的通用参数。

1.null(类型:Field.null)

null的默认值为False,如果设置为True,则当该字段为空时,Django模型会将数据库中的该字段设置为NULL。

注意 避免在基于字符串的字段(如CharField和TextField)上使用null类型,Django模型在使用惯例上是使用空字符串而不是NULL。

2.blank(类型:Field.blank)

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

blank类型与null类型是有区别的。blank类型主要用于表单验证,如果某个表单域设为“blank=True”,则验证时会允许该域为空值;如果某个表单域设为“blank=False”,则验证时该域是必须填写的。

3.default(类型:Field.default)

表示字段的默认值。该字段值可以是一个值或者是一个可调用的对象,如果是一个可调用的对象,则每次实例化模型时都会调用该对象。

default类型的代码示例如下:

【代码3-4】

【代码分析】

在第01、02行代码中定义了一个contact_default()方法,返回了一个email对象。

在第04~06行代码中定义了一个JSON域变量contact_info,其default值引用了contact_default()方法返回的email对象。

4.choices(类型:Field.choices)

choices是一个用来选择值的二维元组。其中,第一个值是实际存储的值,第二个值用来进行选择。

choices类型最好是在Django模型中使用。下面是官方文档给出的代码示例,这个代码示例实现了一个大学生年级类。

【代码3-5】

【代码分析】

在第03行代码中定义了一个大学生类CollegeStudent。

在第04~07行代码中定义了一组字符串变量,即FRESHMAN、SOPHOMORE、JUNIOR和SENIOR,分别用于表示大学生四个年级的名称。

在第08~13行代码中定义了一个choices类型的变量YEAR_IN_COLLEGE_CHOICES,其中包含了4个元组,使用了第04~07行代码中定义的变量。

在第14~18行代码中定义了一个字符型域变量year_in_college,将choices值定义为变量YEAR_IN_COLLEGE_CHOICES,默认值为FRESHMAN。

在第20~21行代码中定义了一个方法is_upperclass(),用于返回大学生中的高年级元组。

5.unique(类型:Field.unique)

如果unique的值设置为True,则这个字段必须在整个表中保持值唯一。unique类型还定义了一组关于日期和时间的子类型,例如unique_for_date(唯一日期)、unique_for_month(唯一月份)、unique_for_year(唯一年份)。

6.editable(类型:Field.editable)

editable默认值为True(真),如果值为False(假),则在Admin模式下字段将不能编辑。

7.primary_key(类型:Field.primary_key)

primary_key用于设置主键,一个字段只能设置一个主键。如果没有设置主键,则Django框架在创建表时会自动加上。如果primary_key值设置为True,则将该字段设置为该模型的主键,示例如下:

     id = meta.AutoField('ID', primary_key=True)

8.help_text(类型:Field.help_text)

help_text是额外的“帮助”文本,随表单控件一同显示。示例如下:

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

即便某个字段未用于表单,该类型对于生成文档也是很有用的。

9.verbose_name(类型:Field.verbose_name)

verbose_name用于设置admin模式中字段的显示名称。

10.validators(类型:Field.validators)

validators用于设置某个域的有效性检查列表。

11.db_column(类型:Field.db_column)

db_column用于为某个域指定数据库列表的名称;如果未指定,则使用该域的名称。

12.db_index(类型:Field.db_index)

如果db_index值为True,则创建数据库索引。

13.db_tablespace(类型:Field.db_tablespace)

db_tablespace用于为某个域的索引指定数据库表空间的名称。

3.3.3 关联关系字段——外键

Django模型中同样也定义了一组代表关系的字段——外键(Foreign Key),这一点与传统关系数据库的设计是一致的。

在Django模型中,外键是通过一个名称为ForeignKey的类实现的,具体声明如下:

     class ForeignKey(to, on_delete, **options)

其中,参数to(必需的)表示要关联的类,on_delete表示删除操作时的级联关系,**options是一些可选参数。在创建“多对一”的关系时,必须设置参数to和on_delete。

如果要创建一个递归关系,即一个与其自身有“多对一”关系的对象,则写法如下:

     models.ForeignKey('self', on_delete=models.CASCADE)

其中,使用models对象上的CASCADE参数表示在删除某一关联数据时,与之关联的全部数据也会删除。

参数on_delete的各个选项值说明如下:

· models.CASCADE:表示在删除某一关联数据时,与之关联的全部数据也会删除。

· models.DO_NOTHING:表示在删除关联数据时将会引发IntegrityError错误。

· models.PROTECT:表示在删除关联数据时将会引发ProtectedError错误。

· models.SET_NULL:表示在删除关联数据时,与之关联的值设置为null(前提是FK字段设置为可空)。

· models.SET_DEFAULT:表示在删除关联数据时,与之关联的值设置为默认值(前提FK字段设置默认值)。

· models.SET:表示在删除关联数据时,如果与之关联的值设置为指定值,则设置models.SET值;如果与之关联的值设置为可执行对象的返回值,则设置models.SET可执行对象。

可选参数**options的各个选项的说明如下:

· related_name=None:表示反向操作时使用的字段名。

· related_query_name=None:表示反向操作时使用的连接前缀。

· limit_choices_to=None:表示在Admin或ModelForm中显示关联数据时提供的条件。

· db_constraint=True:表示是否在数据库中创建外键约束。

· parent_link=False:表示在Admin中是否显示关联数据。

关于在Django模型中使用外键的方法,可参看下面官方文档给出的代码示例。

【代码3-6】

【代码分析】

在第10行代码中定义了一个制造商类Manufacturer。

在第03~08行代码中定义了一个汽车类Car。

在第04~07行代码中,通过models对象的ForeignKey()方法创建了汽车类Car的外键manufacturer。具体内容如下:

· 第05行代码中,参数to引用了制造商类Manufacturer。

· 第06行代码中,参数on_delete设置为models.CASCADE选项值。

3.3.4 关联关系字段——一对一关系

在Django模型中,“一对一”关系是通过一个名称为OneToOneField的类实现的,具体声明如下:

     class OneToOneField(to, on_delete, **options)

其中,参数to(必需的)表示要关联的类,on_delete表示删除操作时的级联关系,**options是一些可选参数。在创建一对一的关系时,必须设置参数to和on_delete。

对于一对一关系,生活中比较典型的例子就是银行“账户”和“联系人”之间的关系,示例代码如下:

【代码3-7】

【代码分析】

在第03~06行代码中定义了一个账户类Account。

在第07~16行代码中定义了一个联系人类Contact。具体内容如下:

· 在第12~15行代码中,通过models对象的OneToOneField()方法创建了联系人类Contact的外键account。

· 在第13行代码中,参数to引用了账户类Account。

· 在第14行代码中,参数on_delete设置为models.CASCADE选项值。

这样,在删除某个账户时,基于联系人类Contact中外键account的设置,相关联的联系人也会一同被删除。

3.3.5 关联关系字段——多对多关系

在关联关系字段的外键使用过程中,除了“多对一”和“一对一”关系之外,最常用的就是“多对多”关系了。

在Django模型中,多对多关系是通过一个名称为ManyToManyField的类实现的,具体声明如下:

     class ManyToManyField(to, **options)

其中,参数to(必需的)表示要关联的类,**options是一些可选参数。在创建多对多的关系时,必须设置参数to。

对于多对多关系,生活中比较典型的例子就是“作者”和“图书”之间的关系。简单来讲,就是一个作者可以编写多本书,而一本书也可以有多个作者,这个就是典型的“多对多”关系。代码示例如下:

【代码3-8】

【代码分析】

在第03~07行代码中,定义了一个作者类Author。

在第08~16行代码中,定义了一个图书类Book。具体说明如下:

在第13~15行代码中,通过models对象的ManyToManyField()方法创建了作者类Author的外键author,实现了多对多关联关系。其中在第14行代码中,参数to引用了作者类Author。

上面的代码实现了“作者”表与“图书”表之间多对多的关联关系,但是如果还想要关联某个作者写作的某一本图书的出版时间,因为表已经存在了,所以增加一个字段的操作就会比较麻烦。

对于这样的情形,Django模型允许指定一个用于管理多对多关联关系的中间模型,然后就可以把这些额外的字段添加到这个中间模型中。具体的方法就是在ManyToManyField()方法中,指定参数through作为中间模型。

下面,我们在【代码3-8】的基础上略作修改,实现添加一个“版本”字段的功能,代码如下:

【代码3-9】

【代码分析】

在第03~07行代码中,定义了一个作者类Author。

在第08~17行代码中,定义了一个图书类Book。具体说明如下:

在第13~16行代码中,通过models对象的ManyToManyField()方法创建了作者类Author的外键author,实现了多对多关联关系。

在第15行代码中,参数through引用了第三个类BookVersion。

在第18~29行代码中,定义了图书版本类(BookVersion)。具体说明如下:

· 在第19~22行代码中,通过models对象的ForeignKey()方法创建了作者类Author的外键author。

· 在第23~26行代码中,通过models对象的ForeignKey()方法创建了图书类Book的外键book。

· 在第27行代码中,通过models对象的CharField()方法新增了一个图书“版本”变量,该变量就是新增的字段。

3.3.6 自定义模型字段

如果已经存在的模型字段不能满足最初的需求,或者希望支持一些不太常见的数据库字段,Django模型支持自定义模型字段,并提供创建自定义字段的各方面内容。

Django模型内置的字段类型并未覆盖所有可能的数据库字段类型,一般只有类似VARCHAR和Integer这样的常见类型。对于更多的字段类型,就需要用户自己创建自定义类型了。自定义类型是一个相对复杂的Python对象,该对象可以采用某种形式进行序列化,适应标准的数据库字段类型。

这里,我们举一个创建“桥牌”自定义模型字段的例子。对于这个“桥牌”自定义模型字段,读者不需要知道“桥牌”具体的游戏规则,只需要知道一副“桥牌”共计52张牌,会平均分配给4个玩家。通常这4个玩家被称为“北”“东”“南”和“西”。

那么,自定义模型“桥牌”这个Python类就可以定义如下:

【代码3-10】

【代码分析】

在第01行代码中,定义了这个桥牌类的名称为Hand。

在第04~09行代码,在定义的初始化方法__init__()中,依次将north(北),east(东),south(南)和west(西)4个玩家设置为Hand类的self内置属性。

在Django模型中使用自定义模型字段时,是不需要修改这个字段的,对象属性的赋值与取值操作与其他Python类是一样的,关键技巧是告诉Django如何保存和加载对象。 tHfzWQtIcu/fjt/hG18lvVtWE4OYVZxPlL+k07wsYFIEf/dSH4eoi3UXxAQlGlt3

点击中间区域
呼出菜单
上一章
目录
下一章
×