百度指数手机版,关键字优化,wordpress怎么用ftp上传插件,无锡制作网站公司简介Django Model 设计
Django Model设计是Django五项基础核心设计之一#xff08;Model设计#xff0c;URL配置#xff0c;View编写#xff0c;Template设计#xff0c;From使用#xff09;#xff0c;也是MVC模式中重要的环节。
如果图片无法访问#xff0c;大家可以移…Django Model 设计
Django Model设计是Django五项基础核心设计之一Model设计URL配置View编写Template设计From使用也是MVC模式中重要的环节。
如果图片无法访问大家可以移步GitHub Django Model 设计查看
Model是数据模型并不是数据库它描述了数据的构成和他们之间的逻辑关系在Django中Model设计实质上就是一个类所以我们可以直接站在类的角度来看Model这样可以尽量避免一些晦涩的概念影响理解。
下面是python中一个基本类的构成
class ClassName(object):# 属性类属性Attribute # 方法def Method():pass根据上面python中的类我们依次研究Django Model
基类定义Django Model的类必须继承自models.Model类名在Django Model设计中类名会被当作是这个数据模型的名称。类属性Django Model设计过程中类属性有两方面的作用一是申明字段二是申明关系一对多多对多一对一方法由于是派生类所以我们不需要自己定义很多方法Model基类已经做的足够完善了只是在有必要的时候我们需要重写一些方法如常见的__str__等内嵌类MetaDjango Model设计过程中内嵌类Meta用来定义元数据所谓元数据就是不是字段的任何数据比如定义排序规则等
下面依次介绍字段关系,Meta
1.字段 Field
都说官方文档才是学习一门语言最好的教程访问官方文档
1.1 字段类型Field types
字面意思用来申明该字段的类型比如常见的字符数字日期邮箱等待下面列举常见的字段类型
AutoField主键
这一个字段一般不需要我们手动定义主要用于ID的自动递增Django会默认为我们创建一个id
# 每一个Model Django都会为我们添加这个字段
id models.AutoField(primary_keyTrue)如果想把自己定义的字段设置为主键需要添加参数primary_key这时显式设置主键Django将不会为我们添加ID字段
与之类似还有一个BigAutoField它支持更大的范围最大到9223372036854775807九百二十亿亿足够绝大多数的使用
IntegerField整数字段
字面意思用来保存整数的字段支持 -2147483648 到 2147483647 的数字
同样与之类似有BigIntegerField 支持-9223372036854775808 到 9223372036854775807 的数字
类似还有FloatField支持浮点数
BooleanField布尔字段
用来存储布尔值与之类似的还有NullBooleanFieldNullBooleanField相当于BooleanField(nulltrue),不过在Django 2.1 之后不建议使用后者应为它有可能在未来版本被弃用
CharField字符字段
这应该是最常用的一个字段了吧用于少量的字符串的储存大量字符串请使用TextField这个字段有一个必须参数max_length用来申明允许储存的最大长度 class CharField(Field):description _(String (up to %(max_length)s))# ...def _check_max_length_attribute(self, **kwargs):if self.max_length is None:return [checks.Error(CharFields must define a max_length attribute.,objself,idfields.E120,)]根据源码我们可以发现如果不指定max_length会直接报CharFields must define a ‘max_length’ attribute.
DateField时间日期字段
该字段有两个常用参数 auto_now 和 auto_now_add
auto_now 指定这个参数可以在每次调用save()时将当前时间作为字段的值会覆盖默认值或之前的值但使用QuerySet.update()等方法不会跟新值auto_now_add : 在初始化会以当前时间戳作为值给字段赋值不管你有没有定义默认值定义了也会被覆盖区别使用auto_now会在每次save()时修改字段值而auto_now_add只是在首次创建对象时才会把当前时间给字段。如果你想能够修改这个字段的值请使用defaultdate.today需要引入from datetime.date.today()auto_now,auto_now_add与default是互斥的任何一种组合都会出错将auto_now或auto_now_add设置为True的结果与editable False和blank True的效果一样
与DateField类似的还有DateTimeField
如果使用DateTimeField想要修改字段的值需要使用defaulttimezone.now 同样需要引入from django.utils.timezone.now()另外还有TimeField,用来表示时间接受的参数与DateField一样
[外链图片转存失败(img-w7TfUVCo-1567244122546)(…/image/DjangoModel_01.png)]
EmailField
实质上是CharField不过使用EmailValidator检查了字符串是否是有效电子邮件地址而已默认max_length254
TextField
实质上也是一个CharField是一个比较大的文本字段
FileField
class FileField(upload_toNone, max_length100, **options)正如文档所说这是一个文件上传字段有两个可选参数upload_to和max_length,后者默认100
upload_to
见名知意upload_to用来申明上传目录如果给定一个字符串类型初值Django会在他后面添加时间就是以上传时间分类文件用户上传文件一般保存到media目录中media目录路径需要在setting.py里定义
MEDIA_ROOT os.path.join(BASE_DIR, media)这个media文件夹如果我们没有建立保存文件时Django会自动创建
class MyModel(models.Model):# file will be uploaded to MEDIA_ROOT/uploadsupload models.FileField(upload_touploads/)# or...# file will be saved to MEDIA_ROOT/uploads/2015/01/30upload models.FileField(upload_touploads/%Y/%m/%d/)如果需要动态存储文件如按用户存储可以把一个函数的返回值作为upload_to的值这个函数必须接受两个参数instance主键传给当前文件的唯一实例和filename文件名如
def user_directory_path(instance, filename):# file will be uploaded to MEDIA_ROOT/user_id/filenamereturn user_{0}/{1}.format(instance.user.id, filename)class MyModel(models.Model):upload models.FileField(upload_touser_directory_path)这里看着有点复杂其实也不难instance是当前FileField的模型实例的模型实例也就是我们定义的字段上面的示例是的user是和User表对应的当然也可以不是user比如
def user_directory_path(instance, filename):# 我没有用user而是自己定义了一个name字段return user_{0}/{1}.format(instance.name, filename)class Diary(models.Model):name models.CharField(max_length10)creat_time models.DateTimeField(auto_now_addTrue)time models.TimeField(auto_nowTrue)upload models.FileField(upload_touser_directory_path,default)class Meta:verbose_name Diaryverbose_name_plural Diarys[外链图片转存失败(img-SGnfpXgs-1567244122548)(…/image/DjangoModel_02.png)]
保存之后就可以看见项目根目录下的文件了
[外链图片转存失败(img-KUPPj7yc-1567244122552)(…/image/DjangoModel_03.png)]
使用时间也是一样的
class Diary(models.Model):name models.CharField(max_length10)creat_time models.DateTimeField(auto_now_addTrue)time models.TimeField(auto_nowTrue)# upload models.FileField(upload_touser_directory_path,default)upload models.FileField(upload_touser_123/%Y/%m/%d/,default)class Meta:verbose_name Diaryverbose_name_plural Diarysdef __str__(self):return self.name[外链图片转存失败(img-oPc8recT-1567244122558)(…/image/DjangoModel_04.png)]
FileField 和 FieldFile
当您访问model上的FileField时会获得一个FieldFile的实例作为访问基础文件的代理。它是继承自python的File的有read(),write()等还自己封装了一些方法如urlname等看官网
ImageField
class ImageField(FileField):attr_class ImageFieldFiledescriptor_class ImageFileDescriptordescription _(Image)def __init__(self, verbose_nameNone, nameNone, width_fieldNone, height_fieldNone, **kwargs):self.width_field, self.height_field width_field, height_fieldsuper().__init__(verbose_name, name, **kwargs)由源码可以看到ImageField是继承自FileField的一个字段除了FileField中的特殊属性外它额外添加了width_field, height_field两个属性用来描述图片大小它会检查一个文件是否是图片其他用法与FileField一样。
其他
除了上面常见的这些还有一些字段诸如用作URL的URLField还有不同大小的IntField如PositiveSmallIntegerFieldPositiveIntegerFieldSmallIntegerField用作IP地址的GenericIPAddressField等待此外你也可以自定义字段看文档就好。
1.2 参数总结
之前遇到很多参数如max_lengthdefault等这里再做总结
null
如果为TrueDjango将在数据库中将空值存储为NULL。 默认值为False。
避免在基于字符串的字段如CharField和TextField上使用null。 如果基于字符串的字段具有null True则表示它具有“无数据”的两个可能值NULL和空字符串。 在大多数情况下为“无数据”提供两个可能的值是多余的; Django约定是使用空字符串而不是NULL。
blank
如果为真则允许该字段为空。默认是假的。注意这与null不同。null纯粹与数据库相关而blank则与验证相关。如果字段为blankTrue表单验证将允许输入空值。如果字段为空False则需要该字段。
choices
为字段提供选项首先他的值应该是一个可迭代对象如列表或元组其次每一项中都应该包含两个元素第一个是要存储到数据库中的真实值第二个是展示给人的值比如
class Diary(models.Model):SEX_CHOICES ((boy, BOY),(girl, GIRL),(else, ELSE))sex models.CharField(max_length10,choicesSEX_CHOICES,default)这个Model展示在admin页面是这样的请忽略其他字段那是之前写的
[外链图片转存失败(img-mRp1xKaa-1567244122563)(…/image/DjangoModel_05.png)]
在随便存储一个值后在MySQL数据库中可以看到是这样的最后一项
[外链图片转存失败(img-0JWk72Nk-1567244122565)(…/image/DjangoModel_06.png)]
展示给我们的是后面大写的而存储在数据库中的则是前面小写的
除此之外如果Model中有多个字段需要选项可以把这些选项分类放在同一个可迭代对象中如
MEDIA_CHOICES ((Audio, ((vinyl, Vinyl),(cd, CD),)),(Video, ((vhs, VHS Tape),(dvd, DVD),)),(unknown, Unknown),
)default
指定默认值可以是默认字符串也可以是函数返回值
db_column
用于此字段的数据库列的名称。 如果没有给出Django将使用该字段的名称。
db_index
如果为True则将为此字段创建数据库索引。
db_tablespace
如果此字段已编制索引则用于此字段索引的数据库表空间的名称。 默认值为项目的DEFAULT_INDEX_TABLESPACE设置如果已设置或模型的db_tablespace如果有。 如果后端不支持索引的表空间则忽略此选项。
editable
如果为False则该字段不会显示在admin或任何其他ModelForm中。 在模型验证期间也会跳过它们。 默认为True。
error_messages error_messages参数允许您覆盖字段将引发的默认消息。传入一个字典其中的关键字与您要覆盖的错误消息相匹配。 在 表单字段 级别或者 表单 Meta 级别定义的错误信息优先级总是高于在 模型字段 级别定义的。 在 模型字段 上定义的错误信息只有在 模型验证 步骤引发 ValidationError 时才会使用并且没有在表单级定义相应的错误信息。 您可以通过添加 NON_FIELD_ERRORS 键到 ModelForm 内部的 Meta 类的 error_messages 中来覆盖模型验证引发的 NON_FIELD_ERRORS 错误信息。 help_text 使用表单小部件显示的额外“帮助”文本。 即使您的字段未在表单上使用它也对文档很有用。 请注意此值不会在自动生成的表单中进行HTML转义。 如果您愿意这可以让您在help_text中包含HTML。 例如 help_textPlease use the following format: emYYYY-MM-DD/em.primary_key
如果为True则此字段将作为Model的主键
unique
如果需要设置该字段值唯一需要把unique设置为True如果尝试保存一个已经存在的值将会引发django.db.IntegrityError异常我们需要捕捉这个异常用于诸如用户名等方面
总结
常用的主要这几个
blank:允许为空choices:提供选择default:提供默认值db_column:提供数据表列名unique:设置是否唯一
2 关系字段
关系也是一种字段只是这个字段的值是别的某个或多个Model只有三种关系字段 ForeignKeyManyToManyField 和 OneToOneField
2.1 ForeignKey
这是一种多对一的关系。 需要两个参数要关联的模型类和on_delete选项。
如果要创建递归关系 与自身具有多对一关系的对象 请使用
models.ForeignKeyselfon_delete models.CASCADE。如果需要在尚未定义的模型上创建关系可以使用模型的名称而不是模型对象本身
class Diary(models.Model):Ordinary_user models.ForeignKey(Demo2,on_deletemodels.CASCADE,default)class Demo2(models.Model):email: str models.EmailField(blankTrue,db_column邮箱,default)Tel_Num models.CharField(max_length20,blankTrue,db_column联系电话,default)address: str models.CharField(max_length100,blankTrue,db_column住址,default)ID_card models.CharField(max_length20, db_column身份证号,default)这样我们建立了两张表Diary表中Ordinary_user字段与Demo2是一个多对一的关系先看一下两张表在MySQL数据库中的样子
先是diary表,同样请忽略其他字段表名是app名_类名
[外链图片转存失败(img-j7xvKUZD-1567244122568)(…/image/DjangoModel_07.png)]
其次是Demo2表
[外链图片转存失败(img-uHS783Pt-1567244122571)(…/image/DjangoModel_08.png)]
发现Django把ForeignKey字段的列名命名为目标Model名_id这里之所以是_id是应为id是这个表的主键而里面存储的也是对应的id序号就是通过保存主键的方式实现一对多的。
然后再看一下再admin界面的样子把
[外链图片转存失败(img-oGREHt43-1567244122573)(…/image/DjangoModel_09.png)]
点加号会打开一个新窗口让你添加Dome的数据应该挺方便
[外链图片转存失败(img-BcLglQBH-1567244122575)(…/image/DjangoModel_10.png)]
on_delete
这是必选参数当删除ForeignKey引用的对象时Django将模拟on_delete参数指定的SQL约束的行为。总共有六种选择 CASCADEPROTECTSET_NULLSET_DEFAULTSET()DO_NOTHING
CASCADE级联删除。 Django模拟SQL约束ON DELETE CASCADE的行为并删除包含ForeignKey的对象。PROTECT通过引发ProtectedErrordjango.db.IntegrityError的子类来防止删除引用的对象。SET_NULL将ForeignKey设置为null; 这只有在null为True时才有可能SET_DEFAULT将ForeignKey设置为其默认值; 必须设置ForeignKey的默认值。SET()将ForeignKey设置为传递给SET的值或者如果传入了回调函数则调用它的结果。 在大多数情况下为了避免在导入models.py时执行查询必须传递一个回调函数。DO_NOTHING不采取行动。 如果数据库后端强制实施参照完整性则除非您手动将SQL ON DELETE约束添加到数据库字段否则将导致IntegrityError。
2.2 ManyToManyField
多对多的关系。 只有一个必须参数与模型相关的类它与ForeignKey的工作方式完全相同包括递归和惰性关系。
2.2.1 参数
(1).symmetrical
只有在和自己建立多对多关系时才有效为true时建立的是对称关系反之为False建立非对称关系默认为True例如
class Demo2(models.Model):friends models.ManyToManyField(self,symmetricalFalse,)默认为true的情况下如果建立A时指定friend为BC那么在BC中A也会被申明为自己的朋友反之则不会
(2).through
Django将自动生成一个表来管理多对多关系。 但是如果要手动指定中间表可以使用through选项指定表示要使用的中间表的Django模型。
此选项最常见的用途是您希望将额外数据与多对多关系相关联。
如果未指定显式直通模型则仍可使用隐式直通模型类来直接访问为保持关联而创建的表。 它有三个字段来链接模型。
如果源模型和目标模型不同表中的字段如下
id: 主键containing_model_id: 申明多对多关系的模型idother_model_id: 指向的模型id
[外链图片转存失败(img-A9IklSnF-1567244122579)(…/image/DjangoModel_11.png)]
如果原模型与目标Model相同自己与自己建立多对多关系表中的字段如下
id关系的主键。from_ model _id源实例to_ model _id目标模型实例
[外链图片转存失败(img-pRlQ5pOm-1567244122581)(…/image/DjangoModel_12.png)]
(3).through_fields
仅在指定自定义中间模型时使用。 Django通常会确定要使用哪个中间模型字段以便自动建立多对多关系。 但是请考虑以下情况
from django.db import modelsclass Person(models.Model):name models.CharField(max_length50)class Group(models.Model):name models.CharField(max_length128)members models.ManyToManyField(Person,throughMembership,through_fields(group, person),)class Membership(models.Model):group models.ForeignKey(Group, on_deletemodels.CASCADE)person models.ForeignKey(Person, on_deletemodels.CASCADE)inviter models.ForeignKey(Person,on_deletemodels.CASCADE,related_namemembership_invites,)invite_reason models.CharField(max_length64)Membership有两个外键person和inviter这使得关系模糊不清Django无法知道使用哪一个。 在这种情况下您必须使用through_fields明确指定Django应使用哪些外键如上例所示。 through_fields接受2元组‘field1’‘field2’其中field1是定义ManyToManyField的模型的外键名称在本例中为groupfield2是外键的名称。 目标模型本例中的person。 如果中间模型上有多个外键到参与多对多关系的任何甚至两个模型则必须指定through_fields。 这也适用于使用中间模型时的递归关系并且模型有两个以上的外键或者您想要明确指定Django应该使用哪两个。 使用中间模型的递归关系总是被定义为非对称的 - 也就是说symmetricalFalse 因此存在“源”和“目标”的概念。 在这种情况下field1’将被视为关系的“源”field2’将被视为“目标”。 2.3 OneToOneField
一对一的关系。 从概念上讲这类似于具有unique True的ForeignKey但关系的“反向”一侧将直接返回单个对象。
这作为模型的主键是最有用的它以某种方式“扩展”另一个模型; 例如通过从子模型向父模型添加隐式一对一关系来实现多表继承。
需要一个位置参数与模型相关的类。 这与ForeignKey完全相同包括有关递归和惰性关系的所有选项。
如果没有为OneToOneField指定related_name参数Django将使用当前模型的小写名称作为默认值。
3. Meta
用来定义元数据除字段以外的别的数据常见的元数据
app_label如果你定义的Model不在app目录下的models.py中就需要指定该字段为app名称db_table自定义数据表名如果不指定默认用app名_model名db_tablespace指定某些数据库的表空间ordering指定排序集verbose_name:可读的名字verbose_name_pluralModel的复数形式