Получили `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 (и корректировка класса сериализатора с учетом этого) решило мою проблему!

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