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!')
夕闻道不如朝闻道