zoukankan      html  css  js  c++  java
  • Django-ORM之ManyToManyField的使用-多对多关系

    表结构设计

    多对多关系表创建外键,典型例子:书--作者--出版社,书与作者的关系就可以看作是多对多关系。

     # 表结构设计
     class Book(models.Model):
        title = models.CharField(max_length=32)
        pub = models.ForeignKey('Publisher', on_delete=models.CASCADE) #与出版社之间建立多对一外键
     ​
     class Author(models.Model):
        name = models.CharField(max_length=32)
        books = models.ManyToManyField('Book')  # 描述多对多的关系  不生成字段  生成关系表

    数据迁移

    如果是在新的app中进行功能的设计,可以使用 python manage.py makemigrations app(应用名) 进行数据的迁移,数据迁移完之后会生成三张表,这是情理之中的事,因为多对多关系的两张表要建立连接的时,需要借助第三张表来维护二者的关系,这里会自动生成第三张表,如图:

    【新建测试表结构】
     1 from django.db import models
     2  3  # Create your models here.
     4  class Publisher(models.Model):
     5     name = models.CharField(max_length=32)
     6     city = models.CharField(max_length=32)
     7  8     def __str__(self):
     9         return "<Publisher object: {} {}>".format(self.id, self.name)
    10 11  class Author(models.Model):
    12     name = models.CharField(max_length=32)
    13     age = models.IntegerField()
    14     phone = models.CharField(max_length=11)
    15 16     def __str__(self):
    17         return "<Author object: {} {}>".format(self.id, self.name)
    18 19  class Book(models.Model):
    20     title = models.CharField(max_length=32)
    21     publish_date = models.DateField(auto_now_add=True)
    22     price = models.DecimalField(max_digits=5, decimal_places=2)
    23     memo = models.TextField(null=True)
    24     # 创建外键,关联publish
    25     publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE)
    26     # 创建多对多关联author
    27     author = models.ManyToManyField(to="Author")
    28 29     def __str__(self):
    30         return "<Book object: {} {} {} {}>".format(self.id, self.title,self.price,self.author)
    新建表结构

    基于对象的正向查询

     book_obj = models.Book.objects.get(pk=1)
     print(book_obj)
     print(book_obj.title)
     print(book_obj.author) # 关系管理对象,通过books可以得到两张表的关系,输出:app01.Book.None
     print(book_obj.author.all()) # 所关联的所有对象,输出:<QuerySet [<Author: <Author object: 1 金老板>>, <Author: <Author object: 2 小哪吒>>]>

    基于对象的反向查询

     author_obj = models.Author.objects.get(pk=1)
     print(author_obj)
     print(author_obj.book_set)
     print(author_obj.book_set.all())
     print(author_obj.name)
    基于字段的正向查询
     # 查找作者叽喳写的书
     book_obj = models.Book.objects.filter(author__name='叽喳')
     print(book_obj)
     print(book_obj.first().title)

    基于字段的反向查询

     # 查找《叽叽喳喳》的作者
     author_obj = models.Author.objects.filter(book__title='叽叽喳喳')
     print(author_obj)

    关系管理对象的方法set、add、remove、clear

    all 关联的所有的对象

     author_obj = models.Author.objects.get(pk=1)
     book_obj = models.Book.objects.get(pk=1)
     print(author_obj.book_set.all())
     print(book_obj.author.all())

    ​set 设置多对多关系,两种方式,添加对象列表

     author_obj.book_set.set([3,4])  # 这个作者写的哪些书
     author_obj.book_set.set(models.Book.objects.filter(pk__in=[3,4]))

    add 添加多对多关系,两种方式,直接添加关系对象就好

     author_obj.book_set.add(3,4) 
     author_obj.book_set.add(*models.Book.objects.filter(pk__in=[3,4]))

    remove 删除多对多关系,两种方式,直接移除关系对象

     author_obj.book_set.remove(3,4) 
     author_obj.book_set.remove(*models.Book.objects.filter(pk__in=[3,4]))
    clear 清空当前对象多对多关系 
    author_obj.book_set.clear()

    关系管理对象的方法create

     author_obj.book_set.create(title='叽叽喳喳的世界',publisher_id=2,price=99.9)
     book_obj.author.creat(name='小提莫',age=23,phone='13822567070') ​

    【配合HTML模板】

    # 获取对应的一个或者多个book的id,注意当或去多个值时使用的时getlist
     books = request.POST.getlist('books')   
     ​
     # 新建作者
     author_obj = models.Author.objects.create(name=name) #第一个name是Author表的字段名
     ​
     # 给作者和书籍绑定关系
     author_obj.books.set(books)  # 【id,id】自动把两者的信息进行匹配保存
    删除对象
    # 直接调用delete方法删除即可
     ​
      pk = request.GET.get("pk")     # 过的主键
      obj = models.Auther.objects.filter(id=pk)  # 通过主键获得整个对象
      obj.delete()  # 删除对象
     这里删除对象之后,会直接把与之相关的外键关系删除,而不会删除关系对应的图书对象

    自定义外键

    自己手动创建

    手动创建关系表,所有的信息维护也需要手动进行增删改查

     class Book(models.Model):
        title = models.CharField(max_length=32)
     ​
     class Author(models.Model):
        name = models.CharField(max_length=32)
     ​
     class Book_Author(models.Model):
        book = models.ForeignKey(Book, on_delete=models.CASCADE)
        author = models.ForeignKey(Author, on_delete=models.CASCADE)
        date = models.DateField()
    自己创建 + ManyToManyField

    手动创建关系表,再借用through函数绑定到关系表,关系信息的维护仍是手动

     class Book(models.Model):
        title = models.CharField(max_length=32)
     ​
     class Author(models.Model):
        name = models.CharField(max_length=32)
        books = models.ManyToManyField(Book, through='Book_Author')
     ​
     class Book_Author(models.Model):
        book = models.ForeignKey(Book, on_delete=models.CASCADE)
        author = models.ForeignKey(Author, on_delete=models.CASCADE)
        date = models.DateField()
         
     # 添加关系
     #方式一:
     m1 = BookAuthor(author=author对象,book=book对象)
     ​
     #方式二:
     m2 = BookAuthor.objects,create(author=author对象,book=book对象)
     ​
    仅供参考,欢迎指正
  • 相关阅读:
    windos端zabbix_agent重启报错:cannot open service
    搭建git服务器:centos环境
    git常用命令
    Centos7下ifconfig command not found 解决办法
    如何将EPEl安装在Centos7上
    linux安装openoffice,并解决中文乱码
    docker上配置mysql主从复制
    在docker上部署mysql
    linux上创建svn服务器(centos7.3)
    微信开发基于springboot
  • 原文地址:https://www.cnblogs.com/jjzz1234/p/11607940.html
Copyright © 2011-2022 走看看