【Django 笔记】模型(1)--字段属性、查询函数、QuerySet查询集

【Django 笔记】模型

笔记主要基于官方文档,从中提取要点和记录笔记,关键处包含了官方文档链接。详见官方文档。

官方文档:Django documentation 

博客推荐:Django2.2教程

官方文档模型层:The model layer   模型层

目录

0.1.ORM

0.2.使用其他数据库(MySQL)

模型

1.字段属性

1.1.模型类属性命名限制

1.2.字段类型

1.3.字段选项

2. 查询

2.1. 查看mysql数据库日志

2.2. 查询函数

字段查询

2.3.用Q对象进行复杂查询

2.4. F对象

2.5.聚合函数

2.6.查询相关函数小结

3.查询集QuerySet


0. 前导

0.1.ORM

了解ORM,全拼Object-Relation Mapping

在MVC框架中的Model模块中都包括ORM,对于开发人员主要带来了如下好处:

  • 实现了数据模型与数据库的解耦,通过简单的配置就可以轻松更换数据库,而不需要修改代码。
  • 只需要面向对象编程,不需要面向数据库编写代码。
  • 在MVC中Model中定义的类,通过ORM与关系型数据库中的表对应,对象的属性体现对象间的关系,这种关系也被映射到数据表中。

0.2.使用其他数据库(MySQL)

创建好Django项目后,打开settings.py文件,找到DATABASES项,看到默认使用SQLite3数据库。需对其做修改。

顺便,创建好应用后,在settings.py文件中,找到INSTALLED_APPS项,将 '应用名' 添加到列表中,以注册应用

修改为使用MySQL数据库,举例代码如下:

将引擎改为mysql,提供连接的主机HOST、端口PORT、数据库名NAME、用户名USER、密码PASSWORD

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test2', #数据库名字,
        'USER': 'root', #数据库登录用户名
        'PASSWORD': 'mysql', #数据库登录密码
        'HOST': 'localhost', #数据库所在主机
        'PORT': '3306', #数据库端口
    }
}

注意Django框架不会自动生成数据库 test2,需要我们自己进入mysql数据库去创建

在MySQL手动创建数据库:

打开新终端,在命令行登录mysql,创建数据库(以数据库test2为例)。

注意:设置字符集为utf8

create database test2 charset=utf8;

如果切换mysql数据库之后不能启动服务器

需要安装操作mysql数据库的包 (Django2以上的版本推荐使用更新的方法

  • python2需要安装mysql-python:

       pip install mysql-python

  • python3需要安装pymysql:

        pip install pymysql

python3中安装好pymysql后,在项目下的__init__.py中加如下内容:

import pymysql

pymysql.install_as_MySQLdb()

 

更新:

在较新版本的Django中,可能存在Django和MySQL的兼容性问题,进行文件迁移时提示以下错误

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.

解决办法一:就是更改源码,但是版本是会持续更新的,治标不治本。

解决方法二:既然提示我们mysqlclient 1.3.13 or newer is required ,那我们就对其进行更新就好:

     1.将旧的组件删除:sudo pip uninstall pymysql

     2.安装新的组件:pip install mysqlclient

     3.如果根目录下的manage.py文件或项目下的__init__.py中有如下语句,删除

import pymysql

pymysql.install_as_MySQLdb()

 

注意定义模型类的外键时,Django1.x与Django2.x的区别:

关系属性名= models.ForeignKey('模型类A')   # Django1的写法
关系属性名 = models.ForeignKey(模型类A, on_delete=models.CASCADE)   # Django2的写法

官方文档:ForeignKey

创建项目、应用、数据库;定义模型类并迁移;定义视图;配置URL;创建模版等。

模型

关于模型常用的一些知识笔记。

1.字段属性

官方文档:字段类型  模型字段参考

常用部分如下。

1.1.模型类属性命名限制

  1. 不能是python的保留关键字。
  2. 不允许使用连续的下划线,这是由django的查询方式决定的。
  3. 定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:
  • 属性名=models.字段类型(选项)
     

1.2.字段类型

使用时需要引入django.db.models包(from django.db import models),字段类型如下:

类型

描述

AutoField

自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性。

BooleanField

布尔字段,值为True或False。

NullBooleanField

支持Null、True、False三种值。

CharField(max_length=最大长度)

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

TextField

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

IntegerField

整数

DecimalField(max_digits=None, decimal_places=None)

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

FloatField

浮点数。参数同上

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,对上传的内容进行校验,确保是有效的图片。

1.3.字段选项

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

选项名

描述

default

默认值。设置默认值。

primary_key

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

unique

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

db_index

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

db_column

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

null

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

blank

如果为True,则该字段允许为空白,默认值是False。

对比:null是数据库范畴的概念,blank是后台管理页面表单验证范畴的。

注:

当修改模型类之后,如果添加的选项影响了表的结构,需要重新做迁移

2. 查询

2.1. 查看mysql数据库日志

mysql.logmysql的日志文件,里面记录了对MySQL数据库的操作记录。

默认情况下mysql的日志文件没有产生,需要修改mysql的配置文件。

步骤如下:

1)使用下面的命令打开mysql的配置文件,去除68,69行的注释,然后保存。

sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

 

即将下面这两行前面的#去掉

#general_log_file        = /var/log/mysql/mysql.log
#general_log             = 1

 

 

2)重启mysql服务(不是重新连接),就会产生mysql日志文件。

sudo service mysql restart

3)打开MySQL的日志文件。

/var/log/mysql/mysql.log mysql日志文件所在的位置。

使用下面的命令可以实时查看mysql的日志文件:

sudo tail -f /var/log/mysql/mysql.log

这样,在Django执行数据库操作时就可以看到其相应执行的SQL。比如在项目的交互环境中,进行查询数据等操作时,就可以实时的看见其转换的SQL语句。

2.2. 查询函数

官方文档:执行查询

完整的各种 QuerySet 方法请参阅 QuerySet API 参考

通过模型类.objects属性可以调用如下函数(点击可跳转官方文档),实现对模型类对应的数据表的查询。

函数名

功能

返回值

说明

 get

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

返回值是一个模型类对象。

参数中写查询条件

1)如果查到多条数据,则抛异常MultipleObjectsReturned

2)查询不到数据,则抛异常:DoesNotExist

all

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

返回值是QuerySet类型

返回的是查询集(可以遍历等)

 filter

返回满足条件的数据。

返回值是QuerySet类型

参数写查询条件

 exclude

返回不满足条件的数据。

返回值是QuerySet类型

参数写查询条件

 

order_by

对查询结果进行排序。

返回值是QuerySet类型

参数中写根据哪些字段进行排序。

使用例子可查看官方文档 :Retrieving objects

完整的各种 QuerySet 方法请参阅 QuerySet API 参考

注意:

字段查询

字段查询即你如何制定 SQL WHERE 子句。它们以关键字参数的形式传递给 QuerySet 方法 filter(), exclude() 和 get(),通俗的说,它们作为这些方法的查询条件(条件运算符

基本的查询关键字参数遵照 field__lookuptype=value 模型类属性名/字段名__查询条件=值(有个双下划线)。例如:

Entry.objects.filter(pub_date__lte='2006-01-01')

转换为 SQL 语句大致如下:

SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

查询子句中指定的字段必须是模型的一个字段名。不过也有个例外,在 ForeignKey 中,可以指定以 _id 为后缀的字段名。这种情况下,value 参数需要包含 foreign 模型的主键的原始值。例子:

Entry.objects.filter(blog_id=4)

下表列出了所有的字段查询参数:

字段名 说明
exact 精确匹配
iexact 不区分大小写的精确匹配
contains 包含匹配
icontains 不区分大小写的包含匹配
in 在..之内的匹配
gt 大于
gte 大于等于
lt 小于
lte 小于等于
startswith 从开头匹配
istartswith 不区分大小写从开头匹配
endswith 从结尾处匹配
iendswith 不区分大小写从结尾处匹配
range 范围匹配
date 日期匹配
year 年份
month 月份
day 日期
week 第几周
week_day 周几
time 时间
hour 小时
minute 分钟
second
isnull 判断是否为空
search 1.10中被废弃
regex 区分大小写的正则匹配
iregex 不区分大小写的正则匹配

完整参考文档位于 字段查询参考(field lookup reference),里面包含较完整的条件运算符,即查询条件

2.3.用Q对象进行复杂查询

Q对象可以实现多条件的复杂查询 。

作用:用于查询时条件之间的逻辑关系。not and or,可以对Q对象进行&|~操作。即Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或。Q对象前可以使用~操作符,表示非not。

使用之前需要先导入:

from django.db.models import Q

语法

Q(属性名__运算符=值)

举例:

多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字。

例:查询阅读量大于20,并且编号小于3的图书。

list=BookInfo.objects.filter(bread__gt=20,id__lt=3)
# 或
list=BookInfo.objects.filter(bread__gt=20).filter(id__lt=3)

如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符。

例:查询阅读量大于20的图书,改写为Q对象如下。

from django.db.models import Q
...
list = BookInfo.objects.filter(Q(bread__gt=20))

例:查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现

list = BookInfo.objects.filter(Q(bread__gt=20) | Q(pk__lt=3))

例:查询编号不等于3的图书。

list = BookInfo.objects.filter(~Q(pk=3))

2.4. F对象

之前的查询都是对象的属性与常量值比较,两个属性怎么比较呢? 答:使用F对象,被定义在django.db.models中。使用表达式,过滤器就可以为模型指定字段,使两个属性进行比较。

F对象

语法F(属性名) 创建F对象, F() 的实例充当查询中的模型字段的引用。

作用:用于类属性之间的比较。

使用之前需要先导入from django.db.models import F

Django 支持对 F() 对象进行加、减、乘、除、求余和次方,另一操作数既可以是常量,也可以是其它 F() 对象。

例:查询阅读量大于等于评论量的图书。

from django.db.models import F
...
list = BookInfo.objects.filter(bread__gte=F('bcomment'))

可以在F对象上使用算数运算

例:查询阅读量大于2倍评论量的图书。

list = BookInfo.objects.filter(bread__gt=F('bcomment') * 2)

2.5.聚合函数

  • 使用aggregate()过滤器调用聚合函数。
  • 聚合函数包括:Avg,Count,Max,Min,Sum
  • 被定义在django.db.models中。

作用:对查询结果进行聚合操作。

aggregate:调用这个函数来使用聚合。 返回值是一个字典。

使用前需先导入聚合类

from django.db.models import Sum,Count,Max,Min,Avg

aggregate的返回值是一个字典类型,格式如下:

  {'聚合类小写__属性名':值}
  如:{'sum__bread':3}

 

注意:区别聚合函数的Count和count函数

count函数 返回值是一个数字

作用:统计满足条件数据的数目。

举例:

1.查询所有图书的数目。(用聚合Count)

BookInfo.objects.all().aggregate(Count('id'))

{'id__count': 5}

 

2.查询所有图书阅读量的总和。

BookInfo.objects.aggregate(Sum('bread'))

{'bread__sum': 126}

 

3.统计所有图书的数目。(用count函数)

BookInfo.objects.all().count()

BookInfo.objects.count()

 

4.统计id大于3的所有图书的数目。

BookInfo.objects.filter(id__gt=3).count()

2.6.查询相关函数小结

3.查询集QuerySet

关于QuerySet及其API可以参考:QuerySet API referenceQuerySet API 

查询集表示从数据库中获取的对象集合。all, filter, exclude, order_by调用这些函数会返回一个QuerySet 对象,即产生一个查询集。QuerySet类对象可以继续调用上面的所有函数。

 

查询集特性

  1. 惰性查询:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用。
  2. 缓存:当使用的是同一个查询集时,第一次的时候会发生实际数据库的查询,然后把结果缓存起来,之后再使用这个查询集时,使用的是缓存中的结果。

 

可以对一个查询集进行取下标或者切片操作来限制查询集的结果。

对一个查询集进行切片操作会产生一个新的查询集下标不允许为负数

取出查询集第一条数据的两种方式:

方式

说明

b[0]

如果b[0]不存在,会抛出IndexError异常

b[0:1].get()

如果b[0:1].get()不存在,会抛出DoesNotExist异常。

exists方法:判断一个查询集中是否有数据:True或 False。

更多查询集方法参考:https://docs.djangoproject.com/zh-hans/2.2/ref/models/querysets/#queryset-api

-----end------

发布了50 篇原创文章 · 获赞 10 · 访问量 6595

猜你喜欢

转载自blog.csdn.net/qq_23996069/article/details/104773036
今日推荐