Django模型

Django 2018-06-12

一、模型

Django对各种数据库提供了很好的支持,Django为这些数据库提供了统一的调用API(即不管底层操作哪种数据库,我们只管模型对象操作即可,其实就是屏蔽掉数据库操作的差异性),这就可以根据不同的业务需求选择不同的数据库。

二、配置数据库

在工程目录下__init__.py文件

import pymysql
pymysql.install_as_MySQLdb()

安装pymysql: pip install pymysql

在工程目录下settings.py文件中,修改DATABASES

DATABASES = {
    'default': {
        # 修改为mysql
        'ENGINE': 'django.db.backends.mysql',
        # 链接数据库,并创建对应的数据库zyz
        'NAME': 'zyz',
        # 用户名
        'USER': 'root',
        # 密码
        'PASSWORD': '123456',
        # 主机
        'HOST': '127.0.0.1',
        # 端口号
        'POST': '3306'
    }
}

三、模型开发流程

  • 配置数据库(创建对应数据,数据库上述配置)
  • 定义模型类(一个模型类对应一个表单)
  • 生成迁移文件(python manage.py makemigrations)
  • 执行迁移文件,生成对应表单(python manage.py migrate)
  • 使用模型类进行增删改查

四、ORM

概述

O: 对象
R: 关系
M: 映射

任务

- 根据对象类型生成表结构;
- 将对象、列表的操作转换sql语句;
- 将sql语句查询到的结果转为对象、列表;

五、属性定义

概述

- Django根据属性的类型确定以下信息:
    当前选择的数据库支持字段的类型;
    渲染管理表单时使用的默认html控件;
    在管理站点最低限度的验证;
- Django的主键
    会为表增加自增长的主键列,每个模型只能有一个主键列;
    如果使用选项设置某属性为主键列后,则Django不会再生成默认的主键列;
- 属性命名规则:
    遵循标识符规则;
    由于Django的查询方式,不允许使用连续的下划线;

- 定义属性时
    需要字段类型,字段类型是被定义在django.db.models.fields目录下;
    为了方便使用,被导入到django.db.models中;
- 使用方式
    导入from django.db import models;
    通过models.field创建字段类型的对象,赋值给属性;

逻辑删除

对于重要数据都做逻辑删除,不做物理删除;
实现方法是定义isDelete属性,类型为BooleanField,默认值为False;

字段类型

- AutoField
    一个根据实际ID自动增长的IntegerField,通常不指定;
    如果不指定,一个主键字段将自动添加到模型中;
- CharField(max_length=字段长度)
    字符串,默认的表单样式TextInput;
- TextField
    大文本字段,一般超过4000使用,默认的表单控件是Textarea;
- IntegerField
    整数;
- DecimalField(max_digits=None, decimal_places=None)
    使用python的Decimal实例表示的十进制浮点数;
    DecimalField.max_digits: 位数总数;
    DecimalField.decimal_places: 小数点后的数字位数;
- FloatField
    用Python的float实例来表示的浮点数;
- BooleanField
    true/false 字段,此字段的默认表单控制是CheckboxInput;
- NullBooleanField
    支持null、true、false三种值;
- DateField([auto_now=False, auto_now_add=False])
    使用Python的datetime.date实例表示的日期;
    DateField.auto_now: 每次保存对象时,自动设置该字段为当前时间,默认是False;
    DateField.auto_now_add: 当对象第一次被创建时自动设置当前时间,它总是使用当前日期,默认是False;
    auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果;
- TimeField
    使用Python的datetime.time实例表示的时间,参数同DateField;
- DateTimeField
    使用Python的datetime.datetime实例表示的日期和时间,参数同DateField;
- FileField
    一个上传文件的字段;
- ImageField
    继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image;

字段选项(通过字段选项,可以实现对字段的约束)

- null
    如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False;
- blanke
    如果为True,则该字段允许为空白,默认值是 False;
    null是数据库范畴的概念,blank是表单验证证范畴的;
- db_column
    字段的名称,如果未指定,则使用属性的名称;
- db_index
    若值为 True, 则在表中会为此字段创建索引;
- default
    默认值;
- primary_key
    若为 True, 则该字段会成为模型的主键字段;
- unique
    如果为 True, 这个字段在表中必须有唯一值;

关系

- ForeignKey:一对多,将字段定义在多的端中
    格式: 对象.模型类小写_set
    示例: grade.students_set
- OneToOneField:一对一,将字段定义在任意一端中
    格式: 对象.模型类小写
    示例: grade.students
- 访问id
    格式: 对象.属性_id
    示例: student.sgrade_id
- ManyToManyField:多对多,将字段定义在两端中

六、定义模型步骤

1. 模型、属性、表、字段的关系

一个模型类在数据库中对应一个表单;
在模型类中定义的属性与表单字段对应;

2. 定义属性

3. 创建模型类

4. 元选项

- 在模型类中定义Mata类,用于设置元信息
- db_table属性
    定义数据表名,推荐使用小写字母,数据表名默认为项目名小写_类名;
- ordering属性
    对象的默认排序字段,获取对象的列表时使用;
    ordering = ['id'] 升序
    ordering = ['-id'] 降序
    ordering = ['sage'] 按sage升序
    注意: 排序会增加数据库的开销;
# 学生表students
class Students(models.Model):
    # 在没有添加主键时,它会在生成时自动添加主键
    # id          = models.IntegerField()
    s_name        = models.CharField(max_length=30)
    s_sex         = models.CharField(max_length=10)
    s_age         = models.IntegerField()
    isdel         = models.BooleanField(default=False)
    lastTime      = models.DateTimeField(auto_now=True)
    createTime    = models.DateTimeField(auto_now=True)

    # 元选项(元信息)
    class Meta:
        db_table= 'students'
        # ordering = ['id']
        ordering = ['sage']

七、模型成员

类属性

- objects管理器
    是Manager类型的一个对象,作用是与数据库交互;
    当定义模型类是没有指定管理器,则Django为模型创建一个名为objects的管理器;
- 自定义管理器
    当为模型指定模型管理器,Django就不在为模型类生成objects模型管理对象;
    studentsObj = models.Manager() # 自定义模型管理器
- 模型管理器作用
    模型管理器是Django的模型与数据库进行交互的接口;
    一个模型可以有多个模型管理器;
- 自定义管理器Manager类
    向着管理器中添加额外的方法;
    修改管理器返回的原始查询集(重写get_queryset())

自定义管理器Manager类

# 重写Students中的get_queryset()方法
class StudentsManager(models.Manager):
    def get_queryset(self):
        # 还是需要调用父类方法,在父类方法中获取到数据之后,再进行过滤
        return super(StudentsManager,self).get_queryset().filter(isdel=False)


# 学生表students
class Students(models.Model):
    # 自定义模型管理器
    studentObj1 = models.Manager()
    studentObj2 = StudentsManager()
    

# 使用1: Students.studentObj1.all()
# 使用2: Students.studentObj2.all()

八、模型查询之基本使用

查询集表示从数据库获取的对象集合。
查询集合可以有多个过滤器。
过滤器就是一个函数,基于所给的参数限制查询结果。
从SQL角度来说,查询集合与select等价,过滤器就像where条件。

查询集

- 在管理器上调用过滤器方法返回查询集;
- 查询集经过过滤器筛选后返回新的查询集,所以可以写出链式调用;
- 惰性执行(创建查询集不会带任何数据访问,直到调用数据时才会访问数据)

直接访问的情况

- 迭代
- 序列化
- 与if合用

过滤器(返回查询集)

- all() 返回查询集中所有数据(一条数据即一个对象)
- filter() 返回符合要求的数据
    filter(键=值)
    filter(键=值,键=值)
    filter(键=值).filter(键=值)
- exclude() 过滤掉符合条件的数据
- order_by() 排序
- values() 返回查询集中所有数据(一条数据即一个字典),返回一个列表

返回单个数据

- get() 返回一个满足条件的对象
    如果没有找到符合条件的对象,会引发'DoesNotExist'异常
    如果找到多个对象,会引发'MultipleObjectsReturned'异常
- count() 返回查询集的对象个数
- first() 返回查询集中的第一个对象
- last() 返回查询集中的最后一个对象
- exists() 判断查询集中是否有数据,有数据返回True

限制查询集

查询集返回列表,可以使用下标的方法进行限制,等同于sql语句中的limit语句;
例如: studentList = Students.objects.all()[0:5]
注意: 下标不能是负数

查询集缓存

- 每个查询集都包含一个缓存,来最小化的数据访问
- 在新建的查询集时,缓存首次为空,第一次对查询集求值,会发生数据缓存
- django会将查询出来的数据做一个缓存,并返回查询结果,以后查询直接使用查询集的缓存

九、模型查询之字段查询

概述

- 实现了sql中的where语句,作为方法filter()、excluede()、get()的参数
- 语法
    属性名称__比较运算符=值
- 外键
    属性名_id
- 转义
    like语句中使用%为了匹配占位
    filter(sname__contains='%')

比较运算符

- exact 判断(大小写敏感)
    filter(isdel=False)
- contains 是否包含(大小写敏感)
    studentList = Student.objects.filter(sname__contains='孙')
- startswith、endswith 以value开头或结尾(大小写敏感)
    studentList = Student.objects.filter(sname__startswith='孙')
备注: 
    以上四个前面加上i,表示不区分大小写;
    iexact、icontains、istartswith、iendswith

- isnull、isnotnull 是否为空
    filter(sname__isnull=False)
- in 是否包含在范围内
    studentList = Students.objects.filter(pk__in=[2,3,4,5,6])
- gt大于、gte大于等于、lt小于、lte小于等于
    studentList = Students.objects.filter(sage__gt=30)
- year、mouth、day、week_day、hour、minute、second 时间相关
    studentList = Student.objects.filter(lastTime__year=2018)
    
- 跨关联查询 (处理join查询)
    语法: 模型类名__属性名__比较符
    例如: 学生描述中带有'张三'的学生属于哪个班级
        grade = Grades.objects.filter(students__sbrief__contains='张三')
- 查询快捷 
    pk 代表主键(因为主键并不一定就是id字段)
    student = Students.objects.get(pk=3)

聚合函数

使用aggregate()函数返回聚合函数的值【sql中的函数使用】
例如: Avg()、Count()、Max()、Min()、Sum()
实例: 
    from django.db.models import Max
    maxAge = STudents.objects.aggregate(Max('sage'))

F对象

- 可以使用模型的A属性与B属性进行比较.
    例如: Grades.objects.filter(ggirlnum__gt=F('gboynum'))

- 支持F对象的算术运算
    例如: Grades.objects.filter(ggirlnum__gt=F('gboynum')+20)

Q对象

- 概述
    过滤器的方法中的关键字参数,条件为and模式
- 需求
    进行or查询
- 解决
    使用Q对象
- 例如
    studentList = Students.objects.filter(Q(pk__lte=3) | Q(sage__gt=50))
    studentList = Students.objects.filter(Q(pk__lte=3)  # 只有一个Q对象就用于匹配
    studentList = Students.objects.filter(~Q(pk__lte=3) # 取反 

本文由 zyz 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

楼主残忍的关闭了评论