一 . 创建外键
一对一创建外键python
外键名称 = models.OneToOneField(to='要链接的类名', to_field='字段')
一对多创建外键mysql
外键名称 = models.ForeignKey(to='要链接的类名',to_field='字段') # 外键要写在一对多的 那个多的类 下面,好比一个老师对应不少学生,外键就要写在学生的下面
多对多创建外键git
外键名称 = models.ManyToManyField(to='另外一个类名') # 这个外键名称(属性)要写在其中一个类的下面,而后to=另外一个类名, 这个外键就至关于第三张表(多对多创建外键必须经过第三张表)
二 . 多表查询(基于子查询)
# models.py建立表 class Author(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) age = models.IntegerField() # to后面加类名 to_field后面写类名中的字段名 这是一对一的外键写法 author_detail = models.OneToOneField(to='AuthorDetail', to_field='id') def __str__(self): return self.name class AuthorDetail(models.Model): id = models.AutoField(primary_key=True) addr = models.CharField(max_length=16) tel = models.IntegerField() class Publish(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) addr = models.CharField(max_length=16) class Book(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) price = models.DecimalField(max_digits=6,decimal_places=2) # 在Book上publish变成了publish_id 这是一对多的外键写法 publish = models.ForeignKey(to='Publish',to_field='id') # 这个authors不是字段,他只是Book类里面的一个属性 这是多对多的创建第三张表的写法 authors = models.ManyToManyField(to='Author')
对authors(第三张表的操做)sql
# 给id=1的书籍添加id=5和id=6这两个做者 book_obj = models.Book.objects.filter(id=1)[0] book_obj.authors.add(*[5, 6]) # 数字的类型是int或者str都行 # 把id=1的书籍的做者所有删掉 book_obj = models.Book.objects.filter(id=1)[0] book_obj.authors.clear() # 把id=1的书籍中的id=5和id=6的这两个做者删掉 book_obj = models.Book.objects.filter(id=1)[0] book_obj.authors.remove(*[5, 6]) # 把id=1的书籍中的做者名更新成id=7和id=8这两个做者 book_obj = models.Book.objects.filter(id=1)[0] book_obj.authors.set([7, 8]) # set 不能用*[7, 8] set的执行流程是先把做者所有删除,而后添加[7, 8]
一对一正向查询(外键在哪一个表,他找别人就是正向)django
# 萧峰的住址 author_obj = models.Author.objects.get(name='萧峰') # author_obj.外键名.要查字段 print(author_obj.author_detail.addr) # author_detail = models.OneToOneField(to='AuthorDetail', to_field='id') # 这个author_detail就是外键名
一对一反向查询(没有外键的表查询有外键的表就是反向查询)app
# 地址是大理的英雄名字 author_detail_obj = models.AuthorDetail.objects.get(addr='大理') # author_detail_obj.要查询的表名(要小写).要查字段 print(author_detail_obj.author.name)
一对多正向查询函数
# 出版天龙八部的出版社名字 book_obj = models.Book.objects.get(name='天龙八部') # book_obj.外键名.要查字段 print(book_obj.publish.name)
一对多反向查询spa
# 查询城市是西夏的出版社 出版的图书 pub_obj = models.Publish.objects.get(city='西夏') # pub_obj.表名_set.all().values('name') 由于不止一个因此须要 表名_set print(pub_obj.book_set.all().values('name'))
多对多正向查询code
# 天龙八部的做者都有谁 book_obj = models.Book.objects.get(name='天龙八部') # book_obj.第三张表的属性.all().values(字段) print(book_obj.authors.all().values('name')) # 这个authors虽然在Book类下面,可是它不是字段,只是属性.
多对多反向查询对象
# 令狐冲写了哪些书 author_obj = models.Author.objects.get(name='令狐冲') # author_obj.表名_all().values(字段) print(author_obj.book_set.all().values('name'))
三 .基于双下划线跨表查询(基于join)
正向查询按照外键名,反向查询按照表名(小写), 和上面的同样,外键字段在哪一个表中, 他找别人就是正向,相反就是反向查询
# 一对一查询 # 查询萧峰做者的电话号 # 正向查询 按照外键 "__" 这个是双下划线 # models.类名(表名).objects.filter(条件).values(外键名__字段) ret = models.Author.objects.filter(name='萧峰').values('author_detail__tel') # 反向查询 按照类名(小写) # models.类名.objects.filter(另外一个类名(小写)__条件).values(字段) ret = models.AuthorDetail.objects.filter(book__name='萧峰').values('tel')
# 一对多查询 # 金庸出版社出版过的全部书籍的名字 # 正向查询 按照外键 # models.类名.objects.filter(外键名__条件).values(字段) ret = models.Book.objects.filter(publish__name='金庸出版社').values('name') # 反向查询 按照类名(小写) # models.类名.objects.filter(条件).values(另外一个类名(小写)__字段) ret = models.Publish.objects.filter(name='金庸出版社').values('book__name')
# 多对多查询 # 萧峰这个做者写了哪几本书 # 正向查询 按照外键 # models.类名.objects.filter(外键__条件).values(字段) ret = models.Book.objects.filter(authors__name='萧峰').values('name') # 反向查询 按照类名 # models.类名.objects.filter(条件).values(另外一个类名__字段) ret = models.Author.objects.filter(name='萧峰').values('book__name')
# 连续跨表查询
# 查询金庸出版社出版的全部的书名及做者名 # 正向查询 ret = models.Book.objects.filter(publish__name='金庸出版社').values('name','authors__name') # 反向查询 ret = models.Publish.objects.filter(name='金庸出版社').values('book__name','book__authors__name') # 因为Author和Publish两个表没有外键关系因此须要经过Book表找到做者名 # 电话以6开头的做者出版过的书名及出版社名 # 正向查询 ret = models.Book.objects.filter(authors__author_detail__tel__startswith='6').values('name','publish__name') # 反向查询 # 方法一 ret = models.Publish.objects.filter(book__authors__author_detail__tel__startswith='6').values('name','book__name') # 方法二 ret = models.AuthorDetail.objects.filter(tel__startswith='6').values('author__book__name','author__book__publish__name') # 因为Author与Book是多对多的关系,而且authors写在Book下面,因此经过author往回找的时候直接author__book.
四 . 聚合查询, 分组查询, F查询, Q查询
聚合查询
# aggregate(*args, **kwargs) 是queryset的终结,queryset对象后面.aggregate 获得一个字典再也不是queryset对象 # 计算全部书的平均价格 from django.db.models import Avg models.Book.objects.all().aggregate(Avg('price')) # 也能够给它起名字 aggregate(a = Avg('price')) # 这个objects后面的 all()写不写都行 能够直接在控制器(models.Book.objects)后面写 # 还能够不止生成一个聚合函数 from django.db.models import Avg,Max,Min models.Book.objects.aggregate(Avg('price'),Max('price'),Min('price'))
分组查询
------------------单表查询(用上边的Book表)---------------------- # 查询每一个出版社出版了多少本书 annotate里面写聚合函数(Max,Min,Avg,Count) 获得一个queryset对象 models.Book.objects.values('publish').annotate(c=Count('id')) # values里面写的是要分组的字段,每一个出版社意思就是以出版社为分组, annotate里面写你要统计的, 并且必须是 别名=聚合函数这个格式 ------------------多表查询(用以前那些表) --------------------- 查询每一个出版社出版了多少本书 models.Publish.objects.values('name').annotate(c=Count('book__id')) # 下面这个方法比较经常使用 models.Publish.objects.annotate(c=Count('book__id')).values('name','c') # 若是用上边的那个方法出现关于group by的错误的话,须要进行一下操做: 进入mysql里执行SELECT @@GLOBAL.sql_mode; 看看里面是否有 ONLY_FULL_GROUP_BY参数,若是有的话须要到配置文件中(my.ini或者是mysql.cnf)修改 sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' 而后重启mysql.
F查询(能够进行两个字段的比较)
# 好比说在Book表里面加上评论数comment_num 和点赞数support_num # 查询评论数大于点赞数的书 from django.db.models import F models.Book.objects.filter(comment_num__gt=F('support_num')) # django 还支持F()对象之间以及F()对象与常数之间的加减乘除 models.Book.objects.filter(comment_num__gt=F('support_num')*2) # 也能够用F()来进行修改 # 把每本书的价格添加1000 models.Book.objects.update(price=F('price')+1000)
Q查询
像filter()中的条件一块儿查询的时候都是and, 若是想要有or的关系就须要用到Q查询
Q对象可使用$(and) |(or) ~(not) 操做组合起来. 当一个操做符用在两个Q对象上面时,这两个Q对象因为操做符的做用就变成了一个新的对象. # 查询做者名字为萧峰或者段誉出版的书 models.Book.objects.filter(Q(authors__name='萧峰')|Q(authors__name='段誉')) # 能够组合其余的操做符进行操做 # 查询做者是萧峰或者是段誉价格不高于100的书 models.Book.objects.filter(Q(author__name='萧峰')|Q(author__name='段誉')& ~Q(price__gt=100)) # 若是有关键字参数和Q查询同时在筛选条件里面,Q查询必需要写到关键字参数前面 # 查询做者名字是萧峰或者是段誉的价格为100 的书 models.Book.objects.filter(Q(author__name='萧峰')|Q(author__name='段誉'),price=100) # 这个关键字参数要写到Q查询的后面,中间用逗号隔开,表示and的意思
五 . python脚本中调用Django环境(django外部脚本使用models)
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() from app01 import models #引入也要写在上面三句以后 books = models.Book.objects.all() print(books)