Reputation: 3282
I have 2 models that look like this:
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)
If the topic is already in the Topic
table, then we return the id of that topic. We do not create another. When a user submits a Post
with tagged topics (think of it as hashtags), then if those topics don't exist in the Topic
table they will be created along with the relationship in PostTopic
That being said, here's how my serializer looks:
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
Currently, my serializer gives me an AttributeError
, because topics is not a field in Post
. How can I fix this so that I can make it work? If I use PostTopic
then how would I get the user to give the actual topics?
Upvotes: 0
Views: 131
Reputation: 51988
I think you are looking for a Many To Many
relationship between Post
and Topic
. You can add it like this:
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)
Also, your method of handling duplicates won't work because model's save method does not return anything. Let us handle it in serializer with with some minor fixes:
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
Upvotes: 1