Django Rest Framework - 在服务器上下载文件

3
我将翻译这段关于IT技术的内容。该API允许客户端发布文件链接,我希望能下载该文件并将其存储在我模型中的FileField中。以下是我的代码:

序列化程序:

from rest_framework import serializers
from django.core.files import File
from rest_framework.serializers import ValidationError

class MySerializer(serializers.ModelSerializer):

    class Meta:
        model = MyModel
        fields = ('url')

    def to_internal_value(self, data):
        validated = dict()

        url = data.get('url')

        # do url validation here

        # download the file to local disk

        validated['file'] = File(open('path/to/downloaded/file'))
        validated['url'] = url

        return validated 

模型:

from django.db import models


class MyModel(models.Model):
    url = models.CharField(max_length=255)
    file = models.FileField(upload_to='files/')

对于视图,我使用了通用的ListCreateAPIView
主要存在两个问题。首先,目前的实现方式会导致文件被复制两次。因为我先将其下载到磁盘上的某个位置,然后当FileField存储到数据库中时,它会再次复制文件到files/文件夹中。有没有什么方法可以避免这种情况?其次,如何异步下载文件,同时在下载完成后能够添加FileField属性到模型中?
1个回答

4
更好的做法是创建您自己的序列化器字段,以达到相同的效果。
from django.core.validators import URLValidator
from django.core.files.base import ContentFile

from rest_framework import serializers

from urllib.request import urlretrieve

class FileUrlField(serializers.FileField):
    def to_internal_value(self, data):
        try:
            URLValidator()(data)
        except ValidationError as e:
            raise ValidationError('Invalid Url')

        # download the contents from the URL
        file, http_message = urlretrieve(data)
        file = File(open(file, 'rb'))
        return super(FileUrlField, self).to_internal_value(ContentFile(file.read(), name=file.name))

然后在您的序列化器中使用它

class MySerializer(serializers.ModelSerializer):
    file = FileUrlField()
    class Meta:
        model = MyModel

然而,我没有测试过它,但应该可以工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接