我正在尝试创建一种关系,可以为博客文章分配任意数量的标签,并且可以将标签与任意数量的博客文章相关联。我希望能够使用Django管理界面为帖子分配标签,并为标签分配帖子。
现在,要创建博客帖子并分配任意数量的标签,这是我的帖子模型:
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=100, unique=True, null=True, blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
updated_on = models.DateTimeField(auto_now=True)
tags = models.ManyToManyField("Tags", blank=True)
content = RichTextUploadingField()
created_on = models.DateTimeField(auto_now_add=True)
以及定义标签的模型:
class Tag(models.Model):
name = models.CharField(max_length=20, unique=True)
这有效。我可以登录到管理界面并创建一堆标签对象,然后创建一个发布对象并为其分配任意数量的这些标签。
但是,我也想做相反的事情。我希望能够登录到管理界面,选择一个标记对象,然后将其与任意数量的发布对象相关联。
我试图通过在ManyToManyField
模型中定义一个Tag
来做到这一点,例如:
class Tag(models.Model):
name = models.CharField(max_length=20, unique=True)
posts = models.ManyToManyField("Post", blank=True, related_name="posts")
这确实显示了更改标签页面上的帖子列表,但我只希望它显示与该帖子关联的标签。使用管理界面,我希望能够选择其他标签来分配给该帖子。因此,我然后尝试使用ForeignKey
,但这只会允许我选择一个帖子。
我知道如何用一个单独的查询覆盖默认管理员ModelAdmin.change_form_template
,以显示分配给帖子的标签。但是我不确定是否有一种方法可以覆盖默认模板。
修改:我已经修改了此问题,以阐明我要实现的目标。我现在认为我的模型设置正确。但是我(可能是错误地)认为我可以将另一个字段添加到第二个模型中,以使其出现在管理界面中。
答案 0 :(得分:1)
多对多字段是用于定义双向关系的字段。但是,您似乎很困惑,因为在Django代码上编写模型时只需要定义一个模型即可。参见ManyToMany relationship doc
这是两个模型。
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
tags = models.ManyToManyField("Tag", related_name='posts')
class Tag(models.Model):
name = models.CharField(max_length=20, unique=True)
此代码将在您的数据库中创建三个表。 posts
,tags
和post_tags
。 post_tags
是中间表。它具有id
,post_id
,tag_id
个字段。
p1 = Post.objects.create(title='Post 1')
p2 = Post.objects.create(title='Post 2')
p3 = Post.objects.create(title='Post 3')
t1 = Tag.objects.create(title='Tag 1')
t2 = Tag.objects.create(title='Tag 2')
t3 = Tag.objects.create(title='Tag 3')
p1.tags.add(t1, t2)
p1.tags.all()
>>> [Tag 1, Tag 2]
t1.posts.all()
>>> [Post 1]
t2.posts.add(p2, p3)
t2.posts.all()
>>> [Post 1, Post 2, Post 3]
post_tags
表项目:
id | post_id | tag_id
---------------------
1 | 1 | 1
2 | 1 | 2
3 | 2 | 1
4 | 3 | 1
“多对多”字段只能在一个模型中定义,如果在相反的模型中定义,则会创建重复的双向关系。
this doc解释了如何实现可以从标签页面选择帖子的管理员。
答案 1 :(得分:0)
我正在把它变得比原来需要的要困难得多。为了使用管理界面使用问题中的模型为帖子分配标签,我只需要创建一个Inline
类:
class TagInline(admin.StackedInline):
model = Tag.post.through
然后在inlines
下的PostAdmin
中指定它:
inlines = [TagInline]
现在,这些关系显示在管理界面的Posts对象中。
感谢@YongjinJo让我走上正轨!