10 django模型层_多表

模型层_多表

建表&绑定关系

06 django模型层\tables\tables_app001\models.py

 1 from django.db import models
 2 
 3 # Create your models here.
 4 
 5 
 6 class Publish(models.Model):
 7     id = models.AutoField(primary_key=True)
 8     name = models.CharField(max_length=32)
 9     city = models.CharField(max_length=32)
10     email = models.EmailField()
11 
12     def __str__(self):
13         return self.name
14 
15 
16 class Author(models.Model):
17     id = models.AutoField(primary_key=True)
18     name = models.CharField(max_length=32)
19 
20     # 一对一  与AuthorDetail
21     authorDetail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
22 
23     def __str__(self):
24         return self.name
25 
26 
27 class AuthorDetail(models.Model):
28     id = models.AutoField(primary_key=True)
29     age = models.BigIntegerField()
30     addr = models.CharField(max_length=32)
31     phone = models.BigIntegerField()
32 
33     def __str__(self):
34         return self.age
35 
36 
37 class Books(models.Model):
38     id = models.AutoField(primary_key=True)
39     title = models.CharField(max_length=32, unique=True)
40     price = models.DecimalField(max_digits=5, decimal_places=2)
41     pub_date = models.DateField()
42     read_num = models.BigIntegerField(default=0)
43     comment_num = models.BigIntegerField(default=0)
44 
45     # 一对多
46     publish = models.ForeignKey(to='Publish', to_field='id', on_delete=models.CASCADE)
47 
48     # 多对多    自动创建第三张表  book_authors
49     authors = models.ManyToManyField(to='Author',)
50 
51     def __str__(self):
52         return self.title
53 
54 
55 class Employee(models.Model):
56     id = models.AutoField(primary_key=True)
57     name = models.CharField(max_length=32, unique=True)
58     age = models.BigIntegerField()
59     sal = models.DecimalField(max_digits=5, decimal_places=1)
60     dep = models.CharField(max_length=32)
61 
62     def __str__(self):
63         return self.title

 

 增删改查

  1 from django.shortcuts import render, HttpResponse
  2 from tables_app001.models import *
  3 
  4 # Create your views here.
  5 
  6 
  7 def add(request):
  8 
  9     ###################    单表插入记录   ####################
 10     Publish.objects.create(name='人民出版社', city='北京', email='qwe@qq.com')
 11     Publish.objects.create(name='湖南出版社', city='湖南', email='hn@qq.com')
 12     Publish.objects.create(name='深圳出版社', city='深圳', email='sz@qq.com')
 13     AuthorDetail.objects.create(age=18, addr='湖南', phone='13537730001')
 14     AuthorDetail.objects.create(age=28,  addr='湖南', phone='13537730002')
 15     AuthorDetail.objects.create(age=38,  addr='深圳', phone='13537730003')
 16 
 17     ##################    一对一插入记录   ####################
 18     detail_obj1 = AuthorDetail.objects.filter(id=1).first()
 19     detail_obj2 = AuthorDetail.objects.filter(id=2).first()
 20     detail_obj3 = AuthorDetail.objects.filter(id=3).first()
 21     Author.objects.create(name='杨一', authorDetail_id=detail_obj1.id)
 22     Author.objects.create(name='杨二', authorDetail=detail_obj2)
 23     Author.objects.create(name='杨三', authorDetail=detail_obj3)
 24 
 25     ##################    一对一插入记录   ####################
 26     publish_obj = Publish.objects.filter(id=1).first()
 27     book_obj1 = Books.objects.create(title='盘龙', price=16, pub_date='2018-12-12', publish=publish_obj)
 28     book_obj2 = Books.objects.create(title='星辰变', price=20, pub_date='2017-12-12', publish=publish_obj)
 29 
 30 
 31     ##################    多对多插入记录 add 方法  ####################
 32     book_obj1 = Books.objects.filter(id=1).first()
 33     book_obj2 = Books.objects.filter(id=2).first()
 34 
 35     author_obj1 = Author.objects.filter(name='杨一').first()
 36     author_obj2 = Author.objects.filter(name='杨二').first()
 37     author_obj3 = Author.objects.filter(name='杨三').first()
 38 
 39     book_obj1.authors.add(author_obj1, author_obj2, author_obj3)
 40     # book_obj2.authors.add(1)
 41     book_obj2.authors.add(*[1,4])
 42 
 43 
 44     ##################    解除多对多的关系   ####################
 45     # book_obj1.authors.remove(1)
 46     # book_obj1.authors.remove(*[4,])
 47     # book_obj1.authors.remove(author_obj3)
 48     # book_obj1.authors.clear()  # 删除所有
 49 
 50 
 51     return HttpResponse('OJBK!')
 52 
 53 
 54 def query(request):
 55     """
 56     跨表查询:
 57        1 基于对象查询
 58        2 基于双下划线查询
 59        3 聚合和分组查询
 60        4 F 与 Q查询
 61     """
 62     # -------------------------基于对象的跨表查询(子查询)-----------------------
 63     # 一对多查询的正向查询 : 查询盘龙这本书的出版社的名字
 64     res = Books.objects.filter(title='盘龙').first().publish.name
 65     # 一对多查询的反向查询 : 查询人民出版社出版过的书籍名称
 66     res = Publish.objects.filter(name='人民出版社').first().books_set.all().values('title')
 67     # 多对多查询的正向查询 : 查询星辰变这本书的所有作者的名字
 68     res = Books.objects.filter(title='星辰变').first().authors.all().values('name')
 69     # 多对多查询的反向查询 : 查询杨一出版过的所有书籍名称
 70     res = Author.objects.filter(name='杨一').first().books_set.all().values('title')
 71     # 一对一查询的正向查询 : 查询杨二的手机号
 72     res = Author.objects.filter(name='杨二').first().authorDetail.phone
 73     # 一对一查询的反向查询 : 查询手机号为0001尾号的作者的名字
 74     res = AuthorDetail.objects.filter(phone__endswith='0001').first().author.name
 75 
 76 
 77     # -------------------------基于双下划线的跨表查询(join查询)-----------------------
 78     '''
 79         正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表
 80     '''
 81     # 一对多查询的正向查询 : 查询盘龙这本书的出版社的名字
 82     res = Books.objects.filter(title='盘龙').values('publish__name')
 83     # ----->  <QuerySet [{'publish__name': '人民出版社'}]>
 84 
 85     # 一对多查询的反向查询 : 查询人民出版社出版过的书籍名称
 86     res = Publish.objects.values('name').filter(books__title='盘龙')
 87     res = Publish.objects.filter(books__title='盘龙').values('name')  # 都可以
 88     # -----> <QuerySet [{'name': '人民出版社'}]>
 89 
 90     # 多对多查询的正向查询 : 查询星辰变这本书的所有作者的名字
 91     res = Books.objects.filter(title='星辰变').values('authors__name')
 92     # -----> <QuerySet [{'authors__name': '杨一'}, {'authors__name': '杨二'}]>
 93 
 94     # 多对多查询的反向查询 : 查询杨一出版过的所有书籍名称
 95     res = Author.objects.filter(books__title='星辰变').values('name')
 96     res = Author.objects.values('name').filter(books__title='星辰变')  # 都可以
 97     # -----> <QuerySet [{'name': '杨一'}, {'name': '杨二'}]>
 98 
 99     # 一对一查询的正向查询 : 查询杨二的手机号
100     res = Author.objects.filter(name='杨二').values('authorDetail__phone')
101     # -----> <QuerySet [{'authorDetail__phone': 13537730002}]>
102 
103     # 一对一查询的反向查询 : 查询手机号为0001尾号的作者的名字
104     res = AuthorDetail.objects.filter(phone__endswith='0001').values('author__name')
105     # ----->  <QuerySet [{'author__name': '杨一'}]>
106 
107     # 练习: 查询人民出版社出版过的所有书籍的名字以及作者的姓名
108     res = Books.objects.filter(publish__name='人民出版社').values('title', 'authors__name')
109 
110     # 练习: 手机号以0001结尾的作者出版过的所有书籍名称以及出版社名称
111     res = Author.objects.filter(authorDetail__phone__endswith='0001').values('books__title', 'books__publish__name')
112     # < QuerySet[{'books__title': '星辰变', 'books__publish__name': '人民出版社'}, {'books__title': '盘龙','books__publish__name': '人民出版社'}] >
113 
114 
115     # --------------  聚合 aggregate:返回值是一个字典,不再是queryset  --------------
116     # 查询所有书籍的平均价格
117     from django.db.models import Avg, Max, Min, Count, Sum
118     res = Books.objects.all().aggregate(Avg('price'))
119     # --------> {'price__avg': Decimal('18.000000')}
120     res = Books.objects.all().aggregate(avgPrice=Avg('price')) # 取别名
121     # --------> {'avgPrice': Decimal('18.000000')}
122 
123     # 查询价格最高的书籍
124     res = Books.objects.all().aggregate(Max('price'))
125     # -------->  {'price__max': Decimal('20.00')}
126 
127 
128     # ---------------  分组查询 annotate ,返回值依然是queryset  ---------------
129 
130     # ------------------------->单表分组查询:
131     # Employee.objects.create(name='steven', age=18, sal=1000, dep='销售部')
132     # Employee.objects.create(name='mike', age=28, sal=2000, dep='销售部')
133     # Employee.objects.create(name='ben', age=38, sal=1000, dep='销售部')
134     # Employee.objects.create(name='jack', age=48, sal=8000, dep='IT部')
135     # Employee.objects.create(name='Mary', age=18, sal=3000, dep='IT部')
136     # 单表分组查询的ORM语法: 单表模型.objects.values("group by的字段").annotate(聚合函数("统计字段"))
137 
138     # 查询每一个部门的名称以及员工的平均薪水
139     res = Employee.objects.values('dep').annotate(Avg('sal'))
140     # <QuerySet [{'dep': '销售部', 'sal__avg': Decimal('1333.33333')}, {'dep': 'IT部', 'sal__avg': Decimal('5500.00000')}]>
141 
142     # 查询每一个部门的名称以及员工数
143     res = Employee.objects.values('dep').annotate(Count('id'))
144     #  <QuerySet [{'dep': '销售部', 'id__count': 3}, {'dep': 'IT部', 'id__count': 2}]>
145 
146     # ------------------------->多表分组查询:
147     # Books.objects.create(title='吞噬星空', price=30, pub_date='2017-12-12', publish_id=2)
148     # Books.objects.create(title='蛮荒记', price=40, pub_date='2017-12-12', publish_id=2)
149 
150     ## 示例1 查询每一个出版社的名称以及出版的书籍个数
151     res = Books.objects.values('publish__name').annotate(c=Count('id'))
152     res = Books.objects.values('publish__id').annotate(c=Count('id')).values('publish__name', 'c')
153     res = Publish.objects.values('id').annotate(c=Count('books__id')).values('name', 'c')
154     # <QuerySet [{'publish__name': '人民出版社', 'c': 2}, {'publish__name': '湖南出版社', 'c': 2}]>
155 
156     ## 示例2 查询每一个作者的名字以及出版过的书籍的最高价格
157     res = Author.objects.values('pk').annotate(Max('books__price'))
158     res = Author.objects.values('pk').annotate(max=Max('books__price')).values('name', 'max')
159     # <QuerySet [{'name': '杨一', 'max': Decimal('20.00')}, {'name': '杨二', 'max': Decimal('20.00')}, {'name': '杨三', 'max': Decimal('16.00')}]>
160 
161     # 总结 跨表的分组查询的模型:
162     # 每一个后表模型.objects.values("pk").annotate(聚合函数(关联表__统计字段))
163     # 示例3 查询每一个书籍的名称以及对应的作者个数
164     res = Books.objects.values('pk').annotate(c=Count('authors__id')).values('title','c')
165     # < QuerySet[{'title': '盘龙', 'c': 3}, {'title': '星辰变', 'c': 2}, {'title': '吞噬星空', 'c': 0}, {'title': '蛮荒记', 'c': 0}] >
166 
167     #################### 跨表分组查询的另一种玩法  ####################
168     # 示例1 查询每一个出版社的名称以及出版的书籍个数
169     res = Publish.objects.values('pk').annotate(c=Count('books__id')).values('name','c')
170     res = Publish.objects.all().annotate(c=Count('books__id')).values('name','c')
171     res = Publish.objects.annotate(c=Count('books__id')).values('name','c')
172     # < QuerySet[{'name': '人民出版社', 'c': 2}, {'name': '湖南出版社', 'c': 2}, {'name': '深圳出版社', 'c': 0}] >
173 
174     ##################### 练习   ####################
175     # 统计每一本以'盘'开头的书籍的作者个数:
176     res = Books.objects.filter(title__startswith='').annotate(c=Count('authors__id')).values('title','c')
177     # <QuerySet [{'title': '盘龙', 'c': 3}]>
178 
179     # 统计不止一个作者的图书
180     res = Books.objects.annotate(c=Count('authors__id')).filter(c__gt=1).values('title','c')
181     # < QuerySet[{'title': '盘龙', 'c': 3}, {'title': '星辰变', 'c': 2}] >
182 
183     # 根据一本图书作者数量的多少对查询集QuerySet进行排序
184     res = Books.objects.annotate(c=Count('authors__id')).values('title', 'c').order_by('c')
185     # < QuerySet[{'title': '吞噬星空', 'c': 0}, {'title': '蛮荒记', 'c': 0}, {'title': '星辰变', 'c': 2}, {'title': '盘龙', 'c': 3}] >
186 
187     # 查询各个作者出的书的总价格:
188     res = Author.objects.annotate(total=Sum('books__price')).values('name','total')
189     # <QuerySet [{'name': '杨一', 'total': Decimal('36.00')}, {'name': '杨二', 'total': Decimal('36.00')}, {'name': '杨三', 'total': Decimal('16.00')}]>
190 
191     # 总结 跨表的分组查询的模型:
192     # 每一个后的表模型.objects.values("pk").annotate(聚合函数(关联表__统计字段)).values("表模型的所有字段以及统计字段")
193     # 每一个后的表模型.objects.annotate(聚合函数(关联表__统计字段)).values("表模型的所有字段以及统计字段")
194 
195 
196     # ###############  F 查询条件里包含字段  ###############
197     # 查询评论数大于阅读数的书记
198     from django.db.models import F
199     res = Books.objects.filter(read_num__gt=F('comment_num'))
200     # < QuerySet[ < Books: 盘龙 >, < Books: 星辰变 >] >
201 
202     # 所有书的价格上调 10%
203     res = Books.objects.update(price=F('price')*1.1)
204 
205 
206     # ###############  Q 查询条件关系  与或非 ###############
207     from django.db.models import Q
208     # 与 &
209     res = Books.objects.filter(price__lt=3, read_num__gt=100)
210     res = Books.objects.filter(Q(price__lt=3)&Q(read_num__lt=100))
211 
212     # 或 |
213     res = Books.objects.filter(Q(price__lt=3)|Q(read_num__lt=100))
214 
215     # 非 ~
216     res = Books.objects.filter(~Q(price__lt=3))
217 
218 
219     print(res)
220     return HttpResponse('OJBK!')

 

posted @ 2019-08-12 08:34  毛斯钢  阅读(166)  评论(0编辑  收藏  举报