串行工作在Django的外壳,但在视图中失败

问题描述:

我有那些机型:串行工作在Django的外壳,但在视图中失败

class ServiceCategory(models.Model): 
    class Meta: 
     db_table = 'service_categories' 

    category = models.CharField(max_length=24) 

    def __str__(self): 
     return self.category 


class Service(models.Model): 
    class Meta: 
     db_table = 'services' 

    service = models.CharField(max_length=24) 
    category = models.ForeignKey('ServiceCategory') 

    def __str__(self): 
     return self.service 

而且他们的串行:

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

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

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

此设置后,I quickly bumped into a problem创建通过其关联ServiceSerializerService :即使我只需要其id,我也必须通过完整的ServiceCategory。上面的ServiceCategory看起来很简单,但事实并非如此,因为为了简洁起见,我省略了许多其他字段。

所以传递ServiceCategory的完整属性为窗体上的前端显得非常低效的给我,让我尝试另一种方法:

class UpsertServiceSerializer(serializers.ModelSerializer): 
    category = serializers.IntegerField() # not ServiceCategorySerializer() 

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

    def create(self, data): 
     c = ServiceCategory.objects.get(pk=data['category']) 
     return Service.objects.create(service=data['service'], category=c) 

我的目的是使用UpsertServiceSerializer用于创建和更新,以ServiceSerializer现在被用于读取。 UpsertServiceSerializer在Django shell中没有问题 - 创建过程中不得不通过ServiceCategoryid而不是其所有属性,并且新的Service对象确实被添加到数据库 - 但是当我通过POST请求通过邮差,我得到这个错误:

TypeError at /services 
int() argument must be a string, a bytes-like object or a number, not 'ServiceCategory' 

于是,我的UpsertServiceSerializer一个新版本:

class UpsertServiceSerializer(serializers.Serializer): 
    service = serializers.CharField() 
    category = serializers.IntegerField() 

    def create(self, data): 
     c = ServiceCategory.objects.get(pk=data['category']) 
     return Service.objects.create(service=data['service'], category=c) 

注意,在新版本中,我的子类,而不是serializers.Serializerserializers.ModelSerializer,里面没有class Meta。这个版本没有什么不同,它也通过了Django shell,但是在视图中使用相同的TypeError失败。

这里的观点:

@api_view(['GET', 'POST']) 
def services(request): 
    if request.method == 'GET': 
     services = Service.objects.all() 
     serializer = ServiceSerializer(services, many=True) 
     return Response(serializer.data) 

    elif request.method == 'POST': 
     serializer = UpsertServiceSerializer(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) 

那我做错了吗?

理解序列化程序中的相关字段是如何工作的常见问题。 ForeignKey默认使用PrimaryKeyRelatedField,所以即使您不需要重写create方法,也不需要IntegerField

class UpsertServiceSerializer(serializers.ModelSerializer): 

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

传递pk类别将工作。如果您需要category模型的特殊布局而不是普通的pk,您可以编写自己的to_representation方法。

class UpsertServiceSerializer(serializers.ModelSerializer): 
    ... 
    def to_representation(self, instance): 
     representation = super(UpsertServiceSerializer, self).to_representation(instance) 
     representation['category'] = ServiceCategorySerializer(instance.category).data 
     return representation 
+0

谢谢。很有价值的信息。接受和upvoted。 – Duos

+0

@Duos您的欢迎 –