Issue
So I have this code below that when a user submits a post it extracts all the hash tags from it then creates a new entry in the hash tag table and also creates a new reference in the HashTagsInPost table so people can search posts by hash tags. My primary concerns lay in the Views.py file.
Problems:
- I don't think it's good to iterate over the list of hash tags pulled out and doing a .get() call to see if exists then if it doesn't create it. There should be a better way to do this.
- Since HashTagsInPost is a one-to-many relation, I don't really know how to store that lists of Hash Tags as the hash_tag attribute in the HashTagsInPost attribute. Do I just pass a list of HashTag objects?
Views.py
def post(self, request):
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
post_body = request.data['body']
post_obj = serializer.save()
hash_tags_list = extract_hashtags(post_body)
for ht in hash_tags_list:
try:
ht_obj = HashTags.objects.get(pk=ht)
except HashTags.DoesNotExist:
ht_obj = HashTags.objects.create(hash_tag=ht)
HashTagsInPost.objects.create(hash_tag=ht_obj, post_id=)
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Models.py
class HashTags(models.Model):
hash_tag = models.CharField(max_length=140, primary_key=True)
class Post(AbstractBaseModel):
creator_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name="post_creator_id", db_index=True)
goal_id = models.ForeignKey(Goal, on_delete=models.CASCADE, db_index=True)
body = models.CharField(max_length=511)
class HashTagsInPost(AbstractBaseModel):
hash_tag = models.ForeignKey(HashTags, on_delete=models.CASCADE, db_index=True)
post_id = models.OneToOneField(Post, on_delete=models.CASCADE)
Solution
Firstly from your use case a Post
can be related to multiple HashTags
(note: model names should ideally be singular) objects. Whereas with your current modelling a post can have only one hashtag. To model a many to many relationship you should use a ManyToManyField
[Django docs] which will internally make a junction table having foreign keys to the two related tables:
class HashTags(models.Model):
hash_tag = models.CharField(max_length=140, primary_key=True)
class Post(AbstractBaseModel):
creator_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name="post_creator_id", db_index=True)
goal_id = models.ForeignKey(Goal, on_delete=models.CASCADE, db_index=True)
body = models.CharField(max_length=511)
# Add a m2m with HashTags
hash_tags = models.ManyToManyField(HashTags, related_name='posts')
Now for your problem of getting / creating the tag, you can use the get_or_create
function:
def post(self, request):
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
post_body = request.data['body']
post_obj = serializer.save()
hash_tags_list = extract_hashtags(post_body)
hash_tags = [HashTags.objects.get_or_create(hash_tag=ht)[0] for ht in hash_tags_list]
post_obj.hash_tags.set(hash_tags)
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Answered By - Abdul Aziz Barkat
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.