一对一的反向查询用表名不加_set,一对多的反向查询表名加_set
前面写了一对多的关系,在这里升级下写下多对多的关系~~
我们从前面的小项目app01中创建了一对多关系的Publish表,从这里我们在创建个作者表用来进行多对多关系的建立。
在我们的models.py中:
from django.db import models # Create your tests here. class Book(models.Model): nid=models.AutoField(primary_key=True) title=models.CharField(max_length=32) pubDate=models.DateField() price=models.DecimalField(max_digits=6,decimal_places=2) #django会自动给外键字段添加"_id",关联哪个表的字段就写哪个表名,django会自动关联publish表的主键 publisher=models.ForeignKey("Publish") #书籍与作者:多对多
#创建多对多关联字段语法,关联字段不会在表中显示,django会自动创建一张“应用名_当前表名_关联字段”app01_book_authors
#与这本书关联的作者对象集合
authors=models.ManyToManyField("Author") #django如果表没有创建主键,会默认创建一个主键,名字叫id class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) tel = models.BigIntegerField() class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() tel=models.CharField(max_length=32)
创建Author作者表还是老方法,不一样的地方在于,我们给书籍添加了个orm层的关联字段authors,用来表示这边数据有多个作者。
我们执行python manage.py makemigrations python manage.py migrate来数据化新增的字段和表,之后会产生Author表和中间表
可以看到我们创建的作者表,和一张关系表,表中的book_id就是数据表中的nid,author_id便是author表中的id,这样,书籍和作者就关联起来了~~~
下面进行我们的表关系表的操作。
多对多的添加
我们要想给书籍绑定作者,需要拿到书籍对象,然后拿到坐着对象,然后进行关联。 1、书籍对象: book_obj=models.Book.objects.create(title=title) 2、绑定作者关系 添加作者关系: 作者对象:alex=models.Author.objects.get(name="alex")
#也可以拿到一个作者对象集合:
author_list=models.Author.objects.all()
绑定一个对象关系 book_obj.authors.add(alex) 可以通过下面的语法
绑定多个对象关系 book_obj.authors.add(*author_list)
显示作者关系: book_obj.authors.all() #book对象相关联的作者对象集合
解除作者关系
#拿到书对象 book_obj=models.Book.objects.get(id=1) #查看下该书对象关联多少个作者 print(book_obj.authors.all()) #拿到作者对象 alex=models.Author.objects.get(name="alex") book_obj.authors.remove(alex) #清空所有作者 book_obj.authors.clear()
可以看出我们所有的操作都是通过关联字段authors的方法进行的。
多对多查询
多对多的正向查询:查询python这本书的作者的姓名和年龄 book_obj=Book.models.objects.get(name="python") for obj in book_obj.authors.all(): print(obj.name,obj.age) 查询人民出版社出版过的书籍名称及价格 pub_obj=models.Publish.objects.get(title="remin") 反向查询书籍 pub_obj.book_set.all()#与这个出版社关联的所有书籍对象 for obj in book_list: print(obj.title,obj.price) 多对多的反向查询:查询alex出版过的所有书籍的名称 alex=models.Author.objects.get(name="alex") book_list=alex.book_set.all() for i in book_list: print(i.title)
完善项目增加作者字段的增改查
我们最终要实现成这种方式
首先我们需要在index.html中添加一列作者的显示信息
很简单,我们只需要在table中添加一个作者标题,在数据显示的地方for循环我们的书对象关联的作者集,然后显示~
添加功能
首先我们在view视图中add函数获取到作者列表,然后通过render方法返回给add.html
然后我们在add.html增加了一些内容
我们在点击添加之后会多出一个作者的多行可选筐。
我们遍历作者列表显示作者的名字
然后通过request.POST.get_list(authors_id)可以从视图函数中获取用户所选择的作者。
修改功能
作者列表的修改功能和添加功能类似
首先我们传authors对象给edit.html
然后
进行显示并进行默认值设置,把作者id发送给模板,模板进行判断如果在作者列表中,变添加selected。
基于双下划线的查询
查询python这本书的出版社的名称和地址 基于双下划线,双下划线相当于跨表 models.Book.objects.filter(title="python").values("publisher__name") 等同于 book_obj=models.Book.object.filter(title="python") for obj in book_obj: obj.publisher.name 反向双下划线查询 models.Publish.objects.filter(book__title="python").values_list("name","addr")
查询人民出版社出版过的所有书籍名称及价格 models.Book.objects.filter(publisher__name="renmin").values_list("title","price") #正向 models.Publish.objects.filter(name="remin").values("book__title","book_set__price")
#查询egon出过的所有书籍的名字(多对多) models.Author.objects.get(name="egon").values("book__title")
models.Book.objects.filter(authors__name__contains="egon").values("title")
#地址以沙河开头的作者出版过的所有书籍和出版社名称
models.Book.objects.filter(authors__addr__startwith("沙河")).values("title","publisher__name")