DRF:嵌套JSON数据的ModelSerializer

时间:2017-05-03 03:44:01

标签: python django django-rest-framework

我正在尝试将现有的DJANGO应用转换为基于API的应用。我已经在Angular中完成了前端并且现在在后端工作。来自客户端的数据将采用json格式,如下所示

  {
    "title": "wue",
    "author": "asd",
    "addons": {
                "header":"head",
                "footer":"foot"
              }
  }

我写了 model.py

class BookDetails(models.Model):
    title= models.CharField(max_length=10)
    author= models.CharField(max_length=10)
    addons= models.ForeignKey(Addons, null=True)
class Addons(models.Model):
    header= models.CharField(max_length=10)
    footer= models.CharField(max_length=10)

serializer.py

class AddonsSerializer(serializers.ModelSerializer):

    class Meta:
        model = Addons
        fields = ('header', 'footer')
        depth = 2


class BookDetailsSerializer(serializers.ModelSerializer):
    addons = AddonsSerializer(many=False, read_only=True)
    class Meta:
        model = BookDetails
        depth = 2
        fields = ('title', 'author','addons')

views.py

class BookDetailsList(APIView):

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

    def post(self, request):
        serializer = BookDetailsSerializer(data=request.data)
        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)

我的 urls.py

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^bookdetails/', views.BookDetailsList.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

现在,当我使用邮递员发送数据时, addons 字段未填充,它获得 null 值。

我曾尝试编写自定义创建,但我认为某处我搞砸了,但无法弄清楚在哪里。

def create(self, validated_data):
    tracks_data = validated_data.pop('addons')
    addons = BookDetails.objects.create(**validated_data)
    Addons.objects.create(addons=addons, **tracks_data)
    return addons

它给我一个错误

  

/ bookdetails /'addons'

中的KeyError

我尝试过分配 depth = 2 ,但它无效。我做错了什么?

编辑1(已删除read_only = True)仍然没有运气:

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 19, in post
    serializer.save()
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/rest_framework/serializers.py", line 214, in save
    self.instance = self.create(validated_data)
  File "/Users/argo/Django/pagination-backend/backend/publishbook/serializers.py", line 26, in create
    Addons.objects.create(addons=addons, **tracks_data)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/db/models/manager.py", line 122, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/db/models/query.py", line 399, in create
    obj = self.model(**kwargs)
  File "/Users/argo/Django/pagination-backend/env/lib/python3.5/site-packages/django/db/models/base.py", line 443, in __init__
    raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
TypeError: 'addons' is an invalid keyword argument for this function

3 个答案:

答案 0 :(得分:1)

您正在将图书详细信息添加为插件模型本身的插件,请尝试更新您的代码,

    def create(self, validated_data):
        tracks_data = validated_data.pop('addons')
        addons = Addons.objects.create(**tracks_data)
        book = BookDetails.objects.create(addons=addons, **validated_data)
        return book 

答案 1 :(得分:0)

您在read_only=True的{​​{1}}字段中指定了addons。这可以防止将json字典的插件部分传递给您的BookDetailsSerializer方法。这就是你尝试create时出现KeyError的原因(我猜,如果你粘贴了堆栈跟踪,而不仅仅是错误,它会有所帮助)。

除此之外,我不确定你的pop方法 - 也许你可以重新格式化它,以便变量名更有意义。您仍然拥有DRF示例中的create,并且您已经命名了tracks_data创建'插件'的产品 - 这实际上没有意义并且难以阅读。此外,您是否可以指定BookDetails方法所属的序列化程序,因为通过查看它很难说明。

注意:一般来说,给Django模型名称提供单数形式是常规的,所以你的是BookDetail和Addon。

问题编辑后更新:

现在,您在此行中遇到错误:create。 该错误告诉您Addons.objects.create(addons=addons, **tracks_data)不是addons模型上的有效字段。我认为这样做只会Addons

答案 2 :(得分:0)

我认为你需要纠正它的创建方法。 你有一个带有ForeignKey到Addon模型的Bookdetails模型。 从我的角度来看,代码应该是这样的, (你应该删除read_only = True,显然)

def create(self, validated_data):
    tracks_data = validated_data.pop('addons')
    book_details = BookDetails.objects.create(**validated_data)
    addons = Addons.objects.create(**tracks_data)
    book_details.addons = addons
    book_details.save()
    return book_details

希望你得到你想要的东西。

说真的,您需要重新考虑一下您的命名约定。