第六篇:多表操作
from django.db import models # Create your models here. # 用了OneToOneField和ForeignKey,模型表的字段,后面会自定加_id # ManyToManyField会自动创建第三张表 # *************重点 # 一对一的关系:OneToOneField # 一对多的关系:ForeignKey # 多对多的关系:ManyToManyField class Publish(models.Model): # id如果不写,会自动生成,名字叫nid,并且自增 id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) addr = models.CharField(max_length=64) email = models.EmailField() class Author(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) # 数字类型 sex = models.IntegerField() # 可以用ForeignKey,但是得设置唯一性约束,会报警告,不建议用,建议用OneToOneField # authordetail=models.ForeignKey(unique=True) # to='AuthorDetail' 加引号,这个表能找到就可以,不用引号,类必须在上面定义 authordetail = models.OneToOneField(to='AuthorDetail', to_field='id') # to_field表示自动关联到主键上 def __str__(self): return self.name class AuthorDetail(models.Model): id = models.AutoField(primary_key=True) phone = models.CharField(max_length=32) addr = models.CharField(max_length=64) class Book(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) publish = models.ForeignKey(to=Publish, to_field='id') #多对多的关系建立在哪里都可以,例如:一个作者可以写多本书,一本书可以由多个作者写 authors = models.ManyToManyField(to=Author) def __str__(self): return self.name
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day77.settings") import django django.setup() from app01.models import * # 一对多新增数据 # 添加一本北京出版社出版的书 # 第一种方式 # 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)