多对多关系作用
Django 中,多对多关系模型的作用主要是为了表示两个模型之间的多对多关系。具体来说,多对多关系允许一个模型的实例与另一个模型的多个实例相关联,反之亦然。这在很多实际应用场景中非常有用,比如:
- 博客和标签:一篇博客文章可以有多个标签,一个标签也可以属于多篇博客文章。
- 学生和课程:一个学生可以选修多门课程,一门课程也可以有多个学生选修。
- 作者和书籍:一本书可以有多个作者,一个作者也可以写多本书。
以下实现简易博客和标签的示例
1,创建应用
Test/app10
python manage.py startapp app10

2,注册应用
Test/Test/settings.py

4,添加路由
Test/Test/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('app9.urls')),
# ...
path('app10/', include('app10.urls')),
]

5,添加模型
Test/app10/models.py
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
tags = models.ManyToManyField(Tag, related_name='posts')
def __str__(self):
return self.title

6,执行迁移
python manage.py makemigrations app10
python manage.py migrate app10



7,添加视图函数
Test/app10/views.py
from django.shortcuts import render
from .models import Post
def post_list(request):
posts = Post.objects.all()
return render(request, '10/post_list.html', {'posts': posts})

8,添加html代码
Test/templates/10/post_list.html
<!DOCTYPE html>
<html>
<head>
<title>Blog</title>
</head>
<body>
<h1>Blog Posts</h1>
<ul>
{% for post in posts %}
<li>
<h2>{{ post.title }}</h2>
<p>{{ post.content }}</p>
<p>Tags:
{% for tag in post.tags.all %}
{{ tag.name }}{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
</li>
{% endfor %}
</ul>
</body>
</html>

9,添加应用路由
Test/app10/urls.py
from django.contrib import admin
from django.urls import path
from app10 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('post_list', views.post_list, name='post_list'),
]

10,管理台添加数据

添加标签

添加文章并关联标签
11,访问页面
http://127.0.0.1:8000/app10/post_list

12,查看数据库
app10_tag 标签表

app10_post 文章表

app10_post_tags

可以看到app10_post_tags表关联另外两张表的id,建立了多对多的关系关系
13,删除文章
13.1 添加删除文章视图函数
Test/app10/views.py
from django.shortcuts import render
from .models import Post
def post_list(request):
posts = Post.objects.all()
return render(request, '10/post_list.html', {'posts': posts})
from django.shortcuts import render, get_object_or_404, redirect
from .models import Post
def delete_post(request, post_id):
post = get_object_or_404(Post, id=post_id)
if request.method == 'POST':
post.delete()
return redirect('post_list')
return render(request, '10/confirm_delete.html', {'post': post})

13.2 添加html代码
Test/templates/10/confirm_delete.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- templates/blog/confirm_delete.html -->
<form method="post">
{% csrf_token %}
<p>你确认要删除文章吗?</p>
<button type="submit">确认</button>
</form>
</body>
</html>

13.3 添加路由地址
Test/app10/urls.py
from django.contrib import admin
from django.urls import path
from app10 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('post_list', views.post_list, name='post_list'),
path('delete_post/<int:post_id>/', views.delete_post, name='delete_post'),
]

13.4 访问页面
http://127.0.0.1:8000/app10/delete_post/2/

14,对比数据库数据
删除前



删除后

可以看到,我们通过post_id删除文章和关系表的数据,但是为什么标签表没有被删除呢?
在 Django 中,当你删除一个模型实例时,Django 会自动处理与该实例相关的多对多关系,但不会删除关联的标签。这是因为标签可能与其他文章也有关系,删除标签会影响其他数据的完整性。
-
多对多关系的管理:
- 在 Django 中,多对多关系通过一个中间表来管理。当你删除一个
Post
实例时,Django 会自动删除中间表中与该Post
实例相关的记录,但不会删除Tag
表中的记录。
- 在 Django 中,多对多关系通过一个中间表来管理。当你删除一个
-
数据完整性:
- 标签(
Tag
)通常是共享资源,可能被多个文章(Post
)使用。如果删除某篇文章时也删除了标签,那么其他使用该标签的文章就会受到影响。因此,Django 默认不会删除标签。
- 标签(
Django admin后台及创建超级账号可参考: