Django_ORM知识梳理
#Sql数据库结构 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sakila | | stie_28 | | sys | | world | +--------------------+ 7 rows in set (0.00 sec) mysql> use stie_28; Database changed mysql> show tables; +----------------------------+ | Tables_in_stie_28 | +----------------------------+ | app1_author | | app1_book | | app1_book_author | | app1_publish | | auth_group | | auth_group_permissions | | auth_permission | | auth_user | | auth_user_groups | | auth_user_user_permissions | | django_admin_log | | django_content_type | | django_migrations | | django_session | +----------------------------+ 14 rows in set (0.00 sec) mysql> select * from app1_book; +----+--------+--------+-------+------------+ | id | title | price | count | publish_id | +----+--------+--------+-------+------------+ | 1 | python | 100.00 | 100 | 1 | | 3 | Linux | 200.00 | 99 | 2 | | 7 | linux2 | 200.00 | 100 | 1 | | 8 | abcn | 67.00 | 38 | 1 | +----+--------+--------+-------+------------+ 4 rows in set (0.00 sec) mysql> select * from app1_author; +----+------+ | id | name | +----+------+ | 1 | 张三 | | 2 | 李四 | | 3 | 王五 | +----+------+ 3 rows in set (0.00 sec) mysql> select * from app1_book_author; +----+---------+-----------+ | id | book_id | author_id | +----+---------+-----------+ | 26 | 3 | 1 | | 27 | 3 | 2 | | 28 | 3 | 3 | +----+---------+-----------+ 3 rows in set (0.00 sec) mysql> select * from app1_publish; +----+------------+---------+ | id | name | address | +----+------------+---------+ | 1 | 人民出版社 | 北京 | | 2 | 出版社A | 北京 | +----+------------+---------+ 2 rows in set (0.00 sec) mysql>
#Django models.py文件内容 from django.db import models # Create your models here. #book与publish外键(一个出版社对应多本书) class Publish(models.Model): name=models.CharField(max_length=32) address=models.CharField(max_length=32) # def __str__(self): #直接print publish_obj的时候显示具体的数值 # return self.name+' '+self.address class Book(models.Model): title=models.CharField(max_length=32) price=models.DecimalField(max_digits=9,decimal_places=2) count=models.IntegerField() #下面的括号内的publish加上""就可以,不用管上下顺序关系,否则必须book必须写在publish下面 publish=models.ForeignKey('Publish') #设置publish为外键,django会自动在数据库中加上_id(publish_id) author=models.ManyToManyField('Author') #书跟作者是多对多的关系,使用ManyToMany让django自动创建第三张关系表 def __str__(self): return self.title class Author(models.Model): name=models.CharField(max_length=32) #手动创建的书跟出版社多对多的关系的第三张表 # class BooktoPublish(models.Model): # book=models.ForeignKey("Book") # publish=models.ForeignKey("Publish")
#Django views.py文件内容 from django.shortcuts import render,HttpResponse,redirect # Create your views here. from app1.models import * def add(request): # 向出版社表中插入数据 # p=Publish(name="人民出版社",address="北京") # p.save() # 向作者表中插入数据 # Author.objects.create( # name='李四' # ) # 两种向表中插入数据的方式 # 一. save()方式 # publish_obj=Publish.objects.get(id=1) #获取出版社表中的条目ID对象(对应ID必须存在) # # print("publish_obj:",publish_obj) #publish_obj是一个 Publish object,可以通过 在class中使用 __str__(self)显示具体数据 # book_obj=Book(title="python",price=100.00,count=100,publish=publish_obj) #给外键赋值的两种办法这里使用对象来赋值,所以写成publish='' # book_obj.save() # # 二. create方式 # Book.objects.create( # title="linux2", # price=200.00, # count=100, # publish_id=1 #给外键赋值的第二种方式,使用publish_id直接指定ID数值(publish的对应ID必须存在) # ) # 添加多对多关系 # 正向绑定 # book_Obj_linux=Book.objects.get(title='Linux') #获取书对象 # author_obj_1=Author.objects.get(id=1) #获取作者对象 # author_obj_2=Author.objects.get(id=2) # author_obj_list=Author.objects.all() #获取所有作者对象 # print("===========",author_obj_list) #这是获取到的作者对象数据形式,QuerySet类型 # <QuerySet [<Author: Author object>, <Author: Author object>, <Author: Author object>]> # 绑定关系 # book_Obj_linux.author.add(author_obj_1,author_obj_2) #绑定单个或者用逗号隔开多个作者 # book_Obj_linux.author.remove(author_obj_1,author_obj_2) #移除单个或者用逗号隔开多个作者 # book_Obj_linux.author.add(*author_obj_list) #添加集合形式需要在前面加上*号 # 反向绑定 # author_obj_zhangsan=Author.objects.get(name='张三') #获取作者对象 # author_obj_zhangsan.book_set.add(*Book.objects.all()) #作者写了所有书 # author_obj_zhangsan.book_set.add(*Book.objects.filter(id=2)) #作者只写了ID为2的书 # 解除绑定 # book_Obj_linux.author.clear() #解除书籍绑定的对应的所有作者关系 # author=Author.objects.get(id=2) #获取author对象 # book_Obj_linux.author.remove(author) #移除 book_obj_linux的对应作者 # book_Obj_linux.delete() #删除 book_obj_linux return HttpResponse("ok") def query(request): # 查询方法 # 一. all() # ret=Book.objects.all() #<QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]> # 查询的所有书籍对象,可以在model中 配置def __str__(self)属性显示具体书名 # <QuerySet [<Book: python>, <Book: Linux>, <Book: linux2>]>配置后查询结果 # 二. filter() # ret=Book.objects.filter(price=200,count__gt=100) #<QuerySet [<Book: python>]> # 过滤查询,filter后面括号内为过滤条件,多个条件逗号隔开 # 三. get() # ret=Book.objects.get(id=1) # 获取 title=Linux 的记录,直接返回获取的属性值Linux # 注:不能get有多个结果的字段值,例如有多个count等于100 # 四. exclude() # ret=Book.objects.exclude(id=1) # <QuerySet [<Book: Linux>, <Book: linux2>]> # 获取与筛选条件不匹配的对象,上面ID=1的是Python ,筛选出另外两个 # 了不起的双下划线 # -----------------单表条件查询------------------------ # ret=Book.objects.filter(id__lt=7,id__gt=1) # <QuerySet [<Book: Linux>]> # 查询book表中id小于7 大于1的条目. # ret=Book.objects.filter(id__in=[1,3,7]) # <QuerySet [<Book: python>, <Book: Linux>, <Book: linux2>]> # 查询id 等于 1 3 7的条目,使用exclude可以达到 not in 不等于取反的效果 # ret=Book.objects.filter(title__icontains='linux') #<QuerySet [<Book: Linux>, <Book: linux2>]> # __icontains不区分大小写,含包含功能所以匹配到两个结果 # ret = Book.objects.filter(title__contains='Linux') # <QuerySet [<Book: Linux>]> # contains匹配一个条目,区分大小写 # ret=Book.objects.filter(id__range=[1,7]) # <QuerySet [<Book: python>, <Book: Linux>, <Book: linux2>]> # 匹配id 1-7 之间 包含1 和 7 # ret=Book.objects.filter(title__startswith='L') # <QuerySet [<Book: Linux>]> # 匹配L开头的title,只显示找到的第一个条目 # ret=Book.objects.filter(title__endswith='n') # <QuerySet [<Book: python>, <Book: abcn>]> # 匹配n结尾的title # istartswith,iendswith <----这两个跟上面一样只是 忽略大小写 # ----------------多表条件关联查询--------------------- # 正向查找 # 一对多 # <QuerySet [{'publish__address': '北京'}]> # ret=Book.objects.filter(id=1).values('publish__address') # 查询出版了id=1的书籍的所有出版社地址 # # 多对多 # <QuerySet [{'author__name': '张三'}, {'author__name': '李四'}, {'author__name': '王五'}]> # ret=Book.objects.filter(title='Linux').values('author__name') # 查询title=Linux的书籍的所有作者姓名 # # 反向查找 # 一对多 # <QuerySet [{'book__title': 'python'}, {'book__title': 'linux2'}]> # ret=Publish.objects.filter(id=1).values('book__title') # 查询ID=1的出版社,出版的所有书籍 # # 反向多对多 # <QuerySet [{'book__title': 'Linux'}]> # ret=Author.objects.filter(id=1).values('book__title') # 查询id=1的作者,写了哪些书籍 # -------------------QuerySet相关 -------------------------- # QuerySet集合支持切片操作 # ret=Book.objects.all()[0] #python 取集合索引为零 # ret=Book.objects.all()[0:2] #<QuerySet [<Book: python>, <Book: Linux>]> 取集合索引0-2的不含2 # ret=Book.objects.all()[2] #linux2 # ret=Book.objects.all()[::2] #[<Book: python>, <Book: linux2>] 隔两个取一个 # print(ret) # QuerySet可迭代 # book_list=Book.objects.all() # # for book in book_list: # for 循环没循环一次访问一次数据库(执行一次sql语句)取出对应的数据 # print(book.title) # # if book_list: # if在判断的时候也执行了sql语句,来判断book_list是否有值 # print('Have values') # -------------查询借助对象以及属性-------------------- # book_obj=Book.objects.get(title='python') # print(book_obj.publish.address) # 北京 # 查询Python这本书的出版社地址 # book_obj=Book.objects.get(title='Linux') # 获取书籍对象 # author_list=book_obj.author.all() # 获取这本书的所有作者集合(QuerySet类型) # for author in author_list: # 循环打印出所有作者的名字 # print(author.name) # 张三 李四 王五 # 查询Linux这本书的所有作者 # 反向查询 # publish_obj=Publish.objects.get(name='人民出版社') #获取出版社对象 # book_list=publish_obj.book_set.all() #获取出版社下的所有书籍集合(QuerySet类型) # for book in book_list: #for循环取出所有的书名 # print(book.title) #python linux2 abcn # 查询人民出版社出版了哪些书 return HttpResponse("query ok")
# 八月三十日追加views内容 def aggregate(request): # -------------------聚合查询和分组查询------------------ from django.db.models import Avg,Min,Sum,Max # ret=Book.objects.all().aggregate(AvgPrice=Avg('price')) # {'price__avg': 141.75} # 求所有书籍的平均价格 AvgPrice=Avg() 前面为自定义键名 ↑ 这是不指定键名自动生成的键名 # ret = Book.objects.all().aggregate(MaxPrice=Max('price')) # {'MaxPrice': Decimal('200.00')} # 求所有书籍的最高价格 ↑ MaxPrice为指定的键名 # ret=Book.objects.filter(author__name='张三').aggregate(Max('price')) # {'price__max': Decimal('200.00')} # 求张三出版的所有书籍最高价格是多少 # ret=Book.objects.values('author__name').annotate(Max('price')) # <QuerySet [{'author__name': '张三', 'price__max': Decimal('200.00')}, {'author__name': '李四', 'price__max': Decimal('199.00')},.... # 查询每个作者出版的价格最高的书籍 ↑ 这是聚合相当于 group_by # ret=Book.objects.values('publish__name').annotate(Min('price')) # <QuerySet [{'publish__name': '人民出版社', 'price__min': Decimal('67.00')}, {'publish__name': '出版社A', 'price__min': Decimal('199.00')}]> # 查询每个出版社出版过的书中价格最低的书 return HttpResponse("aggregate ok") def FandQ(request): from django.db.models import F,Q # 导入models下的F,Q # ret=Book.objects.all().update(price=F("price") + 20) # update会返回更改了几条记录 4 # 给所有书籍的价格加上20 ↑ F相当于临时变量,获取原本的 price数值 # ret=Book.objects.filter(Q(title__startswith='L')|Q(price__gt=200)) # <QuerySet [<Book: python>, <Book: Linux>, <Book: Linux2>]> # 查询书名是L开头的 或者价格大于 200的书籍 |管道符是或的意思 ,逗号是且的意思 Q给条件分组用于复杂查询 return HttpResponse("FandQ ok")
附:
# 查询相关API: # <1>filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 # <2>all(): 查询所有结果 # <3>get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 #-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()-------- # <4>values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列 # <5>exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 # <6>order_by(*field): 对查询结果排序 # <7>reverse(): 对查询结果反向排序 # <8>distinct(): 从返回结果中剔除重复纪录 # <9>values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 # <10>count(): 返回数据库中匹配查询(QuerySet)的对象数量。 # <11>first(): 返回第一条记录 # <12>last(): 返回最后一条记录 # <13>exists(): 如果QuerySet包含数据,就返回True,否则返回False
#在settings加上日志记录部分 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
浙公网安备 33010602011771号