django - 使用 2 个外键将字段添加到序列化程序
问题描述
我有 2 个看起来像这样的模型:
class Topic(models.Model):
name = models.CharField(max_length=25, unique=True)
def save(self, *args, **kwargs):
topic = Topic.objects.filter(name=self.name)
if topic:
return topic[0].id
super(Topic, self).save(*args, **kwargs)
return self.id
class PostTopic(models.Model):
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
post= models.ForeignKey(Post, on_delete=models.CASCADE)
如果主题已经在Topic
表中,那么我们返回该主题的 id。我们不创造另一个。当用户提交Post
带有标签的主题(将其视为主题标签)时,如果这些主题不存在于Topic
表中,则它们将与中的关系一起创建PostTopic
话虽如此,这就是我的序列化程序的外观:
class PostSerializer(serializers.ModelSerializer):
topics = serializers.ListField(
child=serializers.CharField(max_length=256), max_length=3
)
class Meta:
model = Post
fields = ('user', 'status', 'topics')
def create(self, validated_data):
topics= validated_data.pop('topics')
post = Post.objects.create(**validated_data)
for topic in topics:
topic_id = Topic(name=topic).save()
PostTopic(post_id=post.id, topic_id=topic_id).save()
return post
目前,我的序列化程序给了我一个AttributeError
, 因为主题不是Post
. 我该如何解决这个问题才能让它工作?如果我使用PostTopic
,那么我将如何让用户给出实际的主题?
解决方案
我认为您正在寻找和之间的Many To Many
关系。您可以像这样添加它:Post
Topic
class Post(models.Model):
# rest of the fields
topics = models.ManyToManyField('Topic', through='PostTopic')
class Topic(models.Model):
name = models.CharField(max_length=25, unique=True)
# def save(self, *args, **kwargs):
# **Important:** Django model's save function does not return anything. So handling it here won't be good. Let us handle duplicate entry in serializer
# topic = Topic.objects.filter(name=self.name)
# if topic:
# return topic[0].id
# super(Topic, self).save(*args, **kwargs)
# return self.id
class PostTopic(models.Model):
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
post= models.ForeignKey(Post, on_delete=models.CASCADE)
此外,您处理重复项的方法将不起作用,因为模型的保存方法不返回任何内容。让我们在序列化程序中处理它并进行一些小修复:
class PostSerializer(serializers.ModelSerializer):
topics = serializers.ListField(
child=serializers.CharField(max_length=256), max_length=3
)
class Meta:
model = Post
fields = ('user', 'status', 'topics')
def create(self, validated_data):
topics= validated_data.pop('topics')
post = Post.objects.create(**validated_data)
for topic in topics:
new_topic, _ = Topic.objects.get_or_create(name=topic)
PostTopic(post_id=post.id, topic=new_topic).save()
return post
推荐阅读
- javascript - Javascript从日期减/加1个月
- python - Heroku - Python - Matplotlib
- html - 有没有用例
- angular - Angular 9:如果在动画结束之前再次触发,如何重新启动动画
- angular - 每次我创建一个新的 Angular 项目时,它都会给我 5k 次提交
- java - Spring缓存默认大小
- javascript - 如何使用 React Native 中的 props 将数组从父组件传递到子组件?
- java - 如何获取选定区域设置的所有国家字符?
- asp.net - 如何在 aspx 文件后面的代码中迭代地创建 asp:button?
- python - 生成已知字符的单词表