如何在 DRF 中的序列化器 validation/save 之前添加额外的数据?
How to add additional data before serializer validation/save in DRF?
所以我有这个 class:
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)
然后其他 class 表示与 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')
如您所见,我正在向 serializer.save(myclass=myclass) 方法添加附加属性 myclass。
但是,如果我上传照片并在 url 中正确传递我的 class id,我会收到 This field is required. 错误。如果我将 myclass 的正确超链接添加到上传的带照片的多部分表单中,请求将通过验证,然后表单中的 myclass 将被替换为我的 class 我从 url ID.
我怎样才能做到这一点,所以如果我 post 只给 url http://blabla/api/photos/2 这张照片的实例和我的 class 的 pk=2 照片将保存到数据库?
这是因为您在序列化程序的字段元中指定了 myclass
。这使得 DRF 需要并验证它作为 POST 数据的一部分。您自己设置的任何字段都不应该是序列化程序字段的一部分。因此,要使其正常工作,您只需从 Meta.fields
中删除 myclass
。
class PhotoAlterSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = MyPhoto
fields = ('photo', )
所以我有这个 class:
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)
然后其他 class 表示与 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')
如您所见,我正在向 serializer.save(myclass=myclass) 方法添加附加属性 myclass。
但是,如果我上传照片并在 url 中正确传递我的 class id,我会收到 This field is required. 错误。如果我将 myclass 的正确超链接添加到上传的带照片的多部分表单中,请求将通过验证,然后表单中的 myclass 将被替换为我的 class 我从 url ID.
我怎样才能做到这一点,所以如果我 post 只给 url http://blabla/api/photos/2 这张照片的实例和我的 class 的 pk=2 照片将保存到数据库?
这是因为您在序列化程序的字段元中指定了 myclass
。这使得 DRF 需要并验证它作为 POST 数据的一部分。您自己设置的任何字段都不应该是序列化程序字段的一部分。因此,要使其正常工作,您只需从 Meta.fields
中删除 myclass
。
class PhotoAlterSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = MyPhoto
fields = ('photo', )