带post方法的Django Nested Serilizer

时间:2019-06-23 12:04:58

标签: django django-rest-framework

我已成功使用django类创建了序列化器类,并且它仅对GET方法非常有效,但我也需要POST方法才能工作。

当前Post方法不起作用...

这是我的序列化器类:

from rest_framework import serializers
from . models import Author, Article, Category, Organization


class OrganizationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Organization
        fields = '__all__'


class AuthorSerializer(serializers.ModelSerializer):
    organization = OrganizationSerializer()
    class Meta:
        model = Author
        fields = '__all__'


class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__'


class ArticleSerializer(serializers.ModelSerializer):
    author = AuthorSerializer()
    category = CategorySerializer()

    class Meta:
        model =  Article
        fields = '__all__'

以上代码段仅适用于GET方法,不适用于POST方法...

我需要它应该适用于post方法。


如果您不了解上述序列化工具,则可以查看我的模型:

from django.db import models
import uuid

class Organization(models.Model):
    organization_name = models.CharField(max_length=50)
    contact = models.CharField(max_length=12, unique=True)

    def __str__(self):
        return self.organization_name

class Author(models.Model):
    name = models.CharField(max_length=40)
    detail = models.TextField()
    organization = models.ForeignKey(Organization, on_delete=models.DO_NOTHING)

    def __str__(self):
        return self.name

class Category(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Article(models.Model):
    alias = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='author')
    title = models.CharField(max_length=200)
    body = models.TextField()
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

任何人都可以告诉我,使我的端点适用于post方法吗?

这是我看到的错误,来自终端:

 File "/home/pyking/.local/lib/python3.6/site-packages/rest_framework/serializers.py", line 823, in raise_errors_on_nested_writes
    class_name=serializer.__class__.__name__
AssertionError: The `.create()` method does not support writable nested fields by default.
Write an explicit `.create()` method for serializer `blog2.serializers.ArticleSerializer`, or set `read_only=True` on nested serializer fields.
[23/Jun/2019 12:22:49] "POST /blog2/api/v1/article HTTP/1.1" 500 122369
Not Found: /favicon.ico
[23/Jun/2019 12:22:49] "GET /favicon.ico HTTP/1.1" 404 2186

1 个答案:

答案 0 :(得分:0)

正如错误stacktrace所说,您应该在序列化器类中实现create()。在DRF中处理嵌套序列化是很常见的情况。

此问题的一种解决方案是为读取写入数据定义不同的序列化器。这意味着一个用于获取资源的串行器和一个用于创建/更新资源的串行器。


首先,定义用于标准书写操作( POST / PUT / PATCH )的ModelSerializer:< / p>

class ArticleSerializer(serializers.ModelSerializer):
    # Important: Remove your nested serializers declaration here!

    class Meta:
        model = Article
        fields = '__all__'

然后扩展此序列化程序,并使用嵌套序列化( GET )覆盖要获取的字段:

class ArticleReadSerializer(ArticleSerializer):
     author = AuthorSerializer(read_only=True)
     category = CategorySerializer(read_only=True)

     # Note the read_only=True parameters in both serializers
     # And the class you inherit from

然后通过覆盖get_serializer_classAPIView / ViewSet指定要用于不同操作的序列化器:

class ArticleViewSet(viewsets.ModelViewSet):
     queryset = Article.objects.all()

     def get_serializer_class(self):
         if self.request.method in ['GET']:
             return ArticleReadSerializer

         return ArticleSerializer

这是ModelViewSet的示例,但是DRF的每个通用视图类中都存在此方法,因此它是可转移的机制。


现在,您可以通过使用主键指定相关模型来创建文章:

{
    "title": "...",
    "author": 1,
    "category": 1
}

注意:您还应该在organization = OrganizationSerializer(read_only=True)中设置AuthorSerializer,因为您已经创建了具有相关组织的作者,并且在创建文章时不要创建新的组织条目