无法与DRF

时间:2016-11-23 16:54:15

标签: django django-rest-framework

这是我第一次使用DRF。

我的模特:

class ServiceCategory(models.Model):
    category = models.CharField(max_length=24)

class Service(models.Model):
    service = models.CharField(max_length=24)
    category = models.ForeignKey('ServiceCategory')

他们的序列化器:

class ServiceCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = ServiceCategory
        fields = ('id', 'category')

class ServiceSerializer(serializers.ModelSerializer):
    category = ServiceCategorySerializer()

    class Meta:
        model = Service
        fields = ('service', 'category')

    def create(self, data):
        return Service.objects.create(**data)

观点:

elif request.method == 'POST':
    serializer = ServiceSerializer(data=request.data)

    print(serializer.initial_data) # To debug the contents of the request

    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)

最初,在我将嵌套类别添加到ServiceSerializer之前,我没有创建新服务的问题。 print(serializer.initial_data)输出<QueryDict: {'category': ['1'], 'service': ['EC2']}>显然我已经为请求提供了类别,但我收到"category" : ["This field is required"]错误。

所以我认为问题可能出在ServiceSerializer中的create(self, data)方法,但是我无法指出它究竟出了什么问题。

我错过了什么?

更新

ServiceSerializer中没有ServiceCategorySerializer,视图为:

elif request.method == 'POST':
    serializer = ServiceSerializer(data=request.data)

    print(serializer.initial_data) # for debugging

    if serializer.is_valid():
        print(serializer.data) # for debugging

serializer.initial_data返回<QueryDict: {'category': ['1'], 'service': ['EC2']}>serializer.data返回{'service': 'EC2', 'category': 1},因此我假设serializer.data的内容将传递给ServiceSerializer的create()方法。它本身就可以工作,但当我在其中包含ServiceCategorySerializer时,POST不会通过,我会得到同样恼人的"category" : ["This field is required"]

我现在已经坚持了6个多小时。发生了什么???

3 个答案:

答案 0 :(得分:2)

我有一个完整的工作示例 - 您想要实现的目标 - 仅使用我在此主题中找到的信息:

型号:

from __future__ import unicode_literals

from django.db import models


class ServiceCategory(models.Model):
    category = models.CharField(max_length=24)


class Service(models.Model):
    service = models.CharField(max_length=24)
    category = models.ForeignKey('ServiceCategory')

串行器:

from rest_framework import serializers

from nestedd.models import ServiceCategory, Service


class ServiceCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = ServiceCategory
        fields = ('id', 'category')


class ServiceSerializer(serializers.ModelSerializer):
    category = ServiceCategorySerializer()

    class Meta:
        model = Service
        fields = ('service', 'category')

    def create(self, validated_data):
        category_data = validated_data.pop('category')
        # 'created' will be True if no existing category matches
        category, created = ServiceCategory.objects.get_or_create(**category_data)
        return Service.objects.create(category=category, **validated_data)

查看:

# Create your views here.
from rest_framework import viewsets

from nestedd.models import Service
from nestedd.serializers import ServiceSerializer


class ServiceViewSet(viewsets.ModelViewSet):
    queryset = Service.objects.all()
    serializer_class = ServiceSerializer

网址:

from rest_framework.routers import DefaultRouter

from nestedd.views import ServiceViewSet

router = DefaultRouter()
router.register(r'nested', ServiceViewSet, base_name='service')

urlpatterns = router.urls

app urls:

url(r'^api/v2/', include('nestedd.urls')),

这就是我邮差的样子:

Postman request

问题 - 发布数据格式

可能你做错了POST查询 - 如果你想使用嵌套的序列化器,就像这样:

category = ServiceCategorySerializer()

在其他一些序列化程序中,您必须知道第一个字段名称附加到父序列化程序,例如:

{
     "service_name": "test",
     "category": ...
}

应该在类别字段中放置什么?嗯 - 一个对象,因为你告诉这个字段是另一个序列化程序,如果是对象那么:

{
    "service_name": "test",
    "category": {
        "category": "some_category"
    }
}

在此对象中,您可以指定由内部序列化程序描述的模型的字段,因此基本上,当您仅传递“id” - &gt;时很明显,由于模型ServiceCategory上的类别字段是必需的,因此无法创建ServiceCategory。

另一个注意:EXISITING VS.没有明确的类别

处理现有/不存在的类别时会遇到问题; 基本上你应该在ServiceCategory上使类别字段唯一,并在ServiceViewSet上发布 - 检查类别是否存在(如果是,请将其分配给Service对象 - 如果不存在 - 创建一个类别) - 在这种情况下,您不需要传递类别每次都是id。当id - 不存在时处理它。

答案 1 :(得分:1)

在发布服务时,category字段必须包含PK,即整数。 category中的serializer.initial_data字段包含带字符串的列表。

BTW1:当您的模型需要字符串(service)时,您的CharField字段也会有一个列表。这可能也是一个问题。

BTW2:在您的情况下无需覆盖序列化程序的create

答案 2 :(得分:1)

正如the docs中所述,您应该以稍微不同的方式实现create()方法,如果类别尚未存在,则首先保存该类别,然后将其传递给{{ 1}}函数,像这样(未经测试的):

Service.objects.create()