Django模型层多表操作
2020-06-02 22:45
232 查看
目录
1.创建表模型
''' (一)多表查询 一对一:models.OneToOneField(to_field='id',to='Authordatil') 一对多:(外键设置唯一性) models.ForeignKey(to='Publish',to_field='id') 多对多:自动生成第三张表 models.ManyToManyField(to='Author') (二)创建表模型 作者与详情 ( 一对一 ) 书与作者( 多对多 ) 出版社与书(一对多 ) 出版社:id name add email 书: id name price publish 作者: id name sex authordatil 详情: id photo address ''' from django.db import models # Create your models here. class Publish(models.Model): id = models.AutoField(primary_key=True) # 主键 name = models.CharField(max_length=32) address = models.CharField(max_length=64) email = models.EmailField() def __str__(self): return '%s,%s,%s'%(self.name,self.address,self.email) class Book(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5,decimal_places=2) # 出版社与书( 一对多 )外键要设置唯一性,关联的表,关联的字段 publish = models.ForeignKey(to='Publish',to_field='id') # 书与作者( 多对多 ) authors = models.ManyToManyField(to='Author') def __str__(self): return self.name class Author(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) choices = ( (0,"女"),(1,"男") ) sex = SmallIntegerField( choices=choices, default=0 ) # 作者与详情 ( 一对一 ) authordatil = models.OneToOneField(to_field='id',to='Authordatil') def __str__(self): return self.name class Authordatil(models.Model): id = models.AutoField(primary_key=True) photo = models.CharField(max_length=32) address = models.CharField(max_length=32)
- id 字段是自动添加的
- 对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名
- 外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。
2.添加/删除/修改表记录
- 批量插入
# 批量插入 bulk_create li = [] for i in range(100): li.append(models.Book(name='图书%s'%i,price=10+i)) # 生成100个对象 models.Book.objects.bulk_create(li) # 参数为列表,列表里为100个对象,一次插入100条
- 一对一 增/删/改 数据
# 增 Authordatil = Authordatil.objects.create(photo=121212121,address='东莞') # 改 auther = Auther.objects.filter(name = '西游记').update( publish_id=1 ) # 先查 auther = Auther.objects.filter("name" = "西游记").first() auther.name = "东游记" # 再改 auther.save() # 最后保存 auther =Auther.objects.filter(name = '西游记').delete() # 删除
- 一对多 增/删/改 数据
#增: # publish_id: 数字 book = Book.objects.create(name='三国',price=56,publish_id=1) # publish: 对象 publish = Publish.objects.get(id=1) book = Book.objects.create(name='西游记',price=26,publish=publish) #改: # publish_id: 数字 book = Book.objects.filter(name = '西游记').update( publish_id=1 ) # publish: 对象 publish = Publish.objects.get(id=3) book = Book.objects.filter(name = '西游记').update(publish=publish) #删:同单表查询一样 book = Book.objects.filter(name='西游记',price=22).delete()
- 多对多 增/删/改 数据
''' 增:add ( obj1,obj2... ) 可以传对象,可以传id,可以传多个 删:remove( obj1,obj2... ) 可以传对象,可以传id,可以传多个 改:先清空,配置 清空: clear() 清空所有 配置:set() 里面传列表,里面可以是对象或者是id *注意先清空,在配置 ''' #(五)多对多新增 (书 与 作者) zxx = Author.objects.filter(name='zxx').first() yxx = Author.objects.filter(name='yxx').first() book = Book.objects.filter(name='西游记').first() book.authors.add(yxx,zxx) # 删: lxx = Author.objects.filter(name='lxx').first() zxx = Author.objects.filter(name='zxx').first() book = Book.objects.filter(name='红楼梦').first() book.authors.remove(lxx,zxx) # 清空: clear() 清空所有 book.authors.clear() # 配置:set() lxx = Author.objects.filter(name='lxx').first() zxx = Author.objects.filter(name='zxx').first() book.authors.set([1,2]) book.authors.set([lxx,zxx])
3.基于对象的查询表记录(子查询)
- 查询分析:正反向查询
''' 从关联字段的表出发,查向另外一张表 为正向,反之为反向 eg: 正向: author---关联字段在author--->authordetail ------> 按字段 反向: authordetail------关联字段在author--->author -----> 按表名小写 '''
- 一对一 查询
# 正向(按字段名) author = Author.objects.filter(name='lxx').first() photo = author.authordatil.photo # 反向(按表名小写) authordatil = Authordatil.objects.filter(photo=166667878).first() author_name = authordatil.author.name
- 一对多 查询
# 正向(按字段名) book = Book.objects.filter(name='茶社').first() publish = book.publish print(publish.name) # 反向 ( 按 表名_set.all() ) publish = Publish.objects.filter(name='武汉出版社').first() author = publish.book_set.all()
- 多对多 查询
# 正向(按字段名) book = Book.objects.filter(name='红楼梦').first() author = book.authors.all() # 反向( 按 表名_set.all() ) author = Author.objects.filter( name='lxx').first() book = author.book_set.all()
4.基于双下划线查询表记录(连表查询)
# 正向查询 ( 按字段,跨表可以在filter,也可以在values中 ) photo = Author.objects.filter(name='lxx').values('authordatil__photo') print(photo) # 反向查询( 按表名小写,跨表可以在filter,也可以在values中 ) photo = Authordatil.objects.filter(author__name='lxx').values('photo') print(photo) # 正向连续跨表查询( 按字段,跨表可以在filter,也可以在values中 ) name = Publish.objects.filter(name='武汉出版社').values('book__authors__authordatil__photo') # 反向连续跨表查询( 按表名小写,跨表可以在filter,也可以在values中 ) photo = Author.objects.filter(book__publish__name='武汉出版社').values('book__authors__authordatil__photo')
''' 练习一: 1 用orm插入6个作者详情,插入6个作者 2 用orm插入6个出版社 3 用orm插入8本书,4种用publish=对象的形式,4种用publish_id=id的形式 4 两种形式修改书的出版社 5 基于对象查询,地址为山东的作者的姓名 ( 一对一 ) 6 基于对象查询,电话为13888888作者的性别 ( 一对一 ) 7 基于双下划线查询,地址为山东的作者的姓名 8 基于双下划线查询,电话为13888888作者的性别 9 基于对象查询北京出版社出版的所有图书 9 基于对象查询南京出版社出版的价格大于20的图书(一对多) 10 基于对象查询图书名字叫红楼梦这本书的作者(多对多) 11基于对象查询作者名为lqz,出版的所有图书 12 基于对象查询作者名为lqz,出版的价格大于20的所有图书 13 基于对象查询图书名以红开头,所有的出版社信息 14基于对象查询图书名以红开头,出版社以社结尾的所有出版社地址 15 查询所有价格大于20的图书 16 查询所有价格大于20的图书所有的出版社 17 查询手机号以13开头,所有的作者 18查询手机号以13开头,所有作者出版的所有图书 19 查询图书价格在[19.9,56,77.9]内的所有图书 20 查询图书价格在[19.9,56,77.9]内的所有图书,对应的所有作者 21 查询图书价格在[19.9,56,77.9]内的所有图书,对应的所有作者的手机号 ''' # 4 两种形式修改书的出版社 #方法(1) book = Book.objects.filter(name='红楼梦').first() book.publish_id = 2 book.publish = publish book.save() # 方法(2) publish = Publish.objects.filter(name='深圳出版社').first() book = Book.objects.filter(name='红楼梦').first() book.publish = publish book.save() # 5 基于对象查询,地址为山东的作者的姓名 ( 一对一 ) authordatil = Authordatil.objects.filter(address='山东').first() name = authordatil.author.name # 6 基于对象查询,电话为13888888作者的性别 ( 一对一 ) authordatil = Authordatil.objects.filter(photo = 133323223).first() sex = authordatil.author.sex # 7 基于双下划线查询,地址为山东的作者的姓名 authordatil = Authordatil.objects.filter(address='东京').values('author__name') # 8 基于双下划线查询,电话为13888888作者的性别 sex = Authordatil.objects.first(photo=133323223).values('author__sex') # 9 基于对象查询北京出版社出版的所有图书 publish = Publish.objects.filter(name='杭州出版社').first() books = publish.book_set.all() # 9 基于对象查询南京出版社出版的价格大于20的图书(一对多) publish = Publish.objects.filter(name='杭州出版社').first() book = publish.book_set.all().filter(price__gt=20) # 10 基于对象查询图书名字叫红楼梦这本书的作者(多对多) book = Book.objects.filter(name='红楼梦').first() authors = book.authors.all().values('name') # 11基于对象查询作者名为lqz,出版的所有图书 author = Author.objects.filter(name='lxx').first() book = author.book_set.all() # 12 基于对象查询作者名为lqz,出版的价格大于20的所有图书 author = Author.objects.filter(name='lxx').first() book = author.book_set.all().filter(price__gt=31) # 13 基于对象查询图书名以红开头,所有的出版社信息 book = Book.objects.filter(name__startswith='红').first() publish = book.publish # 14基于对象查询图书名以红开头,出版社以社结尾的所有出版社地址 book = Book.objects.filter(name__startswith='红').values_list('publish__address') print(book) publish = Publish.objects.filter(address__endswith='社').values_list('address') for i in publish: if i in book: print(i) # 15 查询所有价格大于20的图书 book = Book.objects.filter(price__gt=20).all() # 16 查询所有价格大于20的图书所有的出版社 books = Book.objects.filter(price__gt=20) for book in books: publish = book.publish print(publish) # 17 查询手机号以13开头,所有的作者 #方法一: authordatils = Authordatil.objects.filter(photo__startswith=13).values('author__name') # 方法二: authordatils = Authordatil.objects.filter(photo__startswith=13) for authordatil in authordatils: author = authordatil.author print(author) # 18查询手机号以13开头,所有作者出版的所有图书 #方法一: books = Authordatil.objects.filter(photo__startswith=13).values('author__book__name') # 方法二: authordatils = Authordatil.objects.filter(photo__startswith=13).first() # 拿到信息表 再到作者 再到书 book = authordatils.author.book_set.all() # 19 查询图书价格在[19.9,56,77.9]内的所有图书 book = Book.objects.filter(price__in=[19.9, 56, 77.9]).all() # 20 查询图书价格在[19.9,56,77.9]内的所有图书,对应的所有作者 # 方法一: author = Book.objects.filter(price__in=[19.9, 56, 77.9]).values('authors') # 方法二: books = Book.objects.filter(price__in=[19.9, 56, 77.9]) for book in books: author = book.authors.all() # 21 查询图书价格在[19.9,56,77.9]内的所有图书,对应的所有作者的手机号 # 方法一: books = Book.objects.filter(price__in=[19.9, 56, 77.9]).values('authors__authordatil__photo') # 方法二: books = Book.objects.filter(price__in=[19.9, 56, 77.9]).all() for book in books: authors = book.authors.all() for author in authors: photo = author.authordatil.photo print(photo) ''' 作业二: 1 修改名字为lqz作者的手机号为12345678901 2 修改以红开头的图书的所有作者手机号为123321321 3 修改出版社是北京出版社出版的所有图书的价格为99.99 4 为红楼梦这本书,新增lqz,egon两个作者(两种方式) 5 更改红楼梦这本书的作者为lqz,xiaohou(两种方式) ?????????? 6 把上题lxx 换成 egon 6 删除红楼梦这本书xiaohou这个作者 7 清空红楼梦这本书所有作者 8 查询图书价格大于30的所有作者的名字 9 查询北京出版社出版的所有图书的作者名字 10 查询北京出版社出版的所有图书的作者手机号 11 查询西游记这本书所有作者的个数 12 查询北京出版社出版的图书个数 ''' # 1 修改名字为lqz作者的手机号为12345678901 author = Author.objects.filter(name='lxx').first() authordatil = author.authordatil authordatil.photo = 12345678901 authordatil.save() # 2 修改以红开头的图书的所有作者手机号为123321321 books = Book.objects.filter(name__startswith='红') for book in books: authors = book.authors.all() for author in authors: authordatil = author.authordatil authordatil.photo = 123321321 authordatil.save() # 3 修改出版社是北京出版社出版的所有图书的价格为99.99 publish = Publish.objects.filter(name='长沙出版社').first() books = publish.book_set.all() for book in books: book.price = 99.99 book.save() print(book.price) # 4 为红楼梦这本书,新增lqz,egon两个作者(两种方式) # 方法一: book = Book.objects.filter(name='红楼梦').first() book.authors.add(4,5) # 方法二: egon = Author.objects.filter(name= 'egon').first() wxx = Author.objects.filter(name='wxx').first() book = Book.objects.filter(name='红楼梦').first() book.authors.add(egon,wxx) # 5 更改红楼梦这本书的作者为lqz,xiaohou(两种方式) ?????????? book = Book.objects.filter(name='红楼梦').first() authors = book.authors.clear() print(authors) lxx = Author.objects.filter(name='lxx').first() zxx = Author.objects.filter(name='zxx').first() book.authors.set([lxx,zxx]) # 把lxx 换成 egon lxx =Author.objects.filter(name='lxx').first() egon = Author.objects.filter(name='egon').first() book = Book.objects.filter(name='边城').first() book.authors.remove(lxx) book.authors.set([egon,]) # 6 删除红楼梦这本书xiaohou这个作者 lxx = Author.objects.filter(name='lxx').first() book = Book.objects.filter(name='红楼梦').first() book.authors.remove(lxx) # 7 清空红楼梦这本书所有作者 book = Book.objects.filter(name='红楼梦').first() book.authors.clear() # 8 查询图书价格大于30的所有作者的名字 book = Book.objects.filter(price__gt=30).values('authors__name','price') # 9 查询北京出版社出版的所有图书的作者名字 publish = Publish.objects.filter(name='武汉出版社').values('book__authors__name') # 10 查询北京出版社出版的所有图书的作者手机号 name = Publish.objects.filter(name='武汉出版社').values('book__authors__authordatil__photo') # 11 查询西游记这本书所有作者的个数 book = Book.objects.filter(name='西游记').first() con = book.authors.all().count() # 12 查询北京出版社出版的图书个数 publish = Publish.objects.filter(name='武汉出版社').first() con = publish.book_set.all().count()
5.聚合查询(aggregate)
from django.db.models import Avg,Count,Min,Max,Sum con = Book.objects.all().aggregate(Max('price'),Min('price'),Avg('price'),Sum('price')) # 计算所有图书的平均价格 con = Book.objects.all().aggregate(Avg('price')) print(con) # 计算图书的最高价格 con = Book.objects.all().aggregate(Max('price')) print(con) # 计算图书的最高价格,最低价格,平均价格,总价 con = Book.objects.all().aggregate(Max('price'),Min('price'),Avg('price'),Sum('price')) print(con)
6.分组查询(annotate)
''' group by 谁,就以谁做基表,filter过滤,annotate取分组,values取值 values在前 以谁分组 values在后 表示 取值 filter在前 where条件 filter在后 表示 having ''' # 统计每一本书作者个数 con = Book.objects.values('pk').all().annotate(c= Count('authors')).values('name','c') print(con) # 统计每一个出版社的最便宜的书 con = Publish.objects.values('pk').all().annotate(c= Min('book__price')).values('name','c') print(con) # 统计每一本以py开头的书籍的作者个数 con = Book.objects.filter(name__startswith='红').annotate(c=Count('authors')).values('name','c') print(con) # 统计每一本以py开头的书籍的作者个数--套用模板 con = Book.objects.filter(name__startswith='红').all().annotate(c=Count('authors')).values('name', 'c') print(con) # 查询各个作者出的书的总价格 con = Author.objects.annotate(c= Sum('book__price')).values('name','c') print(con) # 查询名字叫lqz作者书的总价格 con = Author.objects.filter(name='egon').annotate(c= Sum('book__price')).values('name','c') print(con) # 查询所有作者写的书的总价格大于30 con = Author.objects.annotate(c=Sum('book__price')).filter(c__gt=70).values('name', 'c') print(con) # 统计不止一个作者的图书 con = Book.objects.annotate(c = Count('authors')).filter(c__gt=1).values('name','c') print(con) # F查询 # 查询评论数大于阅读数的书 from django.db.models import F con = Book.objects.filter(commit_num__gt=F('read_num')).values('name') print(con) # 把所有书的评论数加1 con = Book.objects.all().update(commit_num=F('read_num')+1) print(con) # 把python这本书的阅读数减5 con = Book.objects.filter(name='红楼梦').all().update(read_num=F('read_num') -5 ) print(con)
7.F查询
''' 无法引用字段上的值,把字段名的值包裹起来,就能用了 from django.db.models import F eg: Book.objects.filter(id=1).update(F("price")+1) # 将第一本书的价格加一 ''' # 查询评论数大于阅读数的书 from django.db.models import F con = Book.objects.filter(commit_num__gt=F('read_num')).values('name') print(con) # 把所有书的评论数加1 con = Book.objects.all().update(commit_num=F('read_num')+1) print(con) # 把python这本书的阅读数减5 con = Book.objects.filter(name='红楼梦').all().update(read_num=F('read_num') -5 ) print(con)
8.Q查询
from django.db.models import Q # 与 & 或 | 非 ~ #Q查询: 基于关系运算 &与 |或 ~非 # &与 (默认为 与) # 查看价格为15 与(且) 名字为金瓶眉的书 Book.objects.filter(Q(price=15),Q(name="金瓶眉”)) # 查看价格为15 或 名字为金瓶眉的书 Book.objects.filter(Q(price=15) | Q(name="金瓶眉”)) # 查看价格不为15 且 名不为金瓶眉的书 Book.objects.filter(~Q(price=15) & ~Q(name="金瓶眉”)) # 查询作者名字是lqz或者名字是egon的书 con = Author.objects.filter(Q(name='lxx') | Q(name='wxx')).values('book__name') print(con) # 查询作者不是lqz的书 # con = Author.objects.filter(~Q(name='lxx')).values('book__name') con = Author.objects.filter(~Q(name='lxx')).values('book__name') print(con) con = Book.objects.filter(~Q(authors__name='lxx')).values('name') print(con) # 构建很复杂的逻辑, 需要用括号来区分 ret = Book.objects.filter((Q(name='红楼梦') & Q(price__gt=100)) | Q(pk__gt=2)) print(ret)
相关文章推荐
- Django之模型层(单表操作)
- Django模型系统(二)-------数据操作
- django中模型的简单操作
- django模型中外键操作
- 通过数据库对Django进行删除字段和删除模型的操作
- Django之模型层多表操作的实现
- 第六章 python django 数据库【ORM模型 模型增减改查 模型常用属性 外键 表关系 模型操作 查询操作 聚合函数 QuerySet】
- django Model模型二及Model模型对数据库的操作
- Django框架学习 — 7.5模型详解 -- 增删改操作
- Django的ORM模型操作数据库
- Django项目实践3 - Django模型(字段、数据库操作及模型继承)
- django创建用户后,修改了用户模型的操作
- Django模型操作
- django2.0中model模型操作
- Django 1.10.2 模型数据库操作
- Django--model模型绑定_数据库操作
- Django学习之模型的操作详解
- Django模型操作常用方法总结
- Django模型操作常用方法总结
- Django项目实践3 - Django模型(字段、数据库操作及模型继承)