Django Rest Framework不使用简单的嵌套序列化程序

时间:2017-05-04 03:29:08

标签: python json django django-rest-framework

我正在将我现有的应用转换为api。我的文件结构如下:

models.py

class BookDetail(models.Model):
    title= models.CharField(max_length=10, default='title')
    author= models.CharField(max_length=10)
    series= models.CharField(max_length=10)
    edition= models.CharField(max_length=10)
    description= models.CharField(max_length=10)
    keywords= models.CharField(max_length=10)
    reading_age= models.CharField(max_length=10)
    genre= models.CharField(max_length=10)
    publishing_rights= models.CharField(max_length=10)

    def __str__(self):
        return self.title


class Addon(models.Model):
    header= models.CharField(max_length=10)
    footer= models.CharField(max_length=10, default='1')
    additional_features = models.ForeignKey(BookDetail, related_name='additional_features',
                                            on_delete=models.CASCADE, null=True)

    def __str__(self):
        return self.header

views.py

class BookDetailsList(APIView):

    def get(self, request):
        stocks = BookDetail.objects.all()
        serializers = BookDetailsSerializer(stocks, many=True)
        return Response(serializers.data)

    def post(self, request):
        serializer = BookDetailsSerializer(data=request.data)
        print(serializer.is_valid())
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializer.py

class AddonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Addon
        fields = ('header', 'footer')


class BookDetailsSerializer(serializers.ModelSerializer):
    additional_features = AddonSerializer(many=True)
    class Meta:
        model = BookDetail
        fields = ('title', 'author','series', 'edition',
                  'description', 'keywords', 'reading_age',
                  'genre', 'publishing_rights','additional_features')
        # fields = '__all__'

    def create(self, validated_data):
        additional_feature = validated_data.pop('additional_features')
        book_detail = BookDetail.objects.create(**validated_data)
        for a in additional_feature:
            Addon.objects.create(additional_features=book_detail, **a)
        # Addon.objects.create(additional_features=book_detail, **additional_feature)
        return book_detail

我的输入数据是JSON格式

{
    "title": "lolwa",
    "author": "asd",
    "series": "string",
    "edition": "a",
    "description": "as",
    "keywords": "sd",
    "reading_age": "aasd",
    "genre": "adasda",
    "publishing_rights": "aadasd",
    "additional_features": [{"header":"head",
                             "footer":"foot"}]
  }

这很好用。但我真正想要的不是将我的 additional_features 作为我目前正在做的列表传递,我想像这样传递它。

    "additional_features": {"header":"head",
                             "footer":"foot"}

但是当我试图像这样传递时,我的代码会抛出错误。我在 serializer.py

中进行了以下更改
class BookDetailsSerializer(serializers.ModelSerializer):
    additional_features = AddonSerializer(many=False)
    # additional_features = AddonSerializer(many=True)
    class Meta:
        model = BookDetail
        fields = ('title', 'author','series', 'edition',
                  'description', 'keywords', 'reading_age',
                  'genre', 'publishing_rights','additional_features')
        # fields = '__all__'

    def create(self, validated_data):
        additional_feature = validated_data.pop('additional_features')
        book_detail = BookDetail.objects.create(**validated_data)
        # for a in additional_feature:
        #     Addon.objects.create(additional_features=book_detail, **a)
        Addon.objects.create(additional_features=book_detail, **additional_feature)
        return book_detail

使多个=错误删除for循环。由于它们两个,** a和** additional_feature都是

  

OrderedDict([(' header',' head'),(' footer',' foot')])

我没有看到它失败的原因。

这是错误的堆栈跟踪

Internal Server Error: /bookdetails/
Traceback (most recent call last):
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/fields.py", line 444, in get_attribute
    return get_attribute(instance, self.source_attrs)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/fields.py", line 103, in get_attribute
    instance = getattr(instance, attr)
AttributeError: 'RelatedManager' object has no attribute 'header'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/core/handlers/base.py", line 149, in get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/core/handlers/base.py", line 147, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/views.py", line 483, in dispatch
    response = self.handle_exception(exc)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/views.py", line 443, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/views.py", line 480, in dispatch
    response = handler(request, *args, **kwargs)
  File "/Users/argo/Django/pagination-backend/backend/publishbook/views.py", line 21, in post
    return Response(serializer.data, status=status.HTTP_201_CREATED)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/serializers.py", line 531, in data
    ret = super(Serializer, self).data
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/serializers.py", line 262, in data
    self._data = self.to_representation(self.instance)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/serializers.py", line 500, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/serializers.py", line 487, in to_representation
    attribute = field.get_attribute(instance)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/fields.py", line 463, in get_attribute
    raise type(exc)(msg)
AttributeError: Got AttributeError when attempting to get a value for field `header` on serializer `AddonSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `RelatedManager` instance.
Original exception text was: 'RelatedManager' object has no attribute 'header'.

1 个答案:

答案 0 :(得分:1)

从模型的结构来看,BookDetail对象可以有多个Addon实例,因为Addon模型有BookDetail的外键。

如果您想为特定的BookDetail添加多个插件,则无法在不使用列表的情况下更新插件实例。

但是,如果不是这样,那么我建议使用OneToOne关系而不是外键。 实际上,使用OneToOne字段非常难看,而只需将字段添加到父模型(BookDetail)中,如果没有,则可以默认为null。