Django - Сериализатор выбрасывает "Invalid pk - object does not exist" при установке атрибута ManyToMany, когда объект с внешним ключом существует

Ниже у меня есть код, который тестирует функциональность, когда кто-то создает пост, и этот пост имеет hash_tag, который в данном случае является "#video". Код берет Post body и использует regex для поиска любого слова, которое начинается с "#". Если это так, то он создает или получает это HashTag из таблицы HashTag. Затем устанавливает этот список HashTag в атрибут hash_tags под Post.

По какой-то причине сериализатор CreatePostSerializer выбрасывает исключение, которое не имеет смысла. Сериализатор выбрасывает исключение ValidationError({'hash_tags': [ErrorDetail(string='Invalid pk "[\'video\']" - object does not exist.', code='does_not_exist')]}). Это происходит потому, что когда я отлаживаю и устанавливаю точку останова сразу после except Exception as e под views.py вот что я получаю

>>>e
ValidationError({'hash_tags': [ErrorDetail(string='Invalid pk "[\'video\']" - object does not exist.', code='does_not_exist')]})
>>>HashTag.objects.get(pk='video')
<HashTag: HashTag object (video)>
>>>request.data['hash_tags']
['video']

Итак, >>> представляет собой то, что я ввел в отладчик. По сути, я остановился на строке return Response..., и мы видим e - это ValidationError, о котором я говорил, но мы видим, что объект, который, как он утверждает, не существует, действительно существует. Почему сериализатор выбрасывает "ValidationError - объект не существует", когда он существует?

test.py

def test_real_image_upload_w_hash_tag(self):
    image_file = retrieve_test_image_upload_file()
    hash_tag = 'video'
    response = self.client.post(reverse('post'),
                                data={'body': f'Some text and an image #{hash_tag}',
                                      'images': [image_file]},
                                **{'HTTP_AUTHORIZATION': f'bearer {self.access_token}'})
    self.assertEqual(response.status_code, status.HTTP_201_CREATED)

views.py

def set_request_data_for_post(request, user_uuid: str):
    request.data['creator'] = user_uuid
    post_text = request.data['body']
    hash_tags_list = extract_hashtags(post_text)
    hash_tags = [HashTag.objects.get_or_create(hash_tag=ht)[0].hash_tag for ht in hash_tags_list]

    if len(hash_tags) > 0:
        request.data['hash_tags'] = hash_tags

    return request

def create_post(request):
    user_uuid = str(request.user.uuid)
    request = set_request_data_for_post(request=request, user_uuid=user_uuid)

    try:
        serializer = CreatePostSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            post_obj = serializer.save()
    except Exception as e:
        return Response(dict(error=str(e),
                             user_message=error_message_generic),
                        status=status.HTTP_400_BAD_REQUEST)

    return Response(serializer.data, status=status.HTTP_201_CREATED)

serializer.py

from rest_framework import serializers
from cheers.models import Post

class CreatePostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ('creator', 'body', 'uuid', 'created', 'updated_at', 'hash_tags')

model.py

class Post(models.Model):
    # ulid does ordered uuid creation
    uuid = models.UUIDField(primary_key=True, default=generate_ulid_as_uuid, editable=False)
    created = models.DateTimeField('Created at', auto_now_add=True)
    updated_at = models.DateTimeField('Last updated at', auto_now=True, blank=True, null=True)
    creator = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name="post_creator")
    body = models.CharField(max_length=POST_MAX_LEN, validators=[MinLengthValidator(POST_MIN_LEN)])
    hash_tags = models.ManyToManyField(HashTag, blank=True)

class HashTag(models.Model):
    hash_tag = models.CharField(max_length=HASH_TAG_MAX_LEN, primary_key=True, validators=[
        MinLengthValidator(HASH_TAG_MIN_LEN)])

под вашим test/__init__.py вы должны добавить эти строки

from django.db.backends.postgresql.features import DatabaseFeatures

DatabaseFeatures.can_defer_constraint_checks = False

Есть какая-то странная внутренняя ошибка, когда если вы часто работаете с одной таблицей с большим количеством различных TestCase классов, то в конце, после того как таблица будет разрушена, она выполнит проверку БД и вызовет ошибку.

Вернуться на верх