Django之ORM(多对多)

一、ManyToManyField

1、class RelatedManager

"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。

它存在于下面两种情况:

  1. 外键关系的反向查询
  2. 多对多关联关系

简单来说就是当 点后面的对象 可能存在多个的时候就可以使用以下的方法。

2、方法

1)create()

创建一个新的对象,保存对象,并将它添加到关联对象集之中,返回新创建的对象。

>>> import datetime
>>> models.Author.objects.first().book_set.create(title="番茄物语", publish_date=datetime.date.today())

2)add()

把指定的model对象添加到关联对象集中。

# 添加对象
>>> author_objs = models.Author.objects.filter(id__lt=3)
>>> models.Book.objects.first().authors.add(*author_objs)# 添加id
>>> models.Book.objects.first().authors.add(*[1, 2])

3)set()

更新model对象的关联对象。

>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.set([2, 3])

4)remove()

从关联对象集中移除执行的model对象。

>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.remove(3)

5)clear()

从关联对象集中移除一切对象。

>>> book_obj = models.Book.objects.first()
>>> book_obj.authors.clear()

注意:

对于ForeignKey对象,clear()和remove()方法仅在null=True时存在。

示例:

复制代码
# ForeignKey字段没设置null=True时,
class Book(models.Model):title = models.CharField(max_length=32)publisher = models.ForeignKey(to=Publisher)# 没有clear()和remove()方法:
>>> models.Publisher.objects.first().book_set.clear()
Traceback (most recent call last):File "", line 1, in 
AttributeError: 'RelatedManager' object has no attribute 'clear'# 当ForeignKey字段设置null=True时,
class Book(models.Model):name = models.CharField(max_length=32)publisher = models.ForeignKey(to=Class, null=True)# 此时就有clear()和remove()方法:
>>> models.Publisher.objects.first().book_set.clear()
复制代码

4、书籍与作者多对多举例

from django.db import models# Create your models here.class Publisher(models.Model):name = models.CharField(max_length=12)# 书籍表
class Book(models.Model):title = models.CharField(max_length=32)publisher = models.ForeignKey(to="Publisher", on_delete=models.CASCADE)# 作者表
class Author(models.Model):name = models.CharField(max_length=12)# 多对多,自动帮我们在数据库建立第三张关系表books = models.ManyToManyField(to='Book', related_name="authors")
models.py
from django.conf.urls import url
from django.contrib import admin
from app01 import viewsurlpatterns = [url(r'^admin/', admin.site.urls),url(r'^author_list/$', views.author_list),url(r'^delete_author/(\d+)/$', views.delete_author),url(r'^add_author/$', views.AddAuthor.as_view()),url(r'^edit_author/(\d+)/$', views.EditAuthor.as_view()),
]
urls.py
from django.shortcuts import render, redirect, HttpResponse
from app01 import models
from django import views# Create your views here.def author_list(request):author_list = models.Author.objects.all()return render(request, "author_list.html", {"data": author_list})def delete_author(request, delete_id):# models.Author.objects.get(id=delete_id)  # 很少用,谨慎使用models.Author.objects.filter(id=delete_id).delete()return redirect("/author_list/")# 添加作者
class AddAuthor(views.View):def get(self, request):book_list = models.Book.objects.all()return render(request, "add_author.html", {"book_list": book_list})def post(self, request):print(request.POST)# 用户新创建的作者名字author_name = request.POST.get("name")# 用户给新作者设置的书名id, 因为是多选所以要用getlist取值books_ids = request.POST.getlist("books")print(author_name, books_ids)# 1. 先创建一个新的作者对象author_obj = models.Author.objects.create(name=author_name)# 2. 去第三张关系表,建立关系记录
        author_obj.books.set(books_ids)return redirect("/author_list/")# return HttpResponse("OK")class EditAuthor(views.View):def get(self, request, edit_id):author_obj = models.Author.objects.filter(id=edit_id).first()book_list = models.Book.objects.all()return render(request, "edit_author.html", {"author": author_obj, "book_list": book_list})def post(self, request, edit_id):author_obj = models.Author.objects.filter(id=edit_id).first()new_name = request.POST.get("name")new_books = request.POST.getlist("books")# 真正的更新操作author_obj.name = new_nameauthor_obj.save()author_obj.books.set(new_books)return redirect("/author_list/")
views.py
{#author_list.html#}DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>作者列表title>
head>
<body><table border="1"><thead><tr><th>#th><th>idth><th>作者名字th><th>写过的书th><th>操作th>tr>thead><tbody>{% for author in data %}<tr><td>{{ forloop.counter }}td><td>{{ author.id }}td><td>{{ author.name }}td><td>{% for book in author.books.all %}{{ book.title }},{% endfor %}td><td><a href="/delete_author/{{ author.id }}/">删除a><a href="/edit_author/{{ author.id }}/">编辑a>td>tr>{% endfor %}tbody>
table>
body>
html>{#edit_author.html#}DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>编辑作者title>
head>
<body><form action="" method="post">{% csrf_token %}<p>作者名:<input type="text" name="name" value="{{ author.name }}">p><p>书名:<select name="books" multiple>{% for book in book_list %}{% if book in author.books.all %}<option selected value="{{ book.id }}">{{ book.title }}option>{% else %}<option value="{{ book.id }}">{{ book.title }}option>{% endif %}{% endfor %}select>p><p><input type="submit" value="提交">p>form>
body>
html>{#add_author.html#}DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>添加作者title>
head>
<body><form action="" method="post">{% csrf_token %}<p>作者名:<input type="text" name="name">p><p>书名:<select name="books" multiple>{% for book in book_list %}<option value="{{ book.id }}">{{ book.title }}option>{% endfor %}select>p><p><input type="submit" value="提交">p><p>爱好:<input type="checkbox" value="basketball" name="hobby">篮球<input type="checkbox" value="football" name="hobby">足球<input type="checkbox" value="doublecolorball" name="hobby">双色球p>
form>
body>
html>
html代码

5、基于对象和QuerySet查询

复制代码
import osif __name__ == '__main__':os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")import djangodjango.setup()from app01 import modelsauthor_obj = models.Author.objects.first()# 多对多的正向查询ret = author_obj.books.all()print(ret)#多对多的反向查询book_obj = models.Book.objects.last()# 默认按照表名(全小写)_set.all()# ret = book_obj.author_set.all()# 如果多对多字段设置了related_name属性,反向查询的时候就按该属性值来查询ret = book_obj.authors.all()print(ret)# add方法author_obj = models.Author.objects.first()ret = author_obj.books.all()print(ret)# 给作者加一本关联的书籍author_obj.books.set([2, 3])author_obj.books.add(2)ret = author_obj.books.all()print(ret)#查询第一个作者写过的书的名字#1. 基于对象的查询ret = models.Author.objects.first().books.all().values("title")print(ret)#基于QuerySet的双下划线查询ret = models.Author.objects.filter(id=2).values("books__title")print(ret)#基于QuerySet的双下划线的反向查询#由书找作者ret = models.Book.objects.filter(id=2).values("authors__name")print(ret)
复制代码

6、总结

ORM(多对多)
  1. ORM多对多字段
    # 多对多,自动帮我们在数据库建立第三张关系表
    books = models.ManyToManyField(to='Book', related_name="authors")
    参数:
      - to:表示和哪张表建立多对多的关系
      - related_name:表示返乡查询时使用的那个字段名,默认反向查询时使用表名_set的方式
  
  2. 多对多字段的方法
    1. 查询
       .all()  --> 多对多查询的方法,
   
    2. 删除
   
    3. 添加新作者
      1. 当form表单提交的数据是列表(多选的select\多选的checkbox)取值?
      request.POST.getlist("hobby")
 
      2. .set([id1,id2,...])  参数是一个列表  --> 删除原来的设置新的
      3. .add(id值)                           --> 在原来的基础上增加新的纪录

 

转载于:https://www.cnblogs.com/Nopeeee/p/10477535.html


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部