Django中多对多关系的orm表设计
作者的管理
1.设计表结构
出版社 书籍 作者
一个出版社出版多个书籍 1对多
书籍和作者的关系:一个作者写多本书,一本书可以是多个作者写。多对多
1)创建一张表,表中多对多的数据关系。使用 多对多字段的方法
2)创建的这个类,会创建两个表,app_加类名(开头变小写),app_这个类名_另一张表类名
3)这个类创建的表中没有多对多的字段,多对多的关系是以这张表表名加_id和另一张表表名加_id两个字段合成的新的表,id主键自动生成
4)一般多对多字段关联的是有外键的那张表。
2.展示含有多对多关系的作者表
2.1、设计url
url(r'^author_list/', views.author_list),
2.2、写函数
# 展示作者
for author in all_authors:
print(author)
print(author.pk)
print(author.name)
print(author.books,type(author.books)) # 关系管理对象
print(author.books.all(),type(author.books.all()))
print('*'*)
def author_list(request):
# 查询所有的作者
all_authors = models.Author.objects.all()
return render(request,'author_list.html',{'all_authors':all_authors})
点击这里可清空打印内容:
打印查看各个变量的含义
<class 'django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager'> 关系管理对象
通过关系管理对象.all()拿到所有关联的对象
由上可知:从作者表author.books.all()[0].title 获得了book表的书名,那么由author.books.all()[0].pub就能获得对应的一条出版社表的记录。从这张多对多关系的表中,获取到对应多对多关系另一张表的多条记录,又由此能获得另一张表的具有外键的对应的外键表记录,三表联系在一起了。
Book和Author多对多的关系。books是Author中你想要的对象跟Book关联的所有对象。books的作用是在Author和Book中创建一个中间的关系对象,放在第三张表中,再根据这个中间的关系来获取Book中关联的对象
外键和多对多关系区别:
外键是根据book.pub拿到的就是关联的外键对象(每行数据);而多对多是Auther.books直接拿到的是一个关系管理对象,关系管理对象.all()才能拿到所有关联对象(每行数据)。
一个错误:一个函数重定向到自己这个函数会出现递归现象,达到递归上限,报错重定向次数过多,因此当这个函数想要重新返回到自身页面的时候用render,转到其它页面用render或者重定向
2.3、写模板
{% for author in all_authors %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ author.pk }}</td>
<td>{{ author.name }}</td>
<td>
{% for book in author.books.all %}
{% if forloop.last %}
《{{ book.title }}》
{% else %}
《{{ book.title }}》、
{% endif %}
{% endfor %}
</td>
</tr>
{% endfor %}
模板
将对象列表循环出来再取需要的字段,并添加书名号。
将循环出来的每个内容用顿号隔开。
如果只是在后面加个逗号,那么最后那个都会显示逗号:
for循环中批量操作数据,通过添加判断实现满足条件的输出不同内容,
3.多对多关系表的数据增加
# 新增出版社
def add_publisher(request):
error = ''
# 对请求方式进行判断
if request.method == 'POST':
# 处理POST请求
# 获取到出版社的名称
publisher_name = request.POST.get('publisher_name')
# 判断出版社名称是否有重复的
if models.Publisher.objects.filter(name=publisher_name):
error = '出版社名称已存在'
# 判断输入的值是否为空
if not publisher_name:
error = '不能输入为空'
if not error:
# 使用ORM将数据插入到数据库中
obj = models.Publisher.objects.create(name=publisher_name)
# 跳转到展示出版社的页面
return redirect('/publisher_list/')
# 返回一个包含form表单的页面
return render(request, 'add_publisher.html', {'error': error})
新增逻辑和代码
author_obj = models.Author.objects.create(name=author_name) # 只插入book表中的内容
author_obj.books.set(books) # 设置作者和书籍多对多的关系
一个功能,一个url地址,一个函数,外加一个模板。每个功能都是这样
添加作者,选择作者写的多个书籍,提交。实现多选功能:
添加作者:将提交的作者名字和作品获取到并写入数据库,然后重定向到作者展示页面
如下:在页面选中多个提交,但是get获取book的值只获取到一个,应该是选择的book列表才是我们想要的,但是get只是获取到了最后一个数值
正确使用时getlist方法,获取select中多选的值
getlist获取到的类型是列表。多选中选中多个选项获取的值:
存入数据库:
1)先用input输入的作者名字创建作者表对象
2)再获取出来select选中多个关联选项
3)新建的作者对象.books获得关系管理对象,关系管理对象.set(要关联的多个外表的id列表)。由此,这个作者表对象set设置了和外表的多条记录的关系映射,并在第三张表中体现出来
【1】插入数据【2】设置它对多的关系
如下演示:
结果如下:表之接.东西,报错对象没有这个属性,这里是缺少objects了,直接表.create会把它当做表的字段看待
正确结果:,注意create不要将给多对多的代表关系管理对象的设置值
然后再设置重定向到book_list页面
4.多对多关系表的数据删除
删除操作逻辑如下:
拿到要删除的数据id,然后查表找到对应数据进行删除再返回到展示页面
url设置,写函数,作者展示首页添加删除按钮:
删除成功;
5.多对多关系表的数据修改
books = request.POST.getlist('books')
# 修改对象的数据
author_obj.name = name
author_obj.save()
# 多对多的关系
author_obj.books.set(books) # 每次重新设置
编辑和添加的html差不多,直接复制过来修改一下:
有多对多关系的表数据编辑:
1)url
2)函数
3)html
(1)作者展示页点击编辑a标签get请求并带有编辑的对象pk跳转到编辑页
(2)编辑页不是多对多关系的字段可以用输入框
(3)是多对多关系的需要使用多选框,多选框中是另一个表中所有作品,被选中的即已经是作者的作品 是与作者pk条件相等的作者表中关系管理对象的所有对象
逻辑关系如下:
# 编辑作者
def edit_author(request):
# 查询编辑的作者对象
pk = request.GET.get('pk')
author_obj = models.Author.objects.get(pk=pk) if request.method == 'POST':
# 获取提交的数据
name = request.POST.get('author_name')
books = request.POST.getlist('books') #注意是getlist,不然只能获取到一个数字
# 修改对象的数据
author_obj.name = name
author_obj.save()
# 多对多的关系
author_obj.books.set(books) # 每次重新设置 #不管是新增还是修改都使用set就行了
# 重定向
return redirect('/author_list/') # 查询所有的书籍
all_books = models.Book.objects.all() #请求方式判断在前,因为POST中用不到这个 return render(request, 'edit_author.html', {'author_obj': author_obj, 'all_books': all_books})
每次编辑都是重新设置,也就是set之前会把和这个对象在关联表中关联的删掉并重新创建
6.django设置多对多关系三种方法
1.django帮我们生成第三张表
class Author(models.Model):
name = models.CharField(max_length=)
books = models.ManyToManyField('Book') # 不在Author表中生产字段,生产第三张表
2.自己创建第三张表
class AuthorBook(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
date = models.DateField()
注销不用books
3.自建的表和 ManyToManyField 联合使用
class Author(models.Model):
name = models.CharField(max_length=)
books = models.ManyToManyField('Book',through='AuthorBook') # 不在Author表中生产字段,生产第三张表
class AuthorBook(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCA DE)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
date = models.DateField()
1)第三种方式可以使用 ManyToManyField 方法,通过第一个字符串参数指定和哪个表关联;通过 through='自建第三张表'和自建第三张表联系起来,这样它本身不会创建第三张关联表了,而是以你写的第三张表的来作为它和它关联表之间的多对多关联关系。
2)这样的好处是我可以在django建立的关系表上添加字段(比如建立第三张关联表,图书id和作者id一一对应,但是我想要作者编写图书的时间,那么最好的地方就是放到这张表,而自建第三张表的方式才能给表添加字段;但是自建的表查询语句还要自己写,)
3)自建第三张表既能增加数据表字段,也能通过books.all()获取数据,但是不能使用set等某些方法,要想查数据还是要自己写语句
4)自建第三张表是自己设置另外两张表的外键字段
Django中多对多关系的orm表设计的更多相关文章
- Django 之多对多关系
1. 多对多关系 作者 <--> 书籍 1. 表结构设计 1. SQL版 -- 创建作者表 create table author( id int primary key auto_inc ...
- Django中的Object Relational Mapping(ORM)
ORM 介绍 ORM 概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用 ...
- Django中三种方式写form表单
除了在html中自己手写form表单外,django还可以通过 继承django.forms.Form 或django.forms.ModelForm两个类来自动生成form表单,下面依次利用三种方式 ...
- EF Codefirst 多对多关系 操作中间表的 增删改查(CRUD)
前言 此文章只是为了给新手程序员,和经验不多的程序员,在学习ef和lambada表达式的过程中可能遇到的问题. 本次使用订单表和员工表建立多对多关系. 首先是订单表: public class Ord ...
- 关于hibernate中多对多关系
关于多对多关系 数据库:在使用多对多的关系时,我们能够使用复合主键.也能够不使用,直接引入外键相同能够实现. 在数据库中使用多对多关系时,须要一个中间表. 多对多关系中的数据库结构例如以下: 表:Or ...
- Linux下开发python django程序(django数据库多对多关系)
1.多对多关系数据访问 models.py设置 from django.db import models # Create your models here. sex_choices=( ('f',' ...
- XAF中多对多关系 (XPO)
In this lesson, you will learn how to set relationships between business objects. For this purpose, ...
- django 的多对多关系
django里自带的多对多表创建 其实就是两个多对一关系各自关联,在第三张表上 多对多的增加 add()可以传数值 例如 add(1)或数组 add(*[2,3]) 多对多反向操作 自己创建第三张表, ...
- Django中利用type动态操作数据库表
场景分析: 后台MySql数据库保存了一大批按股票代码命名的数据表,每张表保存的是每只股票的日线数据. stock_000002 stock_600030 stock_600020 ...一共3000 ...
随机推荐
- SpringBoot 为什么能够自动的注入一些常用的Bean ?详细分析SpringBoot 自动配置的实现
转载至:https://blog.csdn.net/qq_29941401/article/details/79605388 有一个问题一直让我好奇,为什么在SpringBoot中有的bean 我们都 ...
- (CSDN迁移)js中的判空
<c:if test="${something.something == NaN}">style="display: none;"</c:if ...
- poj 2775 文件结构“图"
总时间限制: 1000ms 内存限制: 65536kB 描述 在计算机上看到文件系统的结构通常很有用.Microsoft Windows上面的"explorer"程序就是这样的一个 ...
- 使用 pthread_cancel 引入的死锁问题
先来说一下 pthread_cancel 基本概念. pthread_cancel 调用并不是强制终止线程,它只提出请求.线程如何处理 cancel 信号则由目标线程自己决定,可以是忽略.可以是立即终 ...
- python 坑1
目录 1.编码解码 2.基础数据类型补充: 2.1 str: 2.2list: 2.3tuple: 2.4dict: 2.5set: 3.坑 4.类型转换: 5.数据类型: 1.编码解码 编码:将文字 ...
- python基础 — random库
python中用于生成伪随机数的函数库是random 因为是标准库,使用时候只需要import random random库包含两类函数,常用的共8个 --基本随机函数: seed(), random ...
- xorm-创建时间created
package main import ( "fmt" _ "github.com/go-sql-driver/mysql" "github.com/ ...
- Django模型层之单表操作
Django模型层之单表操作 一 .ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软 ...
- pdfplumber模块初始用
import pdfplumber import re def pdf_read(): pdf=pdfplumber.open('文件路径'")#文件路径,读取文件 page0=pdf.pa ...
- vue3 template refs dom的引用、组件的引用、获取子组件的值
介绍 通过 ref() 还可以引用页面上的元素或组件. DOM 的引用 <template> <div> <h3 ref="h3Ref">Tem ...