一、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))