Django Rest Framework - 在不提供外键值的情况下创建

时间:2015-02-23 00:08:58

标签: django django-rest-framework

我正在使用Django-Rest-Framework构建我的第一个API,我对验证过程有点困惑。希望这是一个简单的答案,但我无法从6部分的介绍教程中找到答案......

我有一个模特:

class XYZMeta(models.Model):
    id = models.AutoField(primary_key=True)
    xyz_id = models.ForeignKey(XYZ)
    user_id = models.ForeignKey(User)
    field_name = models.CharField(blank=True, max_length=50)
    value = models.TextField(blank=True)

和一个序列化器:

class XYZMetaSerializer(serializers.ModelSerializer):
    class Meta:
        model = XYZMeta
        fields = ('id', 'xyz_id', 'user_id', 'field_name', 'value')

观点:

class XYZMetaViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows xyz metadata to be viewed or edited.
    """
    queryset = XYZMeta.objects.all()
    serializer_class = serializers.XYZMetaSerializer

    def perform_create(self, serializer):
        serializer.save(user_id=self.request.user)

当我发送POST来创建一个新对象时,它运行良好并使用授权用户的ID而不是我提供的任何值。例如:

> curl -X POST -H "Content-Type:application/json" -d '{"xyz_id":"12345",**"user_id":2**,"field_name":"abc","value":"abc comment"}' -u admin:admin http://mysite/xyzmeta/
{"id":2,"dealer_id":12345,**"user_id":1**,"field_name":"abc","value":"abc comment","create_date":"2015-02-22T23:32:27.928991Z"}

但是,如果我完全关闭user_id(因为无论如何都没关系),我收到一个错误,表明该字段是必需的:

> curl -X POST -H "Content-Type:application/json" -d '{"xyz_id":"12345","field_name":"abc","value":"abc comment"}' -u admin:admin http://mysite/xyzmeta/
{"user_id":["This field is required."]}

如何指定我希望在创建过程中以编程方式设置user_id外键字段,而不必提供虚拟值?

3 个答案:

答案 0 :(得分:5)

一种方法:将user_id字段设为非必需

class XYZMetaSerializer(serializers.ModelSerializer):
    class Meta:
        model = XYZMeta
        fields = ('id', 'xyz_id', 'user_id', 'field_name', 'value')
        extra_kwargs = {
            'user_id': {'required': False}
        }

另一种方法:在get_serializer(data=request.data)方法调用之前更改request.data

class XYZMetaViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows xyz metadata to be viewed or edited.
    """
    queryset = XYZMeta.objects.all()
    serializer_class = serializers.XYZMetaSerializer

    def create(self, request, *args, **kwargs):
        request.data['user_id'] = request.user.id
        return super(self.__class__, self).create(request, *args, **kwargs)

答案 1 :(得分:1)

required=False字段只有user_id怎么样?

我还没有对此进行过测试......但这样的事情应该有效!

class XYZMetaSerializer(serializers.ModelSerializer):
    user_id = serializers.RelatedField(source='user_id', required=False)

    class Meta:
        [...]

答案 2 :(得分:0)

由于user_id在请求中没用,您只需从序列化程序中跳过它,稍后在ViewSet的perform_create方法中添加它:

class XYZMetaViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows xyz metadata to be viewed or edited.
    """
    queryset = XYZMeta.objects.all()
    serializer_class = serializers.XYZMetaSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)