Django MVT之M

2022-11-15 21:15:26 浏览数 (1)

在Django MVC概述和开发流程中已经讲解了Django的MVT开发流程,本文重点对MVT中的模型(Model)进行重点讲解。

配置MySQL数据库

确保已经安装了操作mysql的包。

python2安装mysql-python

代码语言:javascript复制
pip install mysql-python

python3安装pymysql

代码语言:javascript复制
pip3 install pymysql

python3安装好pymysql后,需要在与settings.py同级的目录下的__init__.py中加入以下内容

代码语言:javascript复制
import pymysql
pymysql.install_as_MySQLdb()

修改settings.py中的DATABASES,然后重新执行迁移。

代码语言:javascript复制
DATABASES = {
    'default': {
        #'ENGINE': 'django.db.backends.sqlite3',
        #'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        # MySQL引擎
        'ENGINE': 'django.db.backends.mysql',
        # 数据库名
        'NAME': 'school',
        # 用户名
        'USER': 'root',
        # 密码
        'PASSWORD': 'mysql',
        # 连接的mysql的地址
        'HOST': 'localhost',
        # MySQL端口
        'PORT': 3306,
    }
}

注:Django框架只会自动生成数据表,不会生成数据库,所以需要手动创建数据库。

字段类型

Django中每个模型类都会被映射为数据表,而模型类属性则被映射为数据表中的字段。所有数据字段的属性都必须继承自抽象类django.db.models.Field,开发者可以继承该抽象类来定义自己的字段类型,当然也可以使用Django自带的一系列Field子类。

使用时,需引入django.db.models包,常用字段类型如下:

字段类型

描述

AutoField

根据实际ID自动增长的整数字段,通常不需要直接使用,Django会自动生成ID字段并且自动增长。

BooleanField

布尔字段,值为True或False。

NullBooleanField

支持Null、True、False三种值。

CharField(max_length=None)

字符串varchar,参数max_length表示最大字符个数。

TextField

大文本字段,一般超过4000个字符时使用。

IntegerField

整数

DecimalField(max_digits=None, decimal_places=None)

十进制浮点数。参数max_digits表示总位,参数decimal_places表示小数位数。

FloatField

FloatField使用的是Python内部的 float 类型,而DecimalField使用的是Python的 Decimal类型。

DateField(auto_now=False, auto_now_add=False)

日期。1)参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于”最后一次修改”的时间戳,它总是使用当前日期,默认为false。2) 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false。3)参数auto_now_add和auto_now是相互排斥的,组合将会发生错误。

TimeField

时间,参数同DateField。

DateTimeField

日期时间,参数同DateField。

FileField

上传文件字段。

ImageField

继承于FileField,对上传的内容进行校验,确保是有效的图片。

更加完整的介绍参考Django 1.8.2 中文文档

字段选项

通过选项实现对字段的约束,常用选项如下:

选项

描述

default

字段默认值

primary_key

主键约束。默认值是False,若为True,则该字段会成为模型的主键字段,一般作为AutoField的选项使用。

unique

唯一约束。默认值是False,如果为True, 这个字段在表中必须有唯一值。

db_index

默认值是False。若值为True, 则在表中会为此字段创建索引。

db_column

字段的名称。如果未指定,则使用属性的名称。

null

默认值是False,如果为True,表示允许为空。

blank

默认值为False。如果为True,则该字段允许为空白。注意它与null不同。null纯粹是数据库范畴的概念,而blank是数据验证范畴(后台管理表单)的。如果字段设置blank=True,表单验证时将允许输入空值。如果字段设置blank=False,则该字段为必填。

更加完整的介绍参考Django 1.8.2 中文文档 注:当修改模型类之后,如果添加的选项不影响表的结构,则不需要重新做迁移。其中选项default和blank不影响表结构。

查询

函数

Django通过模型的objects对象实现模型数据查询,通过模型类.objects.函数调用如下函数来实现对数据库的查询。

函数名

功能

返回值

说明

get

返回表中满足条件的一条且只能是一条数据。

模型类对象

参数为查询条件。1) 如果查到多条数据,则抛异常MultipleObjectsReturned。2)查询不到数据,则抛异常DoesNotExist。

all

返回模型类对应表格中的所有数据。

QuerySet对象

aggregate 无参数

filter

返回表中满足条件的数据。

QuerySet对象

参数为查询条件。

exclude

返回表中不满足条件的数据。

QuerySet对象

参数为查询条件。

order_by

对查询结果进行排序。

QuerySet对象

参数为需要排序的字段。order_by('age')表示通过年龄升序排序order_by('-age')表示通过年龄降序排序

返回值为QuerySet对象的多个函数可以连接在一起查询,比如StudentInfo.objects.filter(age=18).exclude(school=’北京大学’)查询所有18岁不是北京大学的学生。

查询集(QuerySet对象)

调用all, filter, exclude, order_by这些函数会返回一个查询集(QuerySet对象),查询集有以下特性:

  • 惰性查询:只有在实际使用查询集中的数据的时候才会发生对数据库的真正查询。
  • 缓存: 当使用的是同一个查询集时,第一次使用的时候会发生实际数据库的查询,然后把结果缓存起来,之后再使用这个查询集时,使用的是缓存中的结果。

可以对一个查询集进行取下标或切片操作,切片操作会产生一个新的查询集。与python的列表不同的是,下标不允许为负数。

谓词

Django的查询条件是一种独特的字段查询表达方式,表现形式为:

字段名称__谓词=值

即用‘双下划线连接的字段名称和谓词’来表示查询的条件。Django谓词列表如下:

谓词

含义

示例

等价的SQL语句(为了便于书写,表名定为students)

exact

精确等于

StudentInfo.objects.filter(id__exact=1)

selcet * from students where id = 1

iexact

大小写不敏感的等于

StudentInfo.objects.filter(name__iexact=‘Bob’)

select * from students where lower(name) = ‘bob’

contains

模糊匹配

StudentInfo.objects.filter(name__contains=’蔡’)

select * from students where name like ‘%蔡%’

in

包含

StudentInfo.objects.filter(age__in=18, 20, 21)

select * from students where age in (18, 20, 21)

gtgteltlte

大于大于等于小于小于等于

StudentInfo.objects.filter(age__gt=18)

select * from students where age > 18

startswith

以…开始

StudentInfo.objects.filter(name__startswith=’周’)

select * from students where name like ‘周%’

endswith

以…结尾

StudentInfo.objects.filter(name__startswith=’伦’)

select * from students where name like ‘%伦’

range

在…范围内

StudentInfo.objects.filter(age__range=(18, 30))

select * from students where age between 18 and 30

yearmonthdayweek_day

年月日星期

StudentInfo.objects.filter(birthday__year=1996)

select * from students where birthday between ‘1996-1-1 0:0:0’ and ‘1996-12-31 23:59:59’

isnull

是否为空

StudentInfo.objects.filter(birthday__isnull=True)

select * from students where birthday is null

注:exact谓词可以省略。即id__exact=1可以简写为id=1

F对象

用于模型类A属性与B属性进行比较,使用之前需要导入F类。

代码语言:javascript复制
from django.db.models import F

# 查询女生人数大于男生人数的班级
Grades.objects.filter(girlnum_gt=F('boynum'))   
# F对象支持算术运算
# 查询女生人数大于男生人数 * 2的班级 QuerySet对象
Grades.objects.filter(girlnum_gt=F('boynum') * 2)

Q对象

用于查询时指定条件之间的逻辑关系。可以对Q对象进行& | ~操作,表示SQL语句中的逻辑运算符not and or,使用之前需要导入Q类。

代码语言:javascript复制
from django.db.models import Q

# 查询id大于3且学校为北京大学的学生
StudentInfo.objects.filter(Q(id__gt=3) & Q(school='北京大学')
StudentInfo.objects.filter(id__gt=3, school='北京大学')         # and操作可以这么写

# 查询id大于3或者学校为北京大学的学生
StudentInfo.objects.filter(Q(id__gt=3) | Q(school='北京大学')
                           
# 查询id不等于3的学生
StudentInfo.objects.filter(~Q(id__gt=3))

聚合

对QuerySet对象调用aggregate方法表示 对查询结果进行聚合操作,返回的是一个字典,使用前需导入相应的聚合类。

代码语言:javascript复制
from django.db.models import Sum,Count,Max,Min,Avg

# 查询所有学生的数量
StudentInfo.objects.all().aggregate(Count('id'))
# 查询所有学生年龄总数
StudentInfo.objects.all().aggregate(Sum('age'))
# 查询所有学生平均
StudentInfo.objects.all().aggregate(Avg('age'))

可以不使用聚合类直接在QuerySet对象调用count方法,返回值是一个整数

代码语言:javascript复制
# 查询所有学生的数量
StudentInfo.objects.all().count()

关联查询

一对多关系
代码语言:javascript复制
# 学校类-学生类
# 定义在多的类(学生类)中
school = models.ForeignKey()

在一对多关系中,一对应的类简称一类,多对应的类简称做多类,多类中定义的建立关联的类属性叫做关联属性。

由一类对象查询多类:

代码语言:javascript复制
# 查询所用数据
一类对象.多类名小写_set.all()

由多类对象查询一类:

代码语言:javascript复制
# 查询多类对象对应的一类
多类对象.关联属性  
# 查询多类对象对应的一类特定属性,比如id
多类对象.关联属性_id

通过多类的条件查询一类的数据:

代码语言:javascript复制
一类名.objects.filter(多类名小写__多类属性名__条件名)

通过一类的条件查询多类的数据:

代码语言:javascript复制
多类名.objects.filter(关联属性__一类属性名__条件名)
多对多关系
代码语言:javascript复制
# 体育新闻类-国际新闻类
# 定义在哪个类中都可以
models.ManyToManyField()
一对一关系
代码语言:javascript复制
# 员工基本信息类-员工详细信息类
# 定义在哪个类中都可以
models.OneToOneField

管理器

每个模型类都有objects对象,这是Django自动生成的管理器对象,通过这个管理器可以实现对数据的查询。

自定义模型管理器

  • 1.自定义一个管理器类,这个类继承models.Manger类。
  • 2.在具体的模型类里定义一个自定义管理器类的对象。
代码语言:javascript复制
# 1.自定义一个管理器类,这个类继承models.Manger类
class SchoolInfoManager(models.Manager):
    # 过滤父类方法返回的查询集来改变查询集
    def all(self):
        students = super().all()
        students = students.filter(isDelete=False)
        return students

    # 创建额外的方法
    # 例如Django 模型类管理器自带的 create(name= , addr= ) 可以通过自定义管理器对象来实现
    def create_school(self, name, addr):
        sc = SchoolInfo()
        sc.name = name
        sc.addr = addr
        sc.save()
        return sc

# 学校模型类
class SchoolInfo(models.Model):
    name = models.CharField(max_length=20)
    addr = models.CharField(max_length=100)

    # 在具体的模型类里定义一个自定义管理器类的对象。
    # objects指向自定义的管理类对象
    objects = SchoolInfoManager()

    def __str__(self):
        return self.name

元选项

代码语言:javascript复制
# 学校模型类
class SchoolInfo(models.Model):
    name = models.CharField(max_length=20)
    addr = models.CharField(max_length=100)

    # objects指向自定义的管理类对象
    objects = SchoolInfoManager()

    # 用来说明对象的字符表达方式,
    # 如果在Python 2中,重写的是__unicode__方法
    def __str__(self):
        return self.name

    # 元选项
    class Meta:
        # 不使用Django默认生成的表名,手动指定表名
        db_table = 'school'
        # other_metas = ...

通过Meta子类定义模型元数据,比如数据库表名、数据默认排序方式。

(元选项暂时不补充,待笔者之后用到再补充)

本文作者: Ifan Tsai  (菜菜)

本文链接: https://cloud.tencent.com/developer/article/2164574

版权声明: 本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!

0 人点赞