如何在DRF中进行序列化验证/保存之前添加其他数据?

时间:2015-02-22 00:16:32

标签: python django http django-rest-framework

所以我有这个课程:

class MyClass(models.Model):    
    name = models.CharField(max_length=100)    
    created_time = models.DateTimeField(auto_now_add = True)
    modified_time = models.DateTimeField(auto_now = True)

然后其他类代表MyClass的相关照片:

class MyPhoto(models.Model):
    myclass = models.ForeignKey(MyClass, unique=False, related_name='photos')
    photo = models.ImageField(upload_to='photos',blank=False)

我想创建一个端点,它将处理照片上传(内容类型将是多部分,关联的myclass的id将在url中传递),所以这就是我所拥有的:

urls.py:

router = routers.DefaultRouter()    
router.register(r'photos/(?P<myclass_id>\d+)',PhotoViewSet)

视图集:

class PhotoViewSet(CreateModelMixin,
                    viewsets.GenericViewSet):
    queryset = MyPhoto.objects.all()
    serializer_class = serializers.PhotoAlterSerializer
    parser_classes = (parsers.MultiPartParser,)

    def create(self, request, *args,**kwargs):
        myclass = MyClass.objects.get(pk=kwargs['myclass_id'])
        serializer = serializers.PhotoAlterSerializer(data=request.data,context={'request': request})
        if serializer.is_valid(raise_exception=True):
            photo=serializer.save(myclass=myclass)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

和序列化器:

class PhotoAlterSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyPhoto
        fields = ('myclass','photo')

如您所见,我将其他属性myclass添加到serializer.save(myclass = myclass)方法。

但是,如果我上传照片并在网址中正确传递myclass ID,我会此字段是必需的。错误。如果我将myclass的正确超链接添加到带有照片的上传多部分表单中,请求将通过验证,然后表单中的myclass将被我从url id获得的myclass替换。

如何才能完成这项工作,如果我只将照片发布到网址http://blabla/api/photos/2,则此照片的实例和pk = 2的myclass将保存到数据库?

1 个答案:

答案 0 :(得分:1)

这是因为您在序列化程序的fields meta中指定了myclass。这使得DRF需要并将其作为POST数据的一部分进行验证。您自己设置的任何字段都不应该是序列化程序字段的一部分。因此,您只需要从myclass中删除Meta.fields即可。

class PhotoAlterSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = MyPhoto
        fields = ('photo', )