模型类
介绍
每个模型类都可以被映射为数据库中的一个数据表,类类属性被映射为数据字段,除此之外,数据库表的主键、外键、约束等也通过类属性完成定义
模型类属性
属性 | 描述 |
---|---|
AutoField | AutoField 字段,一个自动递增的整型字段,添加记录时会自动增长,通常会用于充当数据表的主键。 django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。 默认创建的主键列属性名称为id,可以使用pk代替,pk全拼为primary key。注意1:pk是主键的别名,若主键名为id2,那么pk是id2的别名。 注意2:如果不想django帮你自动创建主键,自己手动创建的话,需要加上primary_key=True,数据库有且只有一个主键 |
IntegerField | 用于保存一个整数 |
SmallIntegerField | 类似于 IntegerField 但只具有较小的输入范围,具体范围依赖于所使用的数据库 |
BigIntegerField | 64位整型字段 |
BinaryField | 二进制数据字段 只能通过 types 对其赋值 |
FloatField | 浮点型字段 定义本字段时必须传入 max_digits 和decimal_places 参数 用于定义总位数(不包括小数点和符号)和小数位数 |
DecimalField | 十进制浮点数 max_digits 参数表示总位 decimal_places 参数表示小数位数 |
CommaSeparatedIntegerField | 用于存放逗号分隔的整数值 相较与普通的 CharField, 它有特殊的表单数据验证要求 |
DurationField | 存储时间周期, 用 Python 的 timedelta 类型构建 |
EmailField | 一个带检查 Email 合法性的CharField |
FileField | 用于上传图片,需定义upload_to参数, 如果路径不存在,会自动创建 使用本字段需安装pip install pillow图片库;设置upload_to 到某个目录下, 需要在settings.py中配置多媒体文件路径: MEDIA_ROOT = os.path.join(BASE_DIR, "uploads") |
FilePathField | 按目录限制规则选择文件 定义本字段必须传入参数 path ,用于限制目录 |
ImageField | 用于上传图片并验证图片合法性,需定义upload_to参数, 如果路径不存在,会自动创建 使用本字段需安装pip install pillow图片库;设置upload_to 到某个目录下, 需要在settings.py中配置多媒体文件路径: MEDIA_ROOT = MEDIA_ROOT = os.path.join(BASE_DIR, "uploads") |
IPAddressField | 一个字符串形式的IP地址 例如: 192.23.250.2 |
NullBooleanField | 类似于 BooleanField, 但比其多一个None选项 |
PhoneNumberField | 带有美国风格的电话号码校验的 CharField 格式为 XXX-XXX-XXXX |
SlugField | 只包含字母、数字、下划线和连字符的输入字段 通常用于URL |
URL | 用于保存URL |
USStateField | 美国州名的缩写字段,由两个字母组成 |
XMLField | XML字段 是具有XML合法验证的TextField |
OneToOneField | 一对一,本质上就是ForeignKey加unique |
ForeignKey | 一对多 |
ManyToManyField | 多对多(很少是使用,局限性太强,一般手动创建) 手动创建关系表,再借用through函数绑定到关系表,关系信息的维护仍是手动
|
BooleanField | 布尔字段 |
CharField | CharField |
TextField | 大容量文本字段 |
DateField | 日期字段
|
DateTimeField(常用此字段) | 类似于 DateField,但同时支持于时间的输入
|
TimeField | 时间字段,类似于 DateTimeField
|
模型类属性参数
参数 | 描述 |
---|---|
max_length | 定义字符的长度,一般用于CharField |
primary_key | 主键(一个模型只能有一个主键,如果不想手动生成,不需要使用该字段) |
null | 对于数据库,存入数据库是null |
blank | 针对于表单验证 |
choices | 定义字段的可选值 本字段的值应该是一个包含二维元素的元组 元组的每个元素的第一个值是实际存储的值, 第二个值是HTML页面进行选择时显示的值 |
default | 默认值 |
help_text | HTML页面中输入控件的帮助字符串 |
unique | 唯一,如果设置了unique,就不需要设置db_index,因为其就是表示唯一索引 |
db_index | 若值为True,则在表中会为此字段创建索引 默认False |
db_column | 字段的名称 如果未指定,则使用属性的名称 |
db_contraint | 表与表仅仅逻辑关联,注意容易出现脏读, 保留跨表查询的便利(双下划线跨表查询```),但是不用约束字段了 与null=True, blank=True,on_delete=models.SET_NUL连用才生效 |
on_delete | CASCADE:这就是默认的选项,级联删除。 PROTECT: 保护模式,如果采用该选项,删除的时候,会抛出ProtectedError错误。 SET_NUL: 置空模式,删除的时候,外键字段被设置为空,前提就是blank=True, null=True`,定义该字段的时候,允许为空。 SET_DEFAULT: 置默认值,删除的时候,外键字段设置为默认值,所以定义外键的时候注意加上一个默认值。 SET(): 自定义一个值,该值当然只能是对应的实体了 |
limit_choices_to | 限制关联字段的对象范围 从上面的model字段可以看出, class_teacher字段限制了选择条件:{'depart__title': '教质部'}, 即在选择班主任的时候,只能选择关联班主任的外键表depart中名称为教质部的数据 ManyToMany字段的limit_choices_to指向了 {'depart__title__in':['xx','xx']} 一个列表,那在前端中只能选择这个列表中的数据 class ClassList(models.Model): |
related_name | 反向查询时用到,就不需要小写表名_set这么复杂了, |
unique_for_date | 数据库中字段【日期】部分是否可以建立唯一索引 |
unique_for_month | 数据库中字段【月】部分是否可以建立唯一索引 |
unique_for_year | 数据库中字段【年】部分是否可以建立唯一索引 |
editable | Admin中是否可以编辑 |
validators | 自定义错误验证(列表类型),从而定制想要的验证规则 from django.core.validators import RegexValidator |
元选项 (Meta类)
属性 | 描述 |
---|---|
abstract | 标识本类是否为抽象基类,如果为抽象基类,将不生成新表,一般做基表用 True or False |
app_label | 定义本类所属的应用 |
db_table | 映射的数据库表名,例如: db_table=‘moments’ 如果在Meta中不提供 db_table 字段,则Django 会为模型自动生成数据表名,生成的格式为“应用名_模型名”,例如:应用app的模型UserInfo的默认数据表名为 app_UserInfo |
db_tablespace | 映射的表空间名称 表空间的概念只在某些数据库如 Oracle 中存在,不存在表空间的概念的数据库将忽略此字段 |
default_related_name | 定义本模型的反向关系引用名称,默认与模型名一致 |
get_latest_by | 定义按哪个字段值排列以获得模型的开始或结束记录 本属性值通常指向一个日期或整型的模型字段 |
managed | True or False 定义 Django的 manage.py 命令行工具是否管理本模型。 默认为 True,若将其设置为 False,则运行 python manage.py migrate 时将不会在数据库中生成本模型的数据表,所以需要手工维护数据库的定义 |
order_with_respect_to | 定义本模型可以按照某外键引用的关系排序 |
order | 本模型记录的默认排序字段,可以设置多个字段,默认以升序排列, 若以降序排列则表示要在字段名前加负号("-") 例如:定义 user_name 字段升序 和 pub_date 降序排列 order = ['user_name','-pub_date'] |
dafault_permissions | 模型操作权限 默认为 default_permisstions=('add','change','delete') |
proxy | True or False 本模型及所有继承自本模型的子模型是否为代理模型 |
required_db_features | 定义底层数据库所必须具备的特性 例如: required_db_features=['gis_enabled'] 只将本数据模型生成在满足 gis_enabled 特性的数据库中 |
required_db_vendor | 定义底层数据库类型 比如 SQLite,PostgreSQL,MySQL,Oracle 如果定义了本属性,则模型只能在其声明的数据库中被维护 |
unique_together | 用来设置的不重复的字段组合,必须唯一(可以将多个字段做联合唯一) 注意:django将弃用该字段,推荐在django2.2以上使用UniqueConstraints |
UniqueConstraint | 联合唯一(django2.2以上使用UniqueConstraints) class Meta: constraints = [ # 联合唯一 models.UniqueConstraint(fields=['name', 'title'], name='unique_name') ] |
index_together | 定义联合索引的字段,可以设置多个 例如: index_together = [["pub_date","deadline"],] |
verbose_name | 指明一个易于理解和表述的单数形式的对象名称。 如果这个值没有被设置,则Django将会使用该model的类型的分词形式作为它的对象表述名,即 CamelCase 将会被转换为camel case |
verbose_name_plural | 指明一个易于理解和表述的复数形式的对象名称 |
proxy
介绍
在不动原型的基础上,代你操作完成一些功能。如现需求通过手机号来作为验证条件,那就得增加字段,扩展用户模型了。
代理模型不会改变原数据,只是在原有的基础上增加一些方法,使其更完善,代理不能添加字段,只能增加操作方法。
Proxy模型
from django.db import models
#导入自带的用户模型,给代理继承
from django.contrib.auth.models import User
from django.core import validators
# 定义一个Person类代理继承自User
class Person(User):
telephone = models.CharField(max_length=11,validators=[validators.RegexValidator(r'1[3-9]\d{9}',message='请输入正确的手机号')])
#在Meta中设置proxy=True,表示不会影响原数据结构
class Meta:
#说明Person是User的代理类
proxy = True
比如想要获取黑名单,取决于表中的is_active
如果想方便的获取所有黑名单的人,那么就可以通过,Person.get_blacklist()就可以获取到。并且User.object.all()和Person.objects.all()是等价的。
因为都是从User这个模型中获取所有的数据。
class Person(User):
telephone = models.CharField(max_length=11,validators=[validators.RegexValidator(r'1[3-9]\d{9}',message='请输入正确的手机号')])
class Meta:
#说明Person是User的代理类
proxy = True
# 获取黑名单 来源取决active
@classmethod
def get_blacklist(self):
return self.objects.filter(is_active=False)
CheckConstraint(条件约束)
条件约束确保一个模型实例只有满足一定的规则条件后才被创建,不满足条件的数据不会存入到数据库。下例增加了一个对员工年龄的约束,只有大于18岁的才能注册。
from django.db import models
# Create your models here.
class Text_one(models.Model):
title = models.CharField(max_length=225)
name = models.CharField(max_length=225, db_index=True)
count = models.IntegerField(default=100)
class Meta:
constraints = [
# count大于18才能保存
models.CheckConstraint(check=models.Q(count__gte=18), name='age__gte_18')
]
其他操作
模型中自定义图片和文件上传路径
Django模型中的ImageField和FileField的upload_to选项是必填项,其存储路径是相对于MEIDA_ROOT而来的。然而我们可能希望动态定义上传路径,比如把文件上传到每个用户名下的文件夹里,并对上传文件重命名,这时我们可以定义一个user_directory_path方法。
from django.db import models
from django.contrib.auth.models import User
import uuid
import os
# Create your models here.
def user_directory_path(instance, filename):
ext = filename.split('.')[-1]
filename = '{}.{}'.format(uuid.uuid4().hex[:10], ext)
# return the whole path to the file
return os.path.join(instance.user.id, "avatar", filename)
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
avatar = models.ImageField(upload_to=user_directory_path, verbose_name="头像")
Django模型的Manager方法
Django模型自带models.Manager方法,可以简化我们的代码。如下面案例中,我们可以使用Person.objects.all()查询到所有人,而Person.authors.all和Person.editors.all()只返回所authors和editors。
class AuthorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(role='A')
class EditorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(role='E')
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor'))))
objects = models.Manager()
authors = AuthorManager()
editors = EditorManager()
Django模型的save方法重写
在很多应用场景中我们需要重写django模型的save方法,比如本例中我们希望根据title生成slug,并在一个对象数据save完成后做其它事情(比如发送邮件或发送信号),我们可以按如下代码重写django模型的save方法,非常容易。
from django.template.defaultfilters import slugify
class Article(models.Model):
...
def save(self, *args, **kwargs):
if not self.slug or not self.id:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
Django高级模型结构示例
from django.db import models
from django.urls import reverse
# 自定义Manager方法
class HighRatingManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(rating='1')
class Product(models.Model):
# CHOICES选项
RATING_CHOICES = (
("1", 'Very good'),
("2", 'Good'),
("3", 'Bad'),
)
# 数据表字段
name = models.CharField('name', max_length=30)
rating = models.CharField(max_length=1, choices=RATING_CHOICES)
# MANAGERS方法
objects = models.Manager()
high_rating_products =HighRatingManager()
# META类选项
class Meta:
verbose_name = 'product'
verbose_name_plural = 'products'
# __str__方法
def __str__(self):
return self.name
# 重写save方法
def save(self, *args, **kwargs):
do_something()
super().save(*args, **kwargs)
do_something_else()
# 定义绝对路径
def get_absolute_url(self):
return reverse('product_details', kwargs={'pk': self.id})
# 定义其它方法
def do_something(self):
参考文章
(20条消息) Django-模型model及属性_帅的一库的博客-CSDN博客_django models 属性https://blog.csdn.net/screenswindow/article/details/110222227(20条消息) Django--(2)模型(Model)属性与参数整理_Mikowoo007的博客-CSDN博客_django model 参数https://blog.csdn.net/Mikowoo007/article/details/98203653Django基础篇 03- Models的属性与字段 - 捞铁 - 博客园 (cnblogs.com)https://www.cnblogs.com/hehaheha/p/15221083.html(20条消息) Python之django框架模型(models)详解_嫣夜来的博客-CSDN博客_models pythonhttps://blog.csdn.net/qq_41865652/article/details/106332865?utm_source=app&app_version=5.2.1&code=app_1562916241&uLinkId=usr1mkqgl919blenDjango-ORM之ManyToManyField的使用-多对多关系 - Aries-X - 博客园 (cnblogs.com)https://www.cnblogs.com/jjzz1234/p/11607940.html