一、ORM生成关联模型
(1) 一对一:表示和AuthorDetail这张表的nid构成关联,一对一在人任意一张表构建关联都可以,on_delete类似于mysql的关联删除
publish = models.OneToOneField(to='AuthorDetail',to_field='nid',on_delete=models.CASCADE)
(2) 一对多:表示和publish这张表的nid构成关联,一对多要在多的那张表构建关联
publish = models.ForeignKey(to="publish",to_field="nid",on_delete=models.CASCADE)
(3) 多对多:在一张表下(例如book)写这段代码,那么会自动生成一张表,表明为book_author(由book和变量author拼成),里边有book_id,Author_id,以及2个关联外键。
author = models.ManyToManyField(to='Author')
一对一和一对多都会在执行代码的那张表里添加外键字段,多对多则是新生成一张表。
二、多表操作
(1)添加
1:一对多:
方式1:通过自己写
Book.objects.create(title='小说1',price=100,publishDate='2020-9-9',publish_id=1)
方式2:通过对象传
pub_obj = Publish.objects.filter(id=1).first() Book.objects.create(title='小说1',price=100,publishDate='2020-9-9',publish=pub_obj)
2:一对一:和一对多基本一样
3:多对多:先生成一个book对象,然后通过add构建book和author的关联,其自动会在book_author表中添加关联。
book_obj=Book.objects.create(title='小说2',price=100,publishDate='2020-9-9',publish_id=2)
author1 = Author.object.get(name='author1'
author2 = Author.object.get(name='author2')
book_obj.author.add(author1,author2)#author为多对多字段变量名称(manytomany那个)
#book_obj.author.add(1,2,3)
解除关联:
book = Book.objects.filter(nid=4).first() book.author.remove(1,2,3) #等价于book.author.remove(*[1,2,3]) #book.author.clear() 清除所有
(2)查询
正向查询:从关联属性所在的表去查询,用字段
反向查询:反之,用name_set,其中name为表名
1:基于对象
一对多:
正:查询xx的出版社
book_obj = Book.objects.filter(title='xx').first() print(book_obj.publish) print(book_obj.publish.name)
反:查询xx出版社出版过的书籍
publish = Publish.objects.filter(name='xx').first() ret = publish.book_set.all() print(ret)
多对多:
正:查询ss的作者名
book_obj = Book.objects.filter(title='ss').first()
author_list = book_obj.author.all()
for author in author_list:
print(author.name)
反:查询ss出版过的书籍
ss = Author.objects.filter(name='ss').first() book_list = ss.book_set.all() for book in book_list: print(book.title)
一对一:
正:查询作者p1的电话
p1 = Author.objects.filter(name='p1').first() print(p1.authordetail.telephone)
反:查询电话为199的作者年龄
phone = AuthorDetail.objects.filter(phone='199').first() print(phone.author.age)
2:基于双下划线(join)
正向查询:从关联属性所在的表去查询,用字段
反向查询:反之,用表名小写,代表联表。
一对多:
正:查询xx的出版社名
ret = Book.objects.filter(title='xx').values('publish__name') print(ret) #返回的是queryset对象列表
反: 查询xx的出版社名
ret = Publish.objects.filter(book__title='xx').values('name')#方法二 print(ret)
多对多:
正:查询xx的作者名
ret = Book.objects.filter(title='xx').values('author__name') print(ret)
反:查询xx的作者名
ret = Author.objects.filter(book_title='xx').vaules('name') print(ret)
一对一:查询xx手机号
正:查询xx的手机号
ret = Author.objects.filter(name='xx').vaules('authordetail_phone') print(ret)
反:查询xx的手机号
ret = AuthorDetail.objects.filter(author__name='xx').values('phone') print(ret)
连续跨表:查询手机号以199开头的作者出版过的书籍以及对应出版社名
方式1:
ret = Book.objects.filter(author__authordetail__phone__startwith='119').values('title','publish__name') print(ret)
联接了author,authordetail,book,以及publish的表。
方式2:
ret = Author.objects.filter(authordetail__phone__startwith='119').values('book__title','book__publish__name') print(ret)
3:聚合
有Max,Min,Count,Avg等函数
例子:计算所有书的平均价格
ret = Book.objects.all().aggregate(Avg('price')) print(ret)
4:分组
1:单表
例子: 查询每一个部门的名称以及员工的平均薪水。
from django.db.models import Avg,Max,Min,Count
ret = emp.objects.values('dep').annotate(avg_salary=Avg('salary'))
print(ret)
2:多表
from django.db.models import Avg,Max,Min,Count ret = Publish.objects.values('nid').annotate(c=Count("book__title")).vaules('name','c') print(ret)
5:F与Q
补充:ORM新增字段迁移时,要设置默认值default
F查询主要是表内部字段之间进行gt,lt、=,对比时使用的。因为默认python是找不到数据库的对比字段的。
from django.db.models import F,Q ret = Book.objects.filter(num1__gt=F('num2')) ret = Book.objects.all().update(price=F('price')*2)
Q查询主要是支持与或非选项。&、|、~,默认django是与操作。
例子:找出名字不是xx,并且价格为100或200的书籍
from django.db.models import F,Q ret = Book.objects.filter(~Q(title='xx')&Q(price=100)|Q(price=200))