Django Rest Framework 上传文件到方法
我一直在尝试用DRF上传文件,但到现在为止都没有成功。
我能顺利地通过ModelViewSet
和(FormParser, MultiPartParser,)
上传文件,但我真的需要在像这个链接http://localhost:8000/api/v1/women/{pk}/upload_avatar/
的地方使用它。在这里,我想先通过ID筛选出某个女性,然后上传她的头像(头像是一个指向多媒体模型的外键)。我尝试使用嵌套资源库,但也没有成功。
到目前为止,我在我的模型视图集中有:
class WomenNativePassportViewSet(viewsets.ModelViewSet):
queryset = Women.objects.all()
serializer_class = WomenNativePassportSerializer
authentication_classes = (NoAuthentication,)
permission_classes = (AllowAny,)
parser_classes = (FormParser, MultiPartParser,)
@detail_route(
methods=['post', 'put', 'patch', 'get'], permission_classes=[AllowAny],
authentication_classes=[NoAuthentication], serializer_class=MultimediaSerializer,
parser_classes=(FormParser, MultiPartParser,)
)
def upload_avatar(self, request, pk=None, *args, **kwargs):
if 'POST' in request._method or 'PATCH' in request._method:
# Write code to save the file??
else:
multimedia = Multimedia.objects.filter(user_profiles_avatares__pk=pk)
page = self.paginate_queryset(multimedia)
serializer = self.get_pagination_serializer(page)
return Response(serializer.data)
我的模型:
class Women(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
avatar = models.ForeignKey(
'core.Multimedia', blank=True, null=True,
related_name='user_profiles_avatares'
)
class Multimedia(models.Model):
file = models.FileField(upload_to=upload_to, null=True, blank=True)
thumbnail = models.FileField(upload_to=upload_to, null=True, blank=True)
基本上,我想知道我现在走的这条路是否正确,如果是的话,我该如何正确地将上传的文件保存到模型中呢?
2 个回答
0
任何上传的文件都会在 request.FILES
中找到,这个地方就像一个字典,文件的键是你上传时使用的字段名。一旦你拿到了文件,处理它的方法和处理其他在Django中上传的文件差不多。
如果可以的话,我建议使用一个额外的序列化器来包装 Multimedia
模型,这样就可以通过Django REST框架自动进行图片的验证和保存。这里有一个 ImageField
,它会通过 Pillow
自动验证图片,你可以在序列化器中使用它。
7
这是我为了解决这个问题而写的一些代码。虽然Kevin Brown的回答可能有效,但我觉得我的代码方法稍微“简单”一些:
@detail_route(
methods=['post', 'put', 'patch', 'get'], permission_classes=[AllowAny],
authentication_classes=[NoAuthentication], serializer_class=MultimediaSerializer,
parser_classes=(FormParser, MultiPartParser,)
)
def upload_avatar(self, request, pk=None):
# Because we are using nested resources this was the only way i found to
# upload a file. Maybe there is a better way
if request.method in ['PATCH', 'POST']:
avatar = request.FILES.get('avatar')
if not avatar:
return Response(status=404)
try:
woman = WomenNativePassport.objects.get(pk=pk)
except WomenNativePassport.DoesNotExist:
return Response(status=404)
else:
request.FILES['thumbnail'] = request.FILES['avatar']
serializer = AvatarSerializer(
data=request.DATA, files=request.FILES
)
if serializer.is_valid():
woman.avatar.thumbnail.save(str(avatar), File(avatar))
return Response(status=204)
else:
return Response(status=404)
else:
multimedia = Multimedia.objects.filter(user_profiles_avatares__pk=pk)
page = self.paginate_queryset(multimedia)
serializer = self.get_pagination_serializer(page)
return Response(serializer.data)
# serializer
class AvatarSerializer(serializers.Serializer):
thumbnail = serializers.ImageField()