一,创建多表模型
1,用了OneToOneField and ForeignKey,模型的字段,后面会自动加上_id,一般查询的时候,直接查询_id的内容,(如果插入不加_id时,需要插入一个对象)
2,ManyToManyField会自动创建第三张表
3,一对一的关系:OneToOneFiled,(也可以使用ForeignKey,需要添加唯一性约束(unique=True)但是不建议,)
一对多的关系:ForeignKey
多对多的关系:ManyToManyField
from django.db import models # Create your models here. class Publish(models.Model): # id如果不写会自动添加,名字叫nid,而且会自增,主键 id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) addr = models.CharField(max_length=64) # 存的依然是varchar类型,对于用户来说没什么用,在app的admin中有用 email = models.EmailField() class Author(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) sex = models.IntegerField() # to='AuthorDetail'其中AuthorDetail表如果在引用表的上面,则不需要添加引号,如果加上引号则存在就可以 authordetail = models.OneToOneField(to='AuthorDetail', to_field='id') 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
二,一对多添加表记录
1,1>一对多数据添加(一对多数据修改一样)
方式一:(一对多,添加publish_id字段直接添加对应的id即可) ret = Book.objects.create(name='西游记',price=23,publish_id=1) print(ret) 方式二:(先根据Id获取其publish对象,然后在添加的时候Publish直接添加对象) # 可以直接用pk(主键)添加 publish_obj = Publish.objects.grt(id=1) ret = Book.object.create(name='红楼梦',price=54,publish=publish_obj) print(ret)
2> 一对多修改
一对多修改数据 # 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)
2,一对多数据删除,与一对一数据的处理和单表操作是一样的
3,多对多数据处理一共存在四种方法
# 多对多新增 # 为红楼梦这本书新增一个叫jack,tom的作者 # jack=Author.objects.filter(name='jack').first() # tom=Author.objects.filter(name='tom').first() # book=Book.objects.filter(name='红楼梦').first() # add 添加多个对象 book.authors.add(jack,tom) # add添加作者id book.authors.add(1,2) #删除 remove,可以传对象,可以传id,可以传多个,不要混着用 book.authors.remove(jack) book.authors.remove(2) book.authors.remove(1,2) # clear清空所有 book.authors.clear() # set,先清空(清空的是该Book的所有链接),在新增,要传一个列表(可迭代对象),列表内可以是, id,也可以是对象 book.authors.set([jack,]) # ********这样不行,因为它打散了传过去了,相当于book.authors.set(jack) # book.authors.set(*[jack,])
三,基于对象的跨表查询
1,一对一
正向:正向查找按字段
# 查询lqz作者的手机号 正向查询 # author=Author.objects.filter(name='jack').first() # # author.authordetail 就是作者详情的对象 # authordetail=author.authordetail # print(authordetail.phone)
反向:反向查找按表名小写
# 查询地址是 :山东 的作者名字 反向查询 # authordetail=AuthorDetail.objects.filter(addr='山东').first() # # authordetail.author 这是作者对象 # author=authordetail.author # print(author.name)
2,一对多
正向:正向查询按字段
# 正向 查询红楼梦这本书的出版社邮箱 # book=Book.objects.filter(name='红楼梦').first() # # book.publish 就是出版社对象 # pulish=book.publish # print(pulish.email)
反向:反向按表名小写_set.all()
# 反向 查询地址是北京 的出版社出版的图书 # publish=Publish.objects.filter(addr='北京').first() # # publish.book_set.all() 拿出所有的图书 # books=publish.book_set.all() # # 统计一下条数 # books=publish.book_set.all().count() # print(books)
3,多对多
正向:正向查询按字段,
# 查询红楼梦这本书所有的作者 # book=Book.objects.filter(name='红楼梦').first() # book.authors.all() #是所有的作者,是一个queryset对象,可以继续点 # print(book.authors.all())
反向:反向查询按表名小写_set.all()
# 查询lqz写的所有书 # lqz=Author.objects.filter(name='jack').first() # books=lqz.book_set.all() # print(books)
基于对象的查询,多次查询(子查询)
三,基于双下划线的跨表查询
1,连表查询
# 连续跨表 # 查询红楼梦这本书所有的作者的手机号 # book=Book.objects.filter(name='红楼梦').first() # authors=book.authors.all() # for author in authors: # authordetail=author.authordetail # print(authordetail.phone)
2,一对一双下划线查询
正向:按字段,跨 表可以在filter,也可以values中
反向:按表名小写,跨表可以在filter,也可以在values中
# 一对一 # 查询jack作者的手机号 正向查询 跨表的话,按字段 # 以author表作为基表 # ret=Author.objects.filter(name='jack').values('authordetail__phone') # print(ret) # 以authordetail作为基表 反向查询,按表名小写 跨表的话,用表名小写 # ret=AuthorDetail.objects.filter(author__name='jack').values('phone') # print(ret) # 查询jack这个作者的性别和手机号 # 正向 # ret=Author.objects.filter(name='jack').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)
3,基于双下划线一对多的查询
# 基于双下划线一对多查询 # 例,查询出版社为背景出版社的所有图书的名字,价格 ret = Publish.objects.filter(name='北京出版社').values('book__name','book__price') print(ret) ret = Book.objects.filter(publish__name='北京出版社').values('name','price') print(ret) # 查询北京出版社的价格大于19的书 ret = Publish.objects.filter(name='北京出版社',book__price__gt=19).values('book__name','book__price') print(ret)
4,基于双下划线,多对多的查询
# 基于双下划线多对多的查询 # 例,查询红楼梦的所有作者的名字 ret = Book.objects.filter(name='呐喊').values('authors__name') print(ret) ret = Author.objects.filter(book__name='呐喊').values('name') print(ret) # 例,查询图书价格大于30的所有作者的名字 ret = Book.objects.filter(price__gt=30).values('authors__name') print(ret) ret = Author.objects.filter(book__price__gt=30).values('name') print(ret) # 更进一步练习--->连续跨表查询 # 查询北京出版社出版过的所有书籍的名字以及作者的姓名 ret = Publish.objects.filter(name='北京出版社').values('book__name','book__authors__name') print(ret) ret = Book.objects.filter(publish__name='北京出版社').values('name','authors__name') print(ret)