Dango-之多对多关系—基于双下划线的查询

一对一的反向查询用表名不加_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")

 

posted @ 2017-11-25 18:22  wateligx  阅读(307)  评论(0编辑  收藏  举报