使用 ID 进行 POST 并获取嵌套对象在 ModelSerializer 中不能同时在 django 中工作

nck*_*nck 0 python django post django-serializer django-rest-framework

我已经花了几天时间在类似问题中研究这个问题,但无法找到解决方案。这应该很简单,我有一个模型:

model.py

class Item(models.Model):
    """Class to represent an item..."""

    label = models.TextField(null=True)
    name = models.TextField()

    category = models.ForeignKey(   "Category", on_delete=models.SET_NULL,
                                    null=True, default=DEFAULT_CATEGORY_ID)

class Category(models.Model):
    """Class to represent the category of an Item. Like plants, bikes..."""
    name = models.TextField()

    description = models.TextField(null=True)
Run Code Online (Sandbox Code Playgroud)

view.py

class ItemViewset(viewsets.ModelViewSet): # pylint: disable=too-many-ancestors
    """API Endpoint to return the list of items"""
    queryset = Item.objects.all()
    serializer_class = ItemSerializer
Run Code Online (Sandbox Code Playgroud)

serializer.py

class ItemSerializer(serializers.ModelSerializer):
    """Serializer for Item."""

    category = CategorySerializer(read_only=True)

    class Meta: # pylint: disable=too-few-public-methods
        """Class to represent metadata of the object."""
        model = Item
        fields = [  'id', 'label', 'name', 'category']   
        read_only_fields = ['id']
        
        # def to_representation(self, instance):
        #     ret = super().to_representation(instance)
        #     ret['category'] = CategorySerializer(instance.category).data
        #     return ret
        def create(self, request):
            # Look up objects by arbitrary attributes.
            # You can check here if your students are participating
            # the classes and have taken the subjects they sign up for.
            category = get_object_or_404(Category(), id=request.data.get('category'))

            serializer = self.get_serializer(data=request.data)
            serializer.is_valid(raise_exception=True)
            serializer.save(category=category)
            headers = self.get_success_headers(serializer.data)

            return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Run Code Online (Sandbox Code Playgroud)

如果我对该行category = CategorySerializer(read_only=True)进行了注释,则嵌套 get 将不起作用,例如对于对象的卷曲。我将得到该结构的唯一 ID。如果我像示例中那样取消注释,我会得到正确的响应:

{
  "id": 60,
  "label": null,
  "name": "Delete me",
  "category": {
    "id": 1,
    "name": "IT"
  }
}
Run Code Online (Sandbox Code Playgroud)

但是这样带有 id 的帖子将不起作用,类别将被设置为空。

我怎样才能让两者同时工作?

更新:这是我想做的帖子:

{
    "label": "00000003",
    "name": "Delete me",
    "category": 1,
}
Run Code Online (Sandbox Code Playgroud)

VJ *_*gar 6

您可以重写to_represention序列化器的方法

class ItemSerializer(serializers.ModelSerializer):
    """Serializer for Item."""

    class Meta: # pylint: disable=too-few-public-methods
        """Class to represent metadata of the object."""
        model = Item
        fields = [  'id', 'label', 'name', 'category']   
        read_only_fields = ['id']
        
    def to_representation(self, instance):
            data = super().to_representation(instance)
            data["category"] = CategorySerializer(instance.category).data
            return data
Run Code Online (Sandbox Code Playgroud)