Django - Извлечение хэш-тегов из сообщения и сохранение их в виде отношения "многие к одному".
У меня есть такой код, когда пользователь отправляет сообщение, он извлекает из него все хэш-теги, затем создает новую запись в таблице хэш-тегов, а также создает новую ссылку в таблице HashTagsInPost, чтобы люди могли искать сообщения по хэш-тегам. Мои основные проблемы лежат в файле Views.py.
Проблемы:
- 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)
Во-первых, исходя из вашего случая использования, Post
может быть связан с несколькими HashTags
(примечание: имена моделей в идеале должны быть единственного числа) объектами. В то время как при вашем текущем моделировании пост может иметь только один хэштег. Для моделирования отношений "многие ко многим вы должны использовать ManyToManyField
[Django docs], которая внутренне создаст таблицу-перекресток, имеющую внешние ключи к двум связанным таблицам:
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')
Теперь для решения проблемы получения / создания тега, вы можете использовать функцию get_or_create
:
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) 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)