django学习-34.【多对多】表关系对应的完整业务操作

little-hong 2021-10-26 10:17:55
学习 django 关系 完整 对应

目录结构

 

1.写这篇博客的目的

2.【多对多】的表关系对应的业务例子

3.完整操作流程

3.1.第一步:在【helloworld/hello/models.py】里新增模型类

3.2.第二步:在【helloworld/hello/admin.py】里注册模型类

3.3.第三步:在【helloworld/】根目录下执行生成数据表的相关语句

3.4.第四步:重启服务

3.5.第五步:成功登陆admin管理后台

3.6.第六步:在后台新增2个作者信息

3.7.第七步:在后台新增1本书籍信息

4.相关知识点

4.1.类ManyToManyField里的一个必填参数对应入参值的简单分析

4.1.1.第一步:看类ManyToManyField源码里的【__init__】方法里的内容

4.1.2.第二步:结合实际业务代码,对必填参数【to】的参数值做分析

4.1.2.1.对必填参数【to】的参数值的理解

4.2.当一张【多】表的数据被删除后,对应另外一张【多】表的数据和中间表的数据会有对应的哪些变化的操作记录

 

 

 

 

1.写这篇博客的目的

主要记录:

  1. 如何通过django去创建【多对多】的表关系;
  2. 以及如何通过【多对多】的表关系去走对应的完整业务操作;
  3. 通过修改django里的哪些代码配置,使当一张【多】表的数据被删除后,对应另外一张【多】表的数据和中间表的数据会有对应的哪些变化? 

2.【多对多】表关系对应的业务例子

我们在现实生活里会遇到很多多对多的场景。

比如一个最常见的例子是:一本书可以有多个作者,一个作者也可以写多本书,书和作者就是多对多的关系;

一般会建三张数据表,一张表放书的信息,一张表放作者的信息,一张中间表一般有三个表字段且三个表字段分别存放书的主键值和作者的主键值和中间表本身的主键值;

 

完整操作流程可以看接下来的内容;

3.完整操作流程

3.1.第一步:在【helloworld/hello/models.py】里新增模型类

from django.db import models
class Auther(models.Model):
'''作者'''
name = models.CharField(max_length=10, verbose_name="作者")
mail = models.CharField(max_length=30, verbose_name="邮箱")
city = models.CharField(max_length=10, verbose_name="城市")
class Meta:
verbose_name_plural = '作者'
def __str__(self):
return self.name
class Book(models.Model):
'''书籍'''
book_name = models.CharField(max_length=50, verbose_name="书名")
auther_of_be_associated = models.ManyToManyField(to=Auther) class Meta:
verbose_name_plural = '书籍'
def __str__(self):
return self.book_name

3.2.第二步:在【helloworld/hello/admin.py】里注册模型类

from django.contrib import admin
# Register your models here.
from hello import models
class ControlAuther(admin.ModelAdmin):
'''作者信息'''
# 显示的字段
list_display = ["id","name", "city", "mail"]
class ControlBook(admin.ModelAdmin):
'''书信息'''
# 显示的字段
# 属性list_display里的索引值为1对应的【'被关联的作者'】,这是我们自定义的要展示在列表页面的列表字段(该列表字段不是表里的表字段),且这必须是这个类ControlBook里的我们手工创建的方法名【被关联的作者】;
list_display = ["book_name",'被关联的作者' ]
# 第一步:定义一个方法(方法名任意,方法名为中文也可以只是不规范),比如方法名为【被关联的作者】;
# 第二步:在方法【被关联的作者】里,首先调用模型类Book提供的方法【all()】即通过【obj.auther_of_selected.all()】,获取到book表里的一条书籍数据关联的auther表里的0到多条的完整的作者数据(每条作者数据都包含了每个表字段和每个表字段对应的表字段值);
# 细节:【obj.auther_of_selected.all()】里的【auther_of_selected】是模型类Book里的一个属性且这个属性的属性值必须是类ManyToManyField被实例化后生成的对象;
# 第三步:在方法【被关联的作者】里,接着用for遍历获取每条作者数据里的表字段name的表字段值并用list类提供的append方法用一个空列表来存储这些表字段值,然后返回这个列表;
def 被关联的作者(self,obj):
# 第一种写法,官方推荐写法,语法最简洁,因为只需要一行代码;
# return [a.name for a in obj.auther_of_selected.all()]
# 第二种写法,个人根据第一种写法写的比较简单易懂的写法,语法不简洁,因为需要多行代码;
emptyList = []
for a in obj.auther_of_be_associated.all():
emptyList.append(a.name)
return emptyList
# list_display = ["book_name",'show_all_auther_of_be_associated' ]
# def show_all_auther_of_be_associated(self,obj):
# # return [a.name for a in obj.auther_of_selected.all()]
# emptyList = []
# for a in obj.auther_of_be_associated.all():
# emptyList.append(a.name)
# return emptyList

3.3.第三步:在【helloworld/】根目录下执行生成数据表的相关语句

执行的相关语句和顺序是:

  1. 首先,先执行语句【python manage.py makemigrations】
  2. 最后,再执行语句【python manage.py migrate】

 相关结果如下:

  1. 会生成三张对应的数据表,其中会包含一张中间表;

 

 

3.4.第四步:重启服务

3.5.第五步:成功登陆admin管理后台

3.6.第六步:在后台新增2个作者信息

 

 

 

3.7.第七步:在后台新增1本书籍信息

 

 

 

 

4.相关知识点

4.1.类ManyToManyField里的一个必填参数对应入参值的简单分析

细节:

  1. 从类ManyToManyField的类名,可以直观知道单词ManyToManyField的中文含义是【多对多】;

4.1.1.第一步:看类ManyToManyField源码里的【__init__】方法里的内容

class ManyToManyField(RelatedField):
"""
Provide a many-to-many relation by using an intermediary model that
holds two ForeignKey fields pointed at the two sides of the relation.
Unless a ``through`` model was provided, ManyToManyField will use the
create_many_to_many_intermediary_model factory to automatically generate
the intermediary model.
"""
# Field flags
many_to_many = True
many_to_one = False
one_to_many = False
one_to_one = False
rel_class = ManyToManyRel
description = _("Many-to-many relationship")
def __init__(self, to, related_name=None, related_query_name=None,
limit_choices_to=None, symmetrical=None, through=None,
through_fields=None, db_constraint=True, db_table=None,
swappable=True, **kwargs):
try:
to._meta
except AttributeError:
assert isinstance(to, str), (
"%s(%r) is invalid. First parameter to ManyToManyField must be "
"either a model, a model name, or the string %r" %
(self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT)
)
if symmetrical is None:
symmetrical = (to == RECURSIVE_RELATIONSHIP_CONSTANT)
if through is not None:
assert db_table is None, (
"Cannot specify a db_table if an intermediary model is used."
)
kwargs['rel'] = self.rel_class(
self, to,
related_name=related_name,
related_query_name=related_query_name,
limit_choices_to=limit_choices_to,
symmetrical=symmetrical,
through=through,
through_fields=through_fields,
db_constraint=db_constraint,
)
self.has_null_arg = 'null' in kwargs
super().__init__(**kwargs)
self.db_table = db_table
self.swappable = swappable

截取这部分源码:

 def __init__(self, to, related_name=None, related_query_name=None,
limit_choices_to=None, symmetrical=None, through=None,
through_fields=None, db_constraint=True, db_table=None,
swappable=True, **kwargs):

从这部分源码可以简单看出来:类ManyToManyField被实例化时,必须给一个必填参数【to】赋值,其他入参的入参值一般情况下保持默认值即可;

4.1.2.第二步:结合实际业务代码,对必填参数【to】的参数值做分析

实际业务代码如下:

class Auther(models.Model):
'''作者'''
name = models.CharField(max_length=10, verbose_name="作者")
mail = models.CharField(max_length=30, verbose_name="邮箱")
city = models.CharField(max_length=10, verbose_name="城市")
class Meta:
verbose_name_plural = '作者'
def __str__(self):
return self.name
class Book(models.Model):
'''书籍'''
book_name = models.CharField(max_length=50, verbose_name="书名")
auther_of_be_associated = models.ManyToManyField(to=Auther) class Meta:
verbose_name_plural = '书籍'
def __str__(self):
return self.book_name

截取这部分业务代码:

auther_of_be_associated = models.ManyToManyField(to=Auther)

4.1.2.1.对必填参数【to】的参数值的理解

参数【to】的含义是:关联到对应的一张表(这张表在多对多表关系里是两张表里被关联的那张表);

参数【to】的参数值:必须只能是这个【多对多表关系里的】两个模型类里的其中一个被关联的模型类的模型类名;

 

4.2.当一张【多】表的数据被删除后,对应另外一张【多】表的数据和中间表的数据会有对应的哪些变化的操作记录

 

假设作者表现在有这样两条数据(我们把这两条数据分别命名为数据A和数据B,方便后续相关文案的描述):

  

假设书籍表现在有这样两条数据(我们把这两条数据分别命名为数据C和数据D,方便后续相关文案的描述):

 

 

 假设作者表和书籍表共同对应的中间表现在有这样四条数据(我们把这四条数据分别命名为数据E1和数据E2和数据E3和数据E4,方便后续相关文案的描述):

细节:

  1. 中间表这四条数据的含义是:书籍1的作者是:作者1和作者2、书籍2的作者是:作者1和作者2;

 

 

数据都造好了,接着我们验证这些删除场景(我都已在本地调试通过):

  1. 当从admin管理后台,从作者列表里删除了【作者1】,那么:作者表里的数据A会被删掉、中间表里的数据E1和数据E3会被删掉;
  2. 当从admin管理后台,从作者列表里删除了【书籍1】,那么:书籍表里的数据C会被删掉、中间表里的数据E1和数据E2会被删掉;

 

版权声明
本文为[little-hong]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/xiamen-momo/p/14473524.html

  1. L'implémentation Python lit simplement le contenu d'Excel et signale les erreurs
  2. 用Python定义一个函数,接收n个数字,求这些参数数字的和
  3. Définissez une fonction en python, recevez n nombres et additionnez ces nombres de paramètres
  4. 上电Python写文件后,再断电后导致文件内容丢失
  5. 上電Python寫文件後,再斷電後導致文件內容丟失
  6. Une fois que Python est allumé pour écrire des fichiers, le contenu des fichiers est perdu après une panne de courant
  7. python套接字编程报错:ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的连接。
  8. 【Python从入门到精通】(二)怎么运行Python呢?有哪些好的开发工具(PyCharm)
  9. 【Python从入门到精通】(二)怎么运行Python呢?有哪些好的开发工具(PyCharm)
  10. Python语法1
  11. 2018年度最受推荐的10本Python书籍(初学者必看)
  12. Les 10 livres Python les plus recommandés en 2018 (obligatoire pour les débutants)
  13. Syntaxe Python 1
  14. Python语法1
  15. 在python 运行celery时候 AttributeError: 'NoneType' object has no attribute 'Redis'错误
  16. Attributeerror: 'nonetype' Object has no attribute 'redis' Error when Celery is running in Python
  17. Syntaxe Python 1
  18. Python celery is a plug-in that focuses on distributed asynchronous task processing and task scheduling!
  19. Python celery is a plug-in that focuses on distributed asynchronous task processing and task scheduling!
  20. 在python,使用scrapy爬虫框架
  21. It's time for everyone to see your blog written in Django (including deployment tutorial video)
  22. Python扩展速记符 要求用for循环,if语句
  23. Python擴展速記符 要求用for循環,if語句
  24. Le sténographe d'extension Python nécessite une boucle pour, si instruction
  25. Python+人工智能就业班v5.0wumi
  26. python编程技术的题目,希望能得到解答
  27. Pandas determines the header row dynamically
  28. 关于#python#的问题:模拟登陆后能获取到cookie,就是cookie一天就过期
  29. pandas为dataframe添加新的数据行(rows)、在dataframe后面纵向添加一行数据(数据为列表list形式)、列有不匹配将会使用NA值进行填补
  30. pandas使用组合条件筛选、过滤数据行
  31. 热烈祝贺1024,求解Python3.10闪退问题
  32. Python基础题练习题库有没呢?
  33. python构建神经网络,正向和反向传播
  34. python爬虫输入数字翻页才成功,用变量代替不成功,为什么?
  35. 【Python 爬虫】 2、HTTP基本原理
  36. 【Python 爬虫】 1、爬虫基础概念
  37. Python中如何用find函数计数?
  38. 一文搞懂Python装饰器
  39. python数据结构之递归
  40. 关于#python#的问题:为什么这个open函数会报错
  41. Python:多输入数字求和(Python 程序控制结构)
  42. python忽略警告
  43. Python多维数组问题(编写程序统计成绩)
  44. 一步一步展示并总结Python的异常【建议收藏】
  45. Python中奇葩的round函数!
  46. 总结一下Python的模块加载解析
  47. 保姆级指导给Python库创建桌面快捷方式【赶紧收藏】
  48. 多图速成Python基础语法下篇【万字建议收藏】
  49. Python 命令行工具辅助getopt使用解析!
  50. 【python种子项目ppc】保姆级别指导给项目添加测试
  51. 【python种子项目ppc】一行代码生成项目与开发详细指导
  52. 保姆级教程带你开发优质的Python库之下篇【种子项目】
  53. 保姆级教程带你开发优质的Python库之中篇【命令行发行】
  54. 保姆级教程带你开发优质的Python库之上篇【建议收藏】
  55. python列表自动计算总分程序
  56. 某企业职工的月薪问题python 求解 不知道自己哪里写错了
  57. Python中外部函数对class类中的属性的调用
  58. 朋友股票亏惨了,我一怒用Python爬取了证券最新数据
  59. 习题8和9怎么写(Python基础)
  60. python数据分析,求任务4,5