django模型层:单表多表操作f与q查询(代码片段)

telecasterfanclub telecasterfanclub     2022-12-03     371

关键词:

DJango模型层

单表操作

使用有几步:

  1. settings.py中配置连接数据库的地址,端口
  2. 在init.py中使用pymysql
  3. 在models.py里写类,一个类对应一个表,写属性
  4. 数据库迁移命令,第一个命令是纪录,第二个命令才是真正的数据库同步
  5. 导入models到views,开始使用
# models.py
# 建立单表
from django.db import models
class User(models.Model):
	# 类名就是表名,必须继承models.Model
	name = models.CharField(max_length=32)
	# charfield必须指定最大长度,否则报错
	age = models.IntegerField()
	# 创建数字字段
	register_time = models.DateField(auto_now=True)
	# 创建日期对象,这个字段有两个重要的参数	
	# auto_now 每次操作数据的时候自动更新该字段为
	# auto_now_add,创建的时候纪录时间,只要不人为修改,就会一直不变

当没有创建主键字段(primary_key=True)的时候,orm会自动帮你创建一个名为id的主键字段

执行两条数据库迁移命令,接下来就可以在视图中或测试脚本中使用了

# views.py
from app01 import models
# 先从应用中导入模型
...

增加数据

# 第一种
res = models.User.objects.create(name=‘aaa‘,age=21,register_time=‘2020-02-22‘)
# models.表名.objects.create() 括号里面填字段,日期字段可以直接写日期也可以填一个日期对象
# 这个方法有一个返回值,就是被创建的对象本身

# 第二种
user_obj = models.User(name=‘aaa‘,age=21,register_time=‘2020-02-22‘)
user_obj.save()

删除数据

res = models.User.objects.filter(pk=2).delete()
# 查找当前表主键为2的字段,删除
user_obj = models.User.objects.filter(pk=2).first()
user_obj.delete()

修改数据

user_obj = models.User.objects.filter(pk=3).update(name=‘bbb‘)

orm其他的api

<1> all():                  查询所有结果
  
<2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象
  
<3> get(**kwargs):          返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
  
<4> exclude(**kwargs):      它包含了与所给筛选条件不匹配的对象
 
<5> order_by(*field):       对查询结果排序(‘-id‘)
  
<6> reverse():              对查询结果反向排序
  
<8> count():                返回数据库中匹配查询(QuerySet)的对象数量。
  
<9> first():                返回第一条记录
  
<10> last():                返回最后一条记录
  
<11> exists():              如果QuerySet包含数据,就返回True,否则返回False
 
<12> values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
                            model的实例化对象,而是一个可迭代的字典序列
<13> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
 
<14> distinct():            从返回结果中剔除重复纪录

基于双下划线的模糊查询

Book.objects.filter(price__in=[100,200,300])
Book.objects.filter(price__gt=100)  # 大于
Book.objects.filter(price__lt=100)  # 小于
Book.objects.filter(price__gte=100)  # 大于等于
Book.objects.filter(price__lte=100)  # 小于等于
Book.objects.filter(price__range=[100,200]) 
Book.objects.filter(title__contains="python")
Book.objects.filter(title__icontains="python")
Book.objects.filter(title__startswith="py")
Book.objects.filter(pub_date__year=2012)

多表操作

表与表之间的关系有一对一,一对多,多对多

以图书,出版社,作者举例

一本图书只能有一个出版社,一个出版社出版多本书

  • 书----出版社 :一对多

一本书有多个作者,一个作者可以写多本书

  • 书----作者 : 多对多关系

作者与作者信息是一对一关系

技术图片

创建外键

一对多

models.ForeignKey()

# 书与出版社一对多外键
publish = models.ForeignKey(to=‘Publish‘,to_field=‘nid‘,on_delete=models.CASCADE)
# 创建外键字段publish,其中
# to:关联的表名
# to_field:要关联的表的字段名称,与publish表中的nid字段关联
# on_delete,删除表中的数据时,当前表与其关联的数据的行为
	# models.CASCADE,删除关联数据,与之关联也删除
    # models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
    # models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)

一对一

models.OneToOneField()

# 作者信息与作者表,一对一关系
author_detail = models.OneToOneField(to=‘AuthorDatail‘,to_field=‘nid‘,unique=True,on_delete=models.CASCADE)
# 关联的表明:AuthorDetail,关联的字段nid,该字段唯一,删除表中的数据,authordetail中对应的author也删除

多对多

authors=models.ManyToManyField(to=‘Author‘)

orm多对多关系并没有真正的关联,声明一个ManyToMany字段后,orm会帮我们创建一张中间表

多表添加表纪录

一对多

方式1:
publish_obj=Publish.objects.get(nid=1)
book_obj=Book.objects.create(title="",publishDate="2012-12-12",price=100,publish=publish_obj)
  
方式2:
book_obj=Book.objects.create(title="",publishDate="2012-12-12",price=100,publish_id=1)

多对多

# 当前生成的书籍对象
book_obj=Book.objects.create(title="追风筝的人",price=200,publishDate="2012-11-12",publish_id=1)
# 为书籍绑定的做作者对象
yuan=Author.objects.filter(name="yuan").first()
# 在Author表中主键为2的纪录
egon=Author.objects.filter(name="alex").first()
# 在Author表中主键为1的纪录

# 绑定多对多关系,即向关系表book_authors中添加纪录
book_obj.authors.add(yuan,egon)
#  将某些特定的 model 对象添加到被关联对象集合中。=======book_obj.authors.add(*[])

多对多关系常用api

book_obj.authors.remove()      # 将某个特定的对象从被关联对象集合中去除
# book_obj.authors.remove(*[])
book_obj.authors.clear()       #清空被关联对象集合
book_obj.authors.set()         #先清空再设置 

基于对象的跨表查询

查询两次,先拿到一个对象,再点再查一次得到结果

一对多

一对多的关系,外键字段建在多的一方,正向查询就是从有外键字段的这边查另一边:书表查出版社表

# 查询主键为1的书籍的出版社所在的城市
book_obj=Book.objects.filter(pk=1).first()
# book_obj.publish 是主键为1的书籍对象关联的出版社对象
print(book_obj.publish.city)

正向查询,直接使用点 . 即可

publish=Publish.objects.get(name="苹果出版社")
#publish.book_set.all() : 与苹果出版社关联的所有书籍对象集合
book_list=publish.book_set.all()    
for book_obj in book_list:
	print(book_obj.title)

反向查询,使用 要查询的表_set() 查询

一对一查询

正向,反向都用点方法

# 正向查询
egon=Author.objects.filter(name="egon").first()
print(egon.authorDetail.telephone)
# 通过作者表查询作者信息表的电话号码
# 反向查询
# 查询所有住址在北京的作者的姓名
authorDetail_list=AuthorDetail.objects.filter(addr="beijing")
for obj in authorDetail_list:
     print(obj.author.name)

多对多查询

# 眉所有作者的名字以及手机号
book_obj=Book.objects.filter(title="眉").first()
authors=book_obj.authors.all()
for author_obj in authors:
     print(author_obj.name,author_obj.authorDetail.telephone)
# 查询egon出过的所有书籍的名字
author_obj=Author.objects.get(name="egon")
book_list=author_obj.book_set.all()
#与egon作者相关的所有书籍
for book_obj in book_list:
    print(book_obj.title)

基于双下划线的跨表查询

使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的model 为止

一对多

表名__字段名

# 练习:  查询苹果出版社出版过的所有书籍的名字与价格(一对多)
# 正向查询 按字段:publish
queryResult=Book.objects.filter(publish__name="苹果出版社").values_list("title","price")
# 出版社表__出版社名

# 反向查询 按表名:book
queryResult=Publish.objects.filter(name="苹果出版社").values_list("book__title","book__price")
# 查询的本质一样,就是select from的表不一样

多对多

# 练习: 查询alex出过的所有书籍的名字(多对多)

# 正向查询 按字段:authors:
queryResult=Book.objects.filter(authors__name="yuan").values_list("title")

# 反向查询 按表名:book
queryResult=Author.objects.filter(name="yuan").values_list("book__title","book__price")

连续跨表案例

# 查询人民出版社出版过的所有书籍的名字以及作者的姓名

# 正向查询
queryResult=Book.objects.filter(publish__name="人民出版社").values_list("title","authors__name")
# 反向查询
queryResult=Publish.objects.filter(name="人民出版社").values_list("book__title","book__authors__age","book__authors__name")

F与Q查询

F查询

F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值

from django.db.models import F
# 需要先导入F
Book.objects.filter(commnetNum__lt=F(‘keepNum‘))
# book表中,commentNum<keepNum的数据

Django 支持F()对象之间以及F()对象和常数之间的加减乘除和取模的操作

# 查询评论数大于收藏数2倍的书籍
Book.objects.filter(commnetNum__lt=F(‘keepNum‘)*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元:

Book.objects.all().update(price=F("price")+30) 

Q查询

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象

from django.db.models import Q
Q(title__startswith=‘Py‘)

Q 对象可以使用&| 操作符组合起来。当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。

bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))

等同于下面的SQL WHERE 子句:

WHERE name ="yuan" OR name ="egon"

你可以组合&| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:

查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将“AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如:

bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017), title__icontains="python")

一些例子

 # 查询评论数大于阅读数的书籍
 from django.db.models import F,Q
 ret=Book.objects.filter(commit_num__gt=F(‘reat_num‘))
 print(ret)
 # 把所有书籍的价格加10
 Book.objects.all().update(price=F(‘price‘)+10)

 # ----Q函数,描述一个与,或,非的关系
 # 查询名字叫红楼梦或者价格大于100的书
 ret=Book.objects.filter(Q(name=‘红楼梦‘)|Q(price__gt=100))
 print(ret)
 # 查询名字叫红楼梦和价格大于100的书
 ret = Book.objects.filter(Q(name=‘红楼梦‘) & Q(price__gt=100))
 print(ret)
 # # 等同于
 ret2=Book.objects.filter(name=‘红楼梦‘,price__gt=100)
 print(ret2)
 # 也可以Q套Q
 # 查询名字叫红楼梦和价格大于100  或者 nid大于2
 ret=Book.objects.filter((Q(name=‘红楼梦‘) & Q(price__gt=100))|Q(nid__gt=2))
 print(ret)
 # ----非
 ret=Book.objects.filter(~Q(name=‘红楼梦‘))
 print(ret)
 # Q和键值对联合使用,但是键值对必须放在Q的后面(描述的是一个且的关系)
 # 查询名字不是红楼梦,并且价格大于100的书
 ret=Book.objects.filter(~Q(name=‘红楼梦‘),price__gt=100)
 print(ret)

聚合查询

aggregate(*args, **kwargs)

需要对一个表中所有的数据做操作时,可以使用聚合查询,比如求一个字段的平均值,最大值,最小值,这都需要搜索整个表的这个字段,最后得出结果

聚合查询的方法是QuerySet的一个结束字句,他不返回QuerySet对象,不能在后面继续点

# 计算所有图书的平均价格
from django.db.models import Avg
# 计算平均的方法需要先导入
Book.objects.all().aggregate(Avg(‘price‘))
# ‘price__avg‘: 34.35
# 返回这样一个字典

分组查询

annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

总结 :跨表分组查询本质就是将关联表join成一张表,再按单表的思路进行分组查询。 

练习:统计每一本书作者个数

from django.db.models import Avg, Max, Sum, Min, Max, Count
book_list = models.Book.objects.all().annotate(author_num=Count("authors"))
for book in book_list:
     print(book.name)
     print(book.author_num)
book_list = models.Book.objects.all().annotate(author_num=Count("authors")).values(‘name‘,‘author_num‘)
print(book_list)

django系列

  Django框架简介  Django静态文件  Djangorequest对象与ORM简介  Django路由系统  Django之视图层  Django之模板层  Django的settings源码分析Django表模型操作  Django表关系的创建  Django单表查询  Django多表、跨表、聚... 查看详情

django-orm:单表查询基于对象和双下划线的多表操作集合查询分组查询f查询和q查询(代码片段)

##############################################单表操作##############################################简单查:models.User.objects.filter(id=3)#queryset对象,相当于一个列表,放了一个或多个User对象models.User.objects.filter(id=3).fi 查看详情

mybatis单表多表查询,动态sql使用(代码片段)

文章目录单表查询操作参数占位符#和$$VS#SQL注入like模糊查询多表查询操作一对一多表查询一对多多表查询动态SQL使用if标签trim标签where标签set标签foreach标签单表查询操作参数占位符#和$#:相当于JDBC里面替换占位符的操作方... 查看详情

django模型层:单表操作(代码片段)

一ORM简介 对象关系映射(ObjectRelationalMapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术 查询数据层次图解:如果操作mysql,ORM是在pymysq之上又进行了一层封装MVC或者MTV框架中包括... 查看详情

django模型层(多表操作)(代码片段)

创建模型(一)多表查询一对一:models.OneToOneField(to_field=‘id‘,to=‘Authordatil‘)一对多:(外键设置唯一性)models.ForeignKey(to=‘Publish‘,to_field=‘id‘)多对多:自动生成第三张表models.ManyToManyField(to=‘Author‘)(二)创建表模型作... 查看详情

django-orm-多表操作(代码片段)

目录一、创建模型二、增删改增加记录删除记录修改记录三、基于对象的跨表查询(子查询)四、基于双下划线的跨表查询(连表join)普通版进阶版五、聚合查询、分组查询、F和Q查询聚合查询分组查询F和Q查询ORM执行原生SQL一... 查看详情

单表多表操作

一、单表操作1.1在python的脚本下调用Django环境test.py1.2用orm创建表models.py数据的迁移操作python3manage.pymakemigrations#只是对变化做一个记录,记录文件在app的migrations文件夹下python3manage.pymigrate     #把更改提交到数据库python3manage.... 查看详情

wen应用/路由控制/视图函数/单表多表操作(代码片段)

...ww.cnblogs.com/liuqingzheng/articles/9523087.html   2.MVC和MTV(Django)    M:Model和数据库打交道    V:模板    C:控制器  MTV:(MTV也是MVC架构)    M:models和数据库打交道    T:Templates模板层,对到MVC... 查看详情

django框架

一、Django初识、settings配置等二、路由层三、视图层四、模板层五、模型层  orm基本操作  多对多表创建方式  F、q查询,事务及自定义字段六、Django进阶  Ajax  分页器 查看详情

django模型层之多表操作(代码片段)

一.创建模型实例:作者表:拥有字段:姓名(name),性别(sex),该表与书籍表之间为多对多的关系作者详情表:拥有字段:地址(addr),手机号(phone),该表与作者表之间为一对一的关系出版社表:拥有字段:名字(name),地址(addr),该表与书籍表之间为... 查看详情

django之模型层&orm操作(代码片段)

 一.单表查询:     1.在模型层创建模型表:fromdjango.dbimportmodels#Createyourmodelshere.#单表查询表classUser(models.Model):name=models.CharField(max_length=32)age=models.IntegerField()registe 查看详情

django-模型层(orm语法)

...子查询联表查询今日内容详细测试脚本"""当你只是想测试django中的某一个py文件内容那么你可以不用书写前后端交互的形式而是直接写一个测试脚本即可脚本代码无论是写在应用下的tests.py还是自己单独开设py文件都可以"""#测试... 查看详情

django

Django简介下载安装  Windows下安装Django  Linux上安装DjangoWEB应用HTTP协议web应用项目路由控制视图层模板层模型层:单表操作,多表操作,常用字段和参数组件:Django与Ajax,分页器组件,forms组件,cookie与session组件,中间件组... 查看详情

django之模型层第二篇:多表操作(代码片段)

Django之模型层第二篇:多表操作一表关系回顾?在讲解MySQL时,我们提到,把应用程序的所有数据都放在一张表里是极不合理的。?比如我们开发一个员工管理系统,在数据库里只创建一张员工信息表,该表有四个字段:工号、姓... 查看详情

django基础五之django模型层单表操作(代码片段)

ORM单表操作类---表类对象---一行数据类属性---字段 增创建记录方式1student_obj=models.Student(name=‘dazhaung‘,age=23,)student_obj.save()创建记录方式2new_obj=models.Student.objects.create(name=‘xiaozhuang2‘,age=6)#写成**‘name‘:‘xx‘ 查看详情

数据库之表查询,单表多表,子查询

基本查询语句及方法 from where groupby having distinct orderby limit ....连表 innerjoin leftjoin rightjoin union子查询  书写顺序 selectid,namefromempwhereid>3andid<6;执行顺序 from#确定到底是哪站表 where#根据过来条件筛选数据 s 查看详情

django模型层2多表操作(代码片段)

1.多表操作:  1.创建模型:实例:我们来假定下面这些概念,字段和关系作者模型:一个作者有姓名和年龄。作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对... 查看详情

模型层单表操作(代码片段)

模型层单表操作单表操作例:1.单表的查询1.单表查询所有用户:models.Book.objects.all()得到的是queryset对象(当成列表),列表里面,一个一个的对象[user1,user2]?2.render(request,‘booklist.html‘,‘book_list‘:ret)?3.模板里:%foruserinbook_list%#要循环的... 查看详情