django中Models常用的字段及属性介绍

模型类

介绍

每个模型类都可以被映射为数据库中的一个数据表,类类属性被映射为数据字段,除此之外,数据库表的主键、外键、约束等也通过类属性完成定义

模型类属性

属性 描述
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_digitsdecimal_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函数绑定到关系表,关系信息的维护仍是手动

class Book(models.Model):

   title = models.CharField(max_length=32)

class Author(models.Model):

   name = models.CharField(max_length=32)

   books = models.ManyToManyField(Book, through='Book_Author')

class Book_Author(models.Model):

   book = models.ForeignKey(Book, on_delete=models.CASCADE)

   author = models.ForeignKey(Author, on_delete=models.CASCADE)

   date = models.DateField()

     

# 添加关系

#方式一:

m1 = BookAuthor(author=author对象,book=book对象)

#方式二(可以不绑定):

m2 = BookAuthor.objects,create(author=author对象,book=book对象)

BooleanField 布尔字段
CharField CharField
TextField 大容量文本字段
DateField

日期字段  

auto_now 当对象被保存时,将该字段的值设置为当前时间
auto_now_add 当对象被首次创建时,将该字段的值设置为当前时间

DateTimeField(常用此字段)

类似于 DateField,但同时支持于时间的输入

auto_now 当对象被保存时,将该字段的值设置为当前时间
auto_now_add 当对象被首次创建时,将该字段的值设置为当前时间

TimeField

时间字段,类似于 DateTimeField
但只能表达和输入时间

auto_now 当对象被保存时,将该字段的值设置为当前时间
auto_now_add 当对象被首次创建时,将该字段的值设置为当前时间

模型类属性参数

参数 描述
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):
    """
    班级表
    """
    school = models.ForeignKey(verbose_name='校区', to='School', on_delete=models.CASCADE)
 
  
    class_teacher = models.ForeignKey(verbose_name='班主任', to='UserInfo', related_name='classes',
                                      on_delete=models.CASCADE, limit_choices_to={'depart__title': '教质部'})
    tech_teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo', related_name='teach_classes',
                                           limit_choices_to={'depart__title__in': ['Python教学部', 'Linux教学部']})
    memo = models.TextField(verbose_name='说明', null=True, blank=True)

related_name

反向查询时用到,就不需要小写表名_set这么复杂了,

unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
editable Admin中是否可以编辑
validators

自定义错误验证(列表类型),从而定制想要的验证规则

from django.core.validators import RegexValidator
from django.core.validators import EmailValidator,URLValidator,DecimalValidator,
MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
如:
test = models.CharField(
    max_length=32,
    error_messages={
    'c1': '优先错信息1',
    'c2': '优先错信息2',
    'c3': '优先错信息3',
},
validators=[
    RegexValidator(regex='root_\d+', message='错误了', code='c1'),
    RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
    EmailValidator(message='又错误了', code='c3'), ]
)

元选项 (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

用来设置的不重复的字段组合,必须唯一(可以将多个字段做联合唯一)
例如:unique_together = (("user_name","pub_date"),)
定义了每个 user_name 在同一个 pub_date 中只能有一条数据表记录
因为 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

     (69条消息) djnago---外键的一些操作_骑台风走的博客-CSDN博客https://blog.csdn.net/qq_52385631/article/details/122851343?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166348141116782248582531%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=166348141116782248582531&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-2-122851343-null-null.nonecase&utm_term=%E7%BA%A7%E8%81%94&spm=1018.2226.3001.4450

猜你喜欢

转载自blog.csdn.net/qq_52385631/article/details/126912695