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
классов, то в конце, после того как таблица будет разрушена, она выполнит проверку БД и вызовет ошибку.