Получили `TypeError` при вызове `Post.objects.create()`. Это может быть связано с тем, что у вас есть записываемое поле в классе сериализатора, которое является
Пишу приложение Django, в котором есть таблица post, имеющая рекурсивные отношения к самой себе. Это означает, что пост МОЖЕТ иметь родительский пост (позволяет делать ответы). Я хочу убедиться, что пост может иметь null для атрибута parent post - это будет обозначать "корневой" пост. Однако, когда я реализую представления, модель и сериализатор для постов, я получаю следующую ошибку (трассировка стека):
Got a `TypeError` when calling `Post.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `Post.objects.create()`. You may need to make the field read-only, or override the PostSerializer.create() method to handle this correctly.
Original exception was:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/rest_framework/serializers.py", line 962, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/models/query.py", line 669, in create
obj = self.model(**kwargs)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/models/base.py", line 564, in __init__
_setattr(self, field.attname, val)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/models/fields/related_descriptors.py", line 606, in __set__
raise TypeError(
TypeError: Direct assignment to the reverse side of a related set is prohibited. Use parent_post_id.set() instead.
Вот моя модель:
class PostObjects(models.Manager):
"""
Return the Post object and all children posts
"""
def get_queryset(self):
return super().get_queryset().filter(id='')
title = models.CharField(max_length=250)
body = models.TextField()
# Author deletion cascade deletes all of author's posts
author = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='forum_posts')
# if a post is deleted, all children posts will also be deleted
# defines recursive many-to-one relationship
parent_post = models.ForeignKey('self',
on_delete=models.CASCADE,
blank=True,
null=True,
related_name='parent_post_id')
time_stamp = models.DateTimeField(default=timezone.now)
# Default object manager
objects = models.Manager()
# Custom object manager for a particular object
post_objects = PostObjects()
def __str__(self):
return self.title
Вот мой сериализатор:
class PostSerializer(serializers.ModelSerializer):
"""
Serializer for Post class
"""
class Meta:
model = Post
fields = ('id', 'title', 'body', 'author', 'time_stamp')
Вот мое мнение:
class PostList(generics.ListCreateAPIView):
"""
Create a post or get a list of all posts within the database that are parent posts
API endpoints that use this view:
- /posts
- /createPost
"""
queryset = Post.objects.all()
serializer_class = PostSerializer
В сериализаторах:
Я думаю, что ваши поля должны начинаться и закрываться скобками [].
измените это:
fields = ('id', 'title', 'body', 'author', 'time_stamp')
К этому:
fields = ['id', 'title', 'body', 'author', 'time_stamp']
read_only_fields = ['id'] #also add this
И посмотрим, решит ли это
Проблема заключалась в связанных именах, которые я использовал. Я использовал атрибут related_name в родительском посте внешнего ключа. Это создавало некую обратную связь и вызывало ошибку. Избавление от атрибута related_name (и корректировка класса сериализатора с учетом этого) решило мою проблему!