文章目录
- 前言
- 一、关联关系模型
- 二、一对多写入数据
- 二、多对多写入数据
- 二、跨表查询
- 1.查找'test' 标签的文章
- 2.查找作者名为 'test' 的文章及标签
- 三、跨表删除
前言
表与表之间的关系可分为以下三种:
一对一: 一对一关系表示一个模型的每个实例与另一个模型的每个实例都只关联一次
用 OneToOneField 来定义这种关系
一对多: 一对多关系表示一个模型的每个实例可以关联多个另一个模型的实例,但另一个模型的实例只能关联一个前者的实例
用 ForeignKey 来定义这种关系
多对多: 多对多关系表示两个模型的每个实例可以与对方的多个实例关联
用 ManyToManyField 来定义这种关系
之前我们定义了一个article模型,我们就基于这个模型实现关联关系
一、关联关系模型
更新fa下models.py
from django.db import models
class Tag(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50, unique=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Author(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
email = models.EmailField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Article(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255)
content = models.TextField()
author = models.ForeignKey(Author, null=True, on_delete=models.CASCADE)
# ManyToManyField不会直接在article表显示tag相关字段
# Django 会为 ManyToManyField 创建一个中间表来存储 Article 和 Tag 之间的多对多关系
# Django 会创建一个类似于 article_tags 的中间表,它包含 article_id 和 tag_id 两个字段,分别表示 Article 和 Tag 之间的关联
tags = models.ManyToManyField(Tag, blank=True, related_name='articles') # Many-to-many relationship with Tag model
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
再次生成和应用迁移:
python manage.py makemigrations
python manage.py migrate
二、一对多写入数据
views.py增加方法
def add_article(request):
author = models.Author.objects.filter(pk=1).first()
article = models.Article.objects.create(title="Test Article", content='123456', author=author)
return HttpResponse(article)
urls.py增加路由
path('add_article', views.add_article, name='add_article')
访问链接http://127.0.0.1:8082/article/add_article
二、多对多写入数据
views.py里面新增方法
def add_tag(request):
tag = models.Tag.objects.filter(pk=1).first()
article = models.Article.objects.filter(pk=1).first()
# add() 在即外键中只能传对象( *QuerySet数据类型)不能传 id(*[id表])
article.tags.add(tag)
return HttpResponse(article.tags.all())
urls.py增加路由
path('add_tag', views.add_tag, name='add_tag'),
访问链接http://127.0.0.1:8082/article/add_tag
刷新中间表可以看到
二、跨表查询
1.查找’test’ 标签的文章
新增方法
def search(request):
# 查找名称为 'test' 的标签
tag = models.Tag.objects.filter(name="test").first()
if not tag:
return HttpResponse("Tag not found")
# 使用相关名称访问相关文章
# Article模型设置了 related_name,则应该使用这个名称来访问反向关系。例如,如果 related_name 设置为 articles,则应使用 tag.articles.all()。
# 而如果没有设置 related_name,则应该使用 tag.article_set.all()。
articles = tag.articles.all()
# 将结果转换为字符串以便返回
articles_list = "\n".join([f"Title: {article.title}, Content: {article.content}" for article in articles])
return HttpResponse(articles_list)
访问链接http://127.0.0.1:8082/article/search
2.查找作者名为 ‘test’ 的文章及标签
方法及路由如下
def search_by_author(request):
# 查找作者名为 'test' 的作者
author = models.Author.objects.filter(name="test").first()
if not author:
return HttpResponse("Author not found")
# 查询作者的所有文章,并预取每篇文章的所有标签
articles = author.article_set.prefetch_related('tags').all()
# 构建文章及其标签的字符串
articles_list = []
for article in articles:
tags = ", ".join(tag.name for tag in article.tags.all()) # 获取文章的所有标签
articles_list.append(f"Title: {article.title}, Content: {article.content}, Tags: {tags}")
# 将结果转换为字符串并返回
return HttpResponse("\n".join(articles_list))
path('search_by_author', views.search_by_author, name='search_by_author'),
三、跨表删除
方法及路由如下
def delete_author_articles(request):
# 查找名称为 'test' 的作者
author = models.Author.objects.filter(name="test").first()
if not author:
return HttpResponse("Author not found")
# 获取该作者下的所有文章
articles = author.article_set.all()
# 删除这些文章
articles.delete()
return HttpResponse("All articles by 'test' have been deleted")
path('delete_author_articles', views.delete_author_articles, name='delete_author_articles'),
访问链接http://127.0.0.1:8082/article/delete_author_articles
刷新fa_article及中间表fa_article_tags可以看到数据都被清空了