django之多表查询
Posted xuecaichang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django之多表查询相关的知识,希望对你有一定的参考价值。
一、创建模型
在Models创建如下模型:
from django.db import models # Create your models here. # 用了OneToOneField和ForeignKey,模型表的字段,后面会自定加_id # ManyToManyField会自动创建第三张表 # 一对一的关系:OneToOneField # 一对多的关系:ForeignKey # 多对多的关系:ManyToManyField class Publish(models.Model): 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‘) 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
注意事项:
id 字段 是自动添加的
对于外键字段,django会在字段名上添加“_id”来创建数据库中的列名
外键字段ForeignKey 有一个 null=True的设置(它允许外键接受空值NULL),你可以赋值给它none。
二、添加表记录
1、一对多新增数据
# 添加一本北京出版社出版的书 # 方式一 ret=Book.objects.create(name=‘红楼梦‘,price=35,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=45.5,publish=publish) # print(ret.name)
# -----一对多添加 pub=Publish.objects.create(name=‘egon出版社‘,email=‘[email protected]‘,city=‘山东‘) print(pub) # 为book表绑定和publish的关系 import datetime,time now=datetime.datetime.now().__str__() now = datetime.datetime.now().strftime(‘%Y-%m-%d‘) print(type(now)) print(now) # 日期类型必须是日期对象或者字符串形式的2018-09-12(2018-9-12),其它形式不行 Book.objects.create(name=‘海燕3‘,price=333.123,publish_date=now,publish_id=2) Book.objects.create(name=‘海3燕3‘,price=35.123,publish_date=‘2018/02/28‘,publish=pub) pub=Publish.objects.filter(nid=1).first() book=Book.objects.create(name=‘测试书籍‘,price=33,publish_date=‘2018-7-28‘,publish=pub) print(book.publish.name) # 查询出版了红楼梦这本书出版社的邮箱 book=Book.objects.filter(name=‘红楼梦‘).first() print(book.publish.email)
2、多对多
# 为红楼梦这本书新增一个叫 xcc的作者 # xcc = Author.objects.filter(name=‘xcc‘).first() # zy=Author.objects.filter(name=‘张煜‘).first() # book = Book.objects.filter(name=‘红楼梦‘).first() # add添加对象 # book.authors.add(xcc) # book.authors.add(xcc,zy) # add添加作者id # book.authors.add(1,2) # 删除 remove,可以传对象,可以传id,可以传多个,不要混着用 # book.authors.remove(xcc) # book.authors.remove(2) # book.authors.remove(1,2) # clear清空所有 # book.authors.clear() # set,先清空,再新增,要传一个列表,列表内可以是id,也可以是对象 # book.authors.set([xcc,]) # book.authors.set([2,])
三、基于对象的跨表查询
1、一对多查询
‘‘‘ 一对多 正向 book---关联字段在book--->publish ------> 按字段 反向 publish------关联字段在book--->book -----> 按表名小写_set.all() ‘‘‘ # 正向查询红楼梦这本书的出版社邮箱 # book = Book.objects.filter(name=‘红楼梦‘).first() # publish = book.publish # print(publish.email) # 反向查询地址是北京的出版社出版的图书 # publish = Publish.objects.filter(addr=‘北京‘).first() # publish.book_set.all() 拿出所有图书 # books=publish.book_set.all() # books = publish.book_set.all().count() # print(books)
2、一对一查询:
‘‘‘ 一对一 正向 author---关联字段在author--->authordetail ------> 按字段 反向 authordetail------关联字段在author--->author -----> 按表名小写 ‘‘‘ # 查询xcc作者的手机号,正向查询 # author = Author.objects.filter(name=‘xcc‘).first() # # author.authordetail 就是作者的详情对象 # authordetail = author.authordetail # print(authordetail.phone) # 查询地址是安庆的作者名字,反向查询 # authordetail = AuthorDetail.objects.filter(addr=‘安庆‘).first() # # authordetail.author 这是作者的对象 # author = authordetail.author # print(author.name)
3、多对多查询:
‘‘‘ 多对多 正向 book---关联字段在book--->author ------> 按字段.all() 反向 author------关联字段在book--->book -----> 按表名小写_set.all() ‘‘‘ # 查询红楼梦这本书的所有作者 # book = Book.objects.filter(name=‘红楼梦‘).first() # ret = book.authors.all() # 是所有的作者,是一个queryset对象,可以继续点 # print(ret) # 查询xcc写的所有书 # xcc = Author.objects.filter(name=‘xcc‘).first() # books = xcc.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)
四、基于双划线的跨表查询
# ************基于双下划线的查询 # 一对一 # 查询xcc作者的手机号,正向查询,跨表的话,按字段 # 以author表作为基表 # ret = Author.objects.filter(name=‘xcc‘).values(‘authordetail__phone‘) # print(ret) # 以authordetail作为基表,反向查询,按表名小写,跨表的话,用表名小写 # ret=AuthorDetail.objects.filter(author__name=‘xcc‘).values(‘phone‘) # print(ret) # 查询xcc的性别和手机号 正向 # ret=Author.objects.filter(name=‘xcc‘).values(‘authordetail__phone‘,‘sex‘) # print(ret) # 查询手机号是12234567的作者的性别 # ret=Author.objects.filter(authordetail__phone=‘12234567‘).values(‘sex‘) # print(ret)
以上是关于django之多表查询的主要内容,如果未能解决你的问题,请参考以下文章