模型是你的数据的唯一的、确定的信息源。 它包含你所储存数据的必要字段和行为。 通常,每个模型对应数据库中唯一的一张表。
①每个模型都是一个Python类,它们都是django.db.models.Model的子类。
②每一个模型属性都代表数据库中的一个字段。
AutoField:一个根据实际ID自动增长的IntegerField
BinaryField:一个用来存储原始二进制码的Field.
BooleanField:true/false 字段;默认表单挂件是一个CheckboxInput.
如果需要设置null 值,则使用NullBooleanField 来代替BooleanField。如果Field.default没有指定的话, BooleanField 的默认值是 None。
CharField:一个用来存储各种长度的字符串的字段;对应MySQL中的varchar数据类型。
必须接收一个额外的参数--max_length:字段的最大字符长度,将在数据库层和Django表单验证中起作用, 用来限定字段的长度.
DateField:使用Python的datetime.date实例表示的日期
DateTimeField:使用Python datetime.datetime实例表示的日期和时间
TimeField:使用Python datetime.time 实例表示的时间。
DateField/DateTimeField/TimeField 参数介绍:
auto_now-->每次保存对象时,自动设置该字段为当前时间,使用"最后一次修改"的时间戳;调用Model.save()时,该字段才会自动更新。
auto_now_add-->当对象第一次被创建时自动设置当前时间,使用创建时间的时间戳
DecimalField:用python中 Decimal 的一个实例来表示十进制浮点数.
有两个必须的参数:
max_digits-->位数总数,包括小数点后的位数;
decimal_places-->小数点后的数字位数
IntegerField:一个整数; 在Django所支持的所有数据库中,从 -2147483648 到 2147483647 范围内的值是合法的
PositiveIntegerField:值必须是正数或者零(0);从0到2147483647的值在Django支持的所有数据库中都是安全的。
SmallIntegerField:该字段值在 -32768 至 32767这个范围内对所有可支持的数据库都是安全的
BigIntegerField:一个64位整数;适合从-9223372036854775808到9223372036854775807的数字
SlugField:只能包含字母、数字、下划线或连字符,默认长度为50,通常用来作为短标签;通常它们是用来放在URL里的
TextField:大文本字段
EmailField:一个 CharField 用来检查输入的email地址是否合法。
URLField:一个CharField 类型的URL;不指定max_length,则使用默认值200
UUIDField:一个用来存储UUID的字段,使用Python的UUID类;数据库对应的是char(32)类型(注:PostgreSQL数据库中对应的数据类型是uuid)
primary_key除用AutoField的另外一个好的选择就是UUID。 数据库不会自动生成UUID,所以推荐使用default参数
FileField:上传文件字段;会在数据库中创建一个默认最大长度为100字符的varchar 列
有两个可选参数:
upload_to-->该属性提供设置上传目录和文件名的方式
storage-->一个Storage 对象,用于你的文件的存取
注:需要在settings文件中设置MEDIA_ROOT和 MEDIA_URL
当访问模型上的FileField时,将获得FieldFile的实例作为访问基础文件的代理。
FieldFile.name-->文件名,包括相关FileField的Storage根目录的相对路径。
FieldFile.size-->文件大小;底层Storage.size()方法的结果
FieldFile.url-->该文件的URL,它是一个只读属性,通过调用底层Storage类的url()方法得到
FieldFile.open(mode='rb')-->在指定的mode中打开或重新打开与该实例关联的文件
FieldFile.close()-->该方法像标准的Pythonfile.close() 方法,并关闭相关文件
FieldFile.save(name, content, save=True)-->这个方法会将文件名以及文件内容传递到字段的storage类中,并将模型字段与保存好的文件关联
ImageField:继承FileField的所有属性和方法,但还对上传的对象进行校验,确保它是个有效的图片
额外可选参数:height_field 使用图像高度填充字段的名称;width_field 使用图像宽度填充字段的名称
注:需要Pillow库。
ForeignKey -->定义多对一关系;class ForeignKey(to, on_delete, **options)
ForeignKey 会自动创建数据库索引;可以通过设置db_index 为False 来取消。
在多对一中多的模型中设置ForeignKey;在幕后,Django 会在字段名上添加"_id" 来创建数据库中的列名。
若要创建递归关联关系 — 一个对象与自己具有多对一关联关系 — 请使用models.ForeignKey('self',on_delete=models.CASCADE)
参数介绍:
on_delete-->当删除由ForeignKey引用的对象时,Django将模拟由on_delete参数指定的SQL约束的行为
related_name-->这个名称用于让关联的对象反查到源对象;如果不想让Django 创建一个反向关联,请设置'related_name' 为 '+'
related_query_name-->这个名称用于目标模型的反向过滤。默认值为related_name( 如果设置了该值),否则默认为模型名称
to_field-->关联对象的字段名称。 默认地,Django 使用关联对象的主键。 如果引用其他字段,该字段必须具有unique=True
ManyToManyField -->定义多对多关系;class ManyToManyField(to, **options)
在哪个模型中设置 ManyToManyField 并不重要,在两个模型中任选一个即可 —— 不要两个模型都设置
在幕后,Django 创建一个中间表来表示多对多关系。 默认情况下,此表名称是使用多对多字段的名称以及包含它的模型的表名生成的(如author_books)。此表有3个字段,id、
参数介绍:(related_name、related_query_name同ForeignKey)
db_table -->指定中介表的名称
through-->手动指定想要使用的中介表;此选项最常见的用途是,希望将额外数据与多对多关系相关联。
through_fields-->只能在指定了自定义中间模型的时候使用;接受一个二元数组 ('field1', 'field2'),field1是定义多对多关系的模型的名称,field2是目标模型的名称
OneToOneField -->定义一对一关系;class OneToOneField(to, on_delete, parent_link=False, **options)
在幕后,Django 会在字段名上添加"_id" 来创建数据库中的列名。
当对象想以某种方式“扩展”另一个对象时,在对象的主键上创建一对一关系是最有用的。
例如,通过在子模型中添加指向父模型的隐式一对一关系来实现多表继承。
1,null -->如果为True,Django将在数据库中把空值存储为NULL。 默认为False。
2,blank -->如果为True,该字段允许为空值, 默认为False。
null纯粹是数据库范畴,指数据库中字段内容是否允许为空,而 blank 是表单数据输入验证范畴的。 如果一个字段的blank=True,表单的验证将允许输入一个空值。 如果字段的blank=False,该字段就是必填的
3,choices -->由二项元组构成的一个可迭代对象(如列表或元组),用来给字段提供选择项;每个元组中的第一个元素是将被存储在数据库中的值
4,default -->字段的默认值。 可以是一个值或者可调用对象。 如果可调用 ,每个新对象创建时它都会被调用
5,help_text -->表单部件额外显示的帮助内容。 即使字段不在表单中使用,它对生成文档也很有用。
6,primary_key -->如果为True,那么这个字段就是模型的主键。如果没有指定任何一个字段的primary_key=True,Django 就会自动添加一个主键:id = models.AutoField(primary_key=True)
7,unique -->如果为True, 则这个字段在整张表中必须是唯一的。
8,db_column -->数据库中用来表示该字段的列名称。 如果未指定,那么Django将会使用字段名作为列名.
9,db_index -->如果True,将为该字段创建一个数据库索引
10,verbose_name -->一个字段的可读性更高的名称。 如果没有给定自述名,Django会根据字段属性名,将下划线转换为空格自动创建它
11,error_messages -->覆盖字段引发的异常中的默认信息;传递的是一个字典,其键为你想覆盖的错误信息
12,validators -->可以为字段提供一个验证函数的列表
使用内部的class Meta 定义模型的元数据。
模型元数据是“任何不是字段的数据”,比如排序选项(ordering),数据库表名(db_table)或者人类可读的单复数名称(verbose_name 和verbose_name_plural)等
abstract = True, 表示模型是抽象基类
proxy = True,表示模型是代理模型
db_table = 'music_album',设置模型所用的数据表的名称(默认的数据库表名为appName_modelName)
ordering = ['-pub_date'],设置对象默认的排序依据,有"-"号表示倒序排序
unique_together = ("driver", "restaurant"),设置联合唯一
indexes = [models.Index(fields=['last_name', 'first_name']), ],在模型上定义的索引的列表
verbose_name = "pizza",对象的一个易于理解的名称,为单数。
verbose_name_plural = "stories",对象复数形式的名称,若没有设置,Django 会使用 verbose_name + "s"。
objects-->模型最重要的属性是Manager;它是Django 模型进行数据库查询操作的接口,还用于从数据库提取实例。 如果没有自定义Manager,则默认的名称为objects。 Managers 只能通过模型类访问,而不能通过模型实例访问。
pk属性-->是模型主键字段属性的别名
__str__() :一个Python的“魔法方法”,返回对象的unicode格式“表示”
get_absolute_url() :它告诉Django 如何计算一个对象的URL;任何具有唯一标识自己的URL 的对象都应该定义这个方法。
Model.save(force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None)
当你调用save() 时,Django 使用下面的算法:
如果对象的主键属性为一个求值为True 的值(非None 值或非空字符串),Django将执行UPDATE。
如果对象的主键属性没有设置或者UPDATE没有更新任何记录,Django将执行INSERT。
//覆盖预定义的模型方法(注:批量操作中被覆盖的模型方法不会被调用)
def save(self, *args, **kwargs):
do_something()
super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
do_something_else()
Django中自定义的模型类应该继承自django.db.models.Model
在Django 中有3种风格的继承:
①抽象基类-->通常,你只想使用父类来持有一些信息,你不想在每个子模型中都敲一遍; 这个类永远不会单独使用
②多表继承-->如果你继承一个已经存在的模型且想让每个模型具有它自己的数据库表
③代理模型-->如果你只是想改变一个模型Python 级别的行为,而不用修改模型的字段
1,抽象基类:
抽象化类,将一些共有信息放进一个模型中,并在 Meta类中设置 abstract=True , 这个模型就不会被用来创建任何数据表。 取而代之的是,当它被用来作为其他model的基类时,它的字段将被加入那些子类中。 如果抽象基类和它的子类有相同的字段名,那么将会出现error
Meta类中的abstract=True是无法继承的,其他选项都能继承
2,多表继承
继承关系在子 model 和它的每个父类之间都添加一个链接 (通过一个自动创建的 OneToOneField来实现)。
父类里面的所有字段在 子model中也是有效的,只不过没有保存在数据库中的子model表中
//在父类上使用parent_link=True声明自己的OneToOneField来覆盖隐式创建的OneToOneField
place_ptr = models.OneToOneField(
Place, on_delete=models.CASCADE,
parent_link=True,
)
3,代理模型
需求:只想更改 model 在 Python 层的行为实现。比如:更改默认的 manager ,或是添加一个新方法。
方案:为原始模型创建一个代理 。 你可以创建,删除,更新代理 model 的实例,而且所有的数据都可以像使用原始 model 一样被保存。
声明代理 model :继承自原始model,设置Meta类中 proxy 的值为 True
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 操作同一个数据表!
Manager是Django的模型进行数据库查询操作的接口。 Django 应用的每个模型都拥有至少一个Manager。
同一个模型可以使用多个管理器
默认情况下,Django 为每个模型类添加一个名为objects的Manager。
重命名Manager:new_manager_name = models.Manager()
自定义管理器:
需求:向Manager类中添加额外的方法,或者修改Manager返回的原始QuerySet
方案:自定义Manager,方法是继承Manager 基类并实例化你的自定义Manager
可以通过重写get_queryset()方法来覆盖Manager自带的QuerySet。 get_queryset()应该返回一个带有你需要的属性的QuerySet。
from django.db import models
class BookManager(models.Manager):
def create_book(self, title):
book = self.create(title=title)
# do something with the book
return book
class Book(models.Model):
title = models.CharField(max_length=100)
objects = BookManager()