一.模型关系表 1. 一对一 Author-AuthorDetail 关联字段可以在任意表下,但必须唯一约束。(unique约束) ad_id(unique约束) ad = models.oneToOneField("AuthorDetail",null=True,on_delete=models.CASCADE) 相当于 authors = models.ForgeinKey(to="Author",on_delete=models.CASCADE,unique) 2. 一对多 publish-book 关联字段在“多”的表中 建立ForgeinKey 约束 3. 多对多 book-author 关系表 foreinkey book_id references Book(id) foreinkey author_id references Author(id) authors = models.ManyToManyField("Author") 二.多表查询 a.一定要知道mysql 语句 b.增删改查 ========================================================================================================================= 1. 添加 create 添加记录的思路:考虑 三种关系表的特殊字段 Book.objects.create(title="python",price=123,pub_date="2012-12-12",publish_id=1) #数据库级别 def add(request): ======================绑定一对多关系=========================================== #一对多:(publish-book) 方式一: Book.objects.create(title="python",price=123,pub_date="2012-12-12",publish_id=1) 方式二: pub_obj = Publish.objects.filter(name= "苹果出版社").first() Book.objects.create(title="python",price=123,pub_date = "2012-11-12",publish=pub_obj) python = Book.objects.filter(title="python").first() python.publish #得到的是python这本书对应的出版社对象 ===================绑定多对多关系:无非是在第3张关系表中创建记录===================== 正向操作按字段,反向操作按表名小写 #多对多:(authors-book) key:一定要找到多对多关联属性在哪张表下,如Book下的authors,先找到book对象,再用该书籍对象 点关联字段 1.给python这本书绑定两个作者:alex egon python = Book.objects.filter(title="python").first() alex = Author.objects.filter(name="alex").first() egon = Author.objects.filter(name="egon").first() python.authors.add(alex,egon) python.authors.add(1,2) #1,2分别为alex,egon的主键 python.authors.add(*[1,2,3,4,5]) #打散传 python.authors.remove(alex,egon) python.authors.clear() #解除所有绑定 python.authors.set([1,]) #先清空,在赋值操作 2. 给alex作者绑定两本书籍 python和linux alex = Author.objects.filter(name="alex").first() python= Book.objects.filter(title="python").first() linux= Book.objects.filter(title="linux").first() alex.book_set.add(alex,linux) ========================================================================================================================== 2.查询 def queryset(request): ===============================基于对象的跨表查询================================ 基于对象的跨表查询:(sql语句 子查询:以上一次的查询结果作为下一次的查询条件) 1.一对多: 正向查询按字段publish linux.publish Book----------------------------------------------Publish 反向查询按表名小写_set.all() 1.查询linux这本书籍出版社的邮箱 linux = Book.objects.filter(title="linux").first() print(linux.publish.emial) 2.查询苹果出版社出版的所有书籍 p1 = Publish.objects.filter(name="苹果出版社").first() queryset = p1.book_set.all() 2. 多对多: 正向查询按字段authors book_obj.authors.all() Book---------------------------------------------------Author 反向查询按表名小写_set().all() 1.查询linux这本书所有作者 linux= Book.objects.filter(title="linux").first() queryset = linux.authors.all() 2.查询作者alex出版过的所有书籍 alex = Author.objects.filter(name="alex").first() queryset = alex.book_set.all() 3. 一对一: 正向查询按字段ad, author_obj.ad Author--------------------------------------------AuthorDetail 反向查询按表名小写 Authordetail_obj.author 1.查询alex手机号 alex= Author.objects.filter(name="alex").first() alex.ad.telphone 2.查询手机号为123的作者 ad_obj = AuthorDetail.objects.filter(telphone=123).first() print(ad_obj.author.name) =================================基于双下滑线的跨表查询(join查询)======================================= 把多张表合成一张表,按单表查。 key: 通知orm引擎,进行跨表,正向查询按表名,反向查询按表名小写 1.一对多 1.查询linux这本书籍出版社的邮箱 sql : select email from book inner join publish on book.publish_id = publish.id where book.title='linux' orm :(values 显示查询字段) #方式一 queryset = Book.objects.filter(title="linux").values("publish__email") #方式二 queryset = Publish.objects.filter(book__title = "linux").value("email") 2.多对多 1.查询linux这本书的所有作者名字 sql: select author.name from book left join book2authors on book.id = book2authors.book_id left join author on author.id = book2authors.author_id where book.title="linux" orm: 方式一: queryset = Book.objects.filter(title="linux").values("authors__name") left join 显示左边表中所有的数据 inner join如果基表没有数据就不显示第二个表中的那部分数据 方式二: queryset = Author.objects.filter(book__title="linux").values('name') 3. 一多一 1.查询alex手机号 方式一: queryset = Author.objects.filter(name="alex").values("ad__telphone") 方式二: queryset = AuthorDetail.objects.filter(author__name="alex").values("telphone") 4.连续跨表查询 1.查询人民出版社出版过的所有书籍名称以及作者名字 Publish.objects.filter(name="人民出版社").values("book__name","book__authors__name") Book.objects.filter(publish__name="人民出版社").values("name","authors__name") 2.手机号以151开头的作者出版过的所有书籍名称以及所有出版社名称 Author.objects.filter(ad__telphone__startswith=151).values("book__name","book__publish__name") ================================聚合和分组查询============================================ 1.聚合(aggregate 只对一组进行统计) from django.db.models import Avg,Count,Max,Min 1.计算所有图书的平均价格 Book.objects.all().aggregate(avg_price=Avg("price")) 2. 计算所有图书的最高价和最低价 Book.objects.all().aggregate(min_price=Min("price"),max_price=Max('price')) 2.分组查询 (annotate 对多组数据进行统计) 1.单表分组: emp id name salary dep province 1 alex 20000 销售部 山东 2 egon 30000 人事部 河北 3 wang 40000 人事部 山东 查询 : 每个部门的名称以及员工人数 sql: select dep,Count(*) from emp group by dep; select dep,Avg(salary) from emp group by dep; orm: 按哪个字段group by 就 values 哪个字段,用annotate 统计 1.查询每个部门的名字 queryset = Emp.objects.values("dep").annotate(c=Count("*")) 2.查询每个省份的平均薪水 queryset= Emp.objects.values("province").annotate(avg_salary=Avg("salary")) 2.多表分组:(多张关联表) key:多张表join起来,再按单表查 1.查询每个出版社的名称以及出版过书籍的平均价格 sql: select publish.name,Avg(book.price) from publish left join book on publish.id = book.publish_id group by publish.id,publish.name orm: 方式一: queryset = Publish.objects.values("name","id").annotate(avg_price =avg("book__price")) 方式二: queryset = Publish.objects.all().annotate(avg_price =avg("book__price")) 2.查询每一个作者的名字以及出版书籍的个数 方式一: queryset = Author.objects.values("name").annotate(book_num=Count("book")) 方式二: queryset = Author.objects.annotate(book_num=Count("book")).values("book_num","name") 3.查询每本书籍名称以及作者个数 queryset = Book.objects.annotate(c=Count("authors")).values("title",c) 4.查询作者个数大于1的书籍名称和作者个数 sql: select book.tilte,Count(author.id) as c from book left join book2authors on book.id = book2authors.book_id left join Author on book2authors.author_id group by book.id having c>1 orm: queryset = Book.objects.annotate(c=Count("authors")).filter(c__gt=1).values("title","c") (相当于having) 5.查询书籍名称包含“h"的书籍名称和作者个数 Book.objects.filter(title__icontains='h').annonate(c=Count('authors')).values("title",c) (相当于where) ====================================F查询和Q查询=================================================== from django.db.models import F,Q,Avg 1.F查询 1.查询评论数大于100的文章 Article.objects.filter(comment_num__gt=100) 2.查询评论数大于点赞数的文章 Article.objects.filter(comment_num__gt=F(poll_num)) 3.查询评论数大于100的所有文章 queryset = Article.objects.filter(comment_num__gt=F("poll_num")*2) 4.将所有书籍的价格提高一百元 Book.objects.update(price=F("price")+100) 2.Q查询 (|或 &且 ~非) 1.查询价格大于200或名称以"p"开头的书籍 queryset = Book.objects.all().filter(Q(price__gt=200)|Q(title__startswith="p") 2.查询价格大于300或出版日期(不是)为2019年一月份的书籍 queryset= Book.objects.filter(Q(price__gt=300)|~Q(Q(pub_date_year=2019)&Q(pub_date_month=1)))
一.模型关系表 1. 一对一 Author-AuthorDetail 关联字段可以在任意表下,但必须唯一约束。(unique约束) ad_id(unique约束) ad = models.oneToOneField("AuthorDetail",null=True,on_delete=models.CASCADE) 相当于 authors = models.ForgeinKey(to="Author",on_delete=models.CASCADE,unique) 2. 一对多 publish-book 关联字段在“多”的表中 建立ForgeinKey 约束 3. 多对多 book-author 关系表 foreinkey book_id references Book(id) foreinkey author_id references Author(id) authors = models.ManyToManyField("Author")二.多表查询 a.一定要知道mysql 语句 b.增删改查========================================================================================================================= 1. 添加 create 添加记录的思路:考虑 三种关系表的特殊字段 Book.objects.create(title="python",price=123,pub_date="2012-12-12",publish_id=1) #数据库级别 def add(request): ======================绑定一对多关系=========================================== #一对多:(publish-book) 方式一: Book.objects.create(title="python",price=123,pub_date="2012-12-12",publish_id=1) 方式二: pub_obj = Publish.objects.filter(name= "苹果出版社").first() Book.objects.create(title="python",price=123,pub_date = "2012-11-12",publish=pub_obj) python = Book.objects.filter(title="python").first() python.publish #得到的是python这本书对应的出版社对象 ===================绑定多对多关系:无非是在第3张关系表中创建记录===================== 正向操作按字段,反向操作按表名小写 #多对多:(authors-book) key:一定要找到多对多关联属性在哪张表下,如Book下的authors,先找到book对象,再用该书籍对象 点关联字段 1.给python这本书绑定两个作者:alex egon python = Book.objects.filter(title="python").first() alex = Author.objects.filter(name="alex").first() egon = Author.objects.filter(name="egon").first() python.authors.add(alex,egon) python.authors.add(1,2) #1,2分别为alex,egon的主键 python.authors.add(*[1,2,3,4,5]) #打散传 python.authors.remove(alex,egon) python.authors.clear() #解除所有绑定 python.authors.set([1,]) #先清空,在赋值操作 2. 给alex作者绑定两本书籍 python和linux alex = Author.objects.filter(name="alex").first() python= Book.objects.filter(title="python").first() linux= Book.objects.filter(title="linux").first() alex.book_set.add(alex,linux)========================================================================================================================== 2.查询 def queryset(request): ===============================基于对象的跨表查询================================ 基于对象的跨表查询:(sql语句 子查询:以上一次的查询结果作为下一次的查询条件) 1.一对多: 正向查询按字段publish linux.publish Book----------------------------------------------Publish 反向查询按表名小写_set.all() 1.查询linux这本书籍出版社的邮箱 linux = Book.objects.filter(title="linux").first() print(linux.publish.emial) 2.查询苹果出版社出版的所有书籍 p1 = Publish.objects.filter(name="苹果出版社").first() queryset = p1.book_set.all() 2. 多对多: 正向查询按字段authors book_obj.authors.all() Book---------------------------------------------------Author 反向查询按表名小写_set().all() 1.查询linux这本书所有作者 linux= Book.objects.filter(title="linux").first() queryset = linux.authors.all() 2.查询作者alex出版过的所有书籍 alex = Author.objects.filter(name="alex").first() queryset = alex.book_set.all() 3. 一对一: 正向查询按字段ad, author_obj.ad Author--------------------------------------------AuthorDetail 反向查询按表名小写 Authordetail_obj.author 1.查询alex手机号 alex= Author.objects.filter(name="alex").first() alex.ad.telphone 2.查询手机号为123的作者 ad_obj = AuthorDetail.objects.filter(telphone=123).first() print(ad_obj.author.name) =================================基于双下滑线的跨表查询(join查询)======================================= 把多张表合成一张表,按单表查。 key: 通知orm引擎,进行跨表,正向查询按表名,反向查询按表名小写 1.一对多 1.查询linux这本书籍出版社的邮箱 sql : select email from book inner join publish on book.publish_id = publish.id where book.title='linux' orm :(values 显示查询字段) #方式一 queryset = Book.objects.filter(title="linux").values("publish__email") #方式二 queryset = Publish.objects.filter(book__title = "linux").value("email") 2.多对多 1.查询linux这本书的所有作者名字 sql: select author.name from book left join book2authors on book.id = book2authors.book_id left join author on author.id = book2authors.author_id where book.title="linux" orm: 方式一: queryset = Book.objects.filter(title="linux").values("authors__name") left join 显示左边表中所有的数据 inner join如果基表没有数据就不显示第二个表中的那部分数据 方式二: queryset = Author.objects.filter(book__title="linux").values('name') 3. 一多一 1.查询alex手机号 方式一: queryset = Author.objects.filter(name="alex").values("ad__telphone") 方式二: queryset = AuthorDetail.objects.filter(author__name="alex").values("telphone") 4.连续跨表查询 1.查询人民出版社出版过的所有书籍名称以及作者名字 Publish.objects.filter(name="人民出版社").values("book__name","book__authors__name") Book.objects.filter(publish__name="人民出版社").values("name","authors__name") 2.手机号以151开头的作者出版过的所有书籍名称以及所有出版社名称 Author.objects.filter(ad__telphone__startswith=151).values("book__name","book__publish__name") ================================聚合和分组查询============================================ 1.聚合(aggregate 只对一组进行统计) from django.db.models import Avg,Count,Max,Min 1.计算所有图书的平均价格 Book.objects.all().aggregate(avg_price=Avg("price")) 2. 计算所有图书的最高价和最低价 Book.objects.all().aggregate(min_price=Min("price"),max_price=Max('price')) 2.分组查询 (annotate 对多组数据进行统计) 1.单表分组: emp id name salary dep province 1 alex 20000 销售部 山东 2 egon 30000 人事部 河北 3 wang 40000 人事部 山东 查询 : 每个部门的名称以及员工人数 sql: select dep,Count(*) from emp group by dep; select dep,Avg(salary) from emp group by dep; orm: 按哪个字段group by 就 values 哪个字段,用annotate 统计 1.查询每个部门的名字 queryset = Emp.objects.values("dep").annotate(c=Count("*")) 2.查询每个省份的平均薪水 queryset= Emp.objects.values("province").annotate(avg_salary=Avg("salary")) 2.多表分组:(多张关联表) key:多张表join起来,再按单表查 1.查询每个出版社的名称以及出版过书籍的平均价格 sql: select publish.name,Avg(book.price) from publish left join book on publish.id = book.publish_id group by publish.id,publish.name orm: 方式一: queryset = Publish.objects.values("name","id").annotate(avg_price =avg("book__price")) 方式二: queryset = Publish.objects.all().annotate(avg_price =avg("book__price")) 2.查询每一个作者的名字以及出版书籍的个数 方式一: queryset = Author.objects.values("name").annotate(book_num=Count("book")) 方式二: queryset = Author.objects.annotate(book_num=Count("book")).values("book_num","name") 3.查询每本书籍名称以及作者个数 queryset = Book.objects.annotate(c=Count("authors")).values("title",c) 4.查询作者个数大于1的书籍名称和作者个数 sql: select book.tilte,Count(author.id) as c from book left join book2authors on book.id = book2authors.book_id left join Author on book2authors.author_id group by book.id having c>1 orm: queryset = Book.objects.annotate(c=Count("authors")).filter(c__gt=1).values("title","c") (相当于having) 5.查询书籍名称包含“h"的书籍名称和作者个数 Book.objects.filter(title__icontains='h').annonate(c=Count('authors')).values("title",c) (相当于where) ====================================F查询和Q查询=================================================== from django.db.models import F,Q,Avg 1.F查询 1.查询评论数大于100的文章 Article.objects.filter(comment_num__gt=100) 2.查询评论数大于点赞数的文章 Article.objects.filter(comment_num__gt=F(poll_num)) 3.查询评论数大于100的所有文章 queryset = Article.objects.filter(comment_num__gt=F("poll_num")*2) 4.将所有书籍的价格提高一百元 Book.objects.update(price=F("price")+100) 2.Q查询 (|或 &且 ~非) 1.查询价格大于200或名称以"p"开头的书籍 queryset = Book.objects.all().filter(Q(price__gt=200)|Q(title__startswith="p") 2.查询价格大于300或出版日期(不是)为2019年一月份的书籍 queryset= Book.objects.filter(Q(price__gt=300)|~Q(Q(pub_date_year=2019)&Q(pub_date_month=1)))