多表操作


 一对多新增数据
     添加一本北京出版社出版的书
     第一种方式
     ret=Book.objects.create(name='红楼梦',price=34.5,publish_id=1)
     print(ret.name)

     第二种方式,存对象publish=出版社的对象,存到数据库,是一个id
     publish=Publish.objects.get(id=1)
     pk是主键,通过主键查找
     publish=Publish.objects.get(pk=1)
     publish = Publish.objects.filter(pk=2).first()
     ret = Book.objects.create(name='西游记', price=34.5, publish=publish)
     print(ret.name)

     一对多修改数据
     book=Book.objects.get(pk=1)
      book.publish=出版社对象
     book.publish_id=2
     book.save()

     方式二
     book=Book.objects.filter(pk=1).update(publish=出版社对象)??
     book=Book.objects.filter(pk=1).update(publish_id=1)
     多对多新增

     为红楼梦这本书新增一个叫lqz,egon的作者
     lqz=Author.objects.filter(name='lqz').first()
     egon=Author.objects.filter(name='egon').first()
     book=Book.objects.filter(name='红楼梦').first()

      add 添加多个对象
     book.authors.add(lqz,egon)

     add添加作者id
     book.authors.add(1,2)

    删除 remove,可以传对象,可以传id,可以传多个,不要混着用
     book.authors.remove(lqz)
     book.authors.remove(2)
     book.authors.remove(1,2)

     clear清空所有
     book.authors.clear()

     set,先清空,在新增,要传一个列表,列表内可以是, id,也可以是对象
     book.authors.set([lqz,])

     ********这样不行,因为它打散了传过去了,相当于book.authors.set(lqz)
     book.authors.set(*[lqz,])


     lqz=Author.objects.filter(name='lqz')
     print(type(lqz))
    from  django.db.models.query import QuerySet
 ***************************基于对象的跨表查询
    '''
    一对一
    正向   author---关联字段在author--->authordetail   ------>  按字段
    反向   authordetail------关联字段在author--->author  -----> 按表名小写
    
    '''
     查询lqz作者的手机号   正向查询
     author=Author.objects.filter(name='lqz').first()
      author.authordetail 就是作者详情的对象
     authordetail=author.authordetail
     print(authordetail.phone)     查询地址是 :山东 的作者名字   反向查询     authordetail=AuthorDetail.objects.filter(addr='山东').first()      authordetail.author  这是作者对象     author=authordetail.author     print(author.name)

    一对多
    '''
    一对多
    正向   book---关联字段在book--->publish   ------>  按字段
    反向   publish------关联字段在book--->book  -----> 按表名小写_set.all()
    '''
     正向 查询红楼梦这本书的出版社邮箱
     book=Book.objects.filter(name='红楼梦').first()
      book.publish  就是出版社对象
     pulish=book.publish
     print(pulish.email)
     反向  查询地址是北京 的出版社出版的图书
     publish=Publish.objects.filter(addr='北京').first()
      publish.book_set.all()  拿出所有的图书
     books=publish.book_set.all()
      统计一下条数
     books=publish.book_set.all().count()
     print(books)

    '''
    多对多
    正向   book---关联字段在book--->author   ------>  按字段.all()
    反向   author------关联字段在book--->book  -----> 按表名小写_set.all()
    '''
    查询红楼梦这本书所有的作者
     book=Book.objects.filter(name='红楼梦').first()
     book.authors.all()  是所有的作者,是一个queryset对象,可以继续点
     print(book.authors.all())

     查询lqz写的所有书
     lqz=Author.objects.filter(name='lqz').first()
     books=lqz.book_set.all()
     print(books)

     连续跨表
     查询红楼梦这本书所有的作者的手机号
     book=Book.objects.filter(name='红楼梦').first()
     authors=book.authors.all()
     for author in authors:
         authordetail=author.authordetail
         print(authordetail.phone)


     ****************************基于对象的查询---是子查询也就是多次查询
     ***************基于双下划线的查询*****
     一对一
     查询lqz作者的手机号   正向查询  跨表的话,按字段
     以author表作为基表
     ret=Author.objects.filter(name='lqz').values('authordetail__phone')
     print(ret)
     以authordetail作为基表 反向查询,按表名小写  跨表的话,用表名小写
     ret=AuthorDetail.objects.filter(author__name='lqz').values('phone')
     print(ret)
     查询lqz这个作者的性别和手机号
     正向
     ret=Author.objects.filter(name='lqz').values('sex','authordetail__phone')
     print(ret)
     查询手机号是13888888的作者性别
     ret=Author.objects.filter(authordetail__phone='13888888').values('sex')
     print(ret)
     ret=AuthorDetail.objects.filter(phone='13888888').values('author__sex')
     print(ret)


  1 创建多表模型(详情见代码)    
用了OneToOneField和ForeignKey,模型表的字段,后面会自定加_id
ManyToManyField会自动创建第三张表
一对一的关系:OneToOneField
一对多的关系:ForeignKey
多对多的关系:ManyToManyField

2 添加表记录
  1 一对多新增
     -两种方式:
      -publish=对象
      -publish_id=id
2 一对多删除:同单表删除
3 一对多修改:两种方式,可以传对象,可以传id
4 一对一跟一对多一样
5 多对多:
    -add ----->可以传对象,可以传id,可以传多个
    -remove ----->可以传对象,可以传id,可以传多个
    -clear ---->没有参数
    -set ----->跟上面不一样,必须传列表,列表里面可以是对象,可以是id

3 基于对象的跨表查询    
  1 一对一
    正向:正向查询按字段
    反向:反向查询按表名小写
  2 一对多
    正向:正向查询按字段
    反向:反向按表名小写_set.all()
  3 多对多
    正向:正向查询按字段
    反向查询:反向按表名小写_set.all()
4 基于双下划线的跨表查询    
    -连表查询
    -一对一双下划线查询
      -正向:按字段,跨表可以在filter,也可以在values中
      -反向:按表名小写,跨表可以在filter,也可以在values中

id如果不写,会自动生成,名字叫nid,并且自增

可以用ForeignKey,但是得设置唯一性约束,会报警告,不建议用,建议用OneToOneField
authordetail=models.ForeignKey(unique=True)
to='AuthorDetail' 加引号,这个表能找到就可以,不用引号,类必须在上面定义

用了OneToOneField和ForeignKey,模型表的字段,后面会自定加_id 
ManyToManyField会自动创建第三张表
一对一的关系:OneToOneField
一对多的关系:ForeignKey
多对多的关系:ManyToManyField


原文地址:https://www.cnblogs.com/zhouhao123/p/9954753.html