Django - Извлечение хэш-тегов из сообщения и сохранение их в виде отношения "многие к одному".

У меня есть такой код, когда пользователь отправляет сообщение, он извлекает из него все хэш-теги, затем создает новую запись в таблице хэш-тегов, а также создает новую ссылку в таблице HashTagsInPost, чтобы люди могли искать сообщения по хэш-тегам. Мои основные проблемы лежат в файле Views.py.

Проблемы:

  1. 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.
  2. 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)
Вернуться на верх