Django-Rest-Framework:如何构建异步目录/文件夹上传和批量文件上传

问题描述

所以我和我的队友一直在努力解决我们构建的同步文件上传 CRUD 端点的效率问题,现在我们需要使用 celery 或 asyncio(任何欢迎使用其他方法)。

我目前的工作

我的模型:

class CompanyFileUpload(SoftDeletionModel):

    name = models.CharField(
        max_length=100,null=True,unique=False,blank=True,default="file name"
    )

    user = models.ForeignKey(
        User,on_delete=models.CASCADE,related_name='company_file_uploads'
    )

    timestamp = models.DateTimeField(
        auto_now_add=True
    )

    data_file = models.FileField(
        upload_to=Utils.create_company_file_upload_path,validators=[validate_file]
    )

    comment = models.CharField(
        max_length=400,unique=False
    )

    file_size = models.CharField(
        max_length=100,default="null"
    )

    def save(self,*args,**kwargs):
        size = self.data_file.size
        power = 2**10
        n = 0
        power_labels = {0: '',1: 'Kilo',2: 'Mega',3: 'Giga',4: 'Tera'}
        while size > power:
            size /= power
            n += 1

        self.file_size = f"{size:.2f} {power_labels[n]}bytes"
        self.name = self.data_file.name

        super(CompanyFileUpload,self).save(*args,**kwargs)

    def __str__(self):
        return f'{self.data_file},{self.user}'


@receiver(post_save,sender=CompanyFileUpload)
def email_report_details_handler(sender,instance,**kwargs):

    ctx = {
        "firstname": instance.user.firstname,"timestamp": instance.timestamp,"fullname_and_email": f"{instance.user.firstname} {instance.user.othernames}","subject": "File Upload","recepient": instance.user.email,"email": instance.user.email,"url": instance.data_file.url,"comment": instance.comment
    }

    Utils.send_report_email(ctx)

我的序列化程序:

class CompanyFileUploadSerializer(serializers.ModelSerializer):
    timestamp = serializers.DateTimeField(
        format="%d-%m-%Y %H:%M:%S",read_only=True)

    class Meta:
        model = CompanyFileUpload
        fields = ["id","name","user","data_file","comment","file_size","timestamp"]

        extra_kwargs = {
            'file_size': {'read_only': True},'name': {'read_only': True}
        }

我的观点:

class CreateCompanyFileUploadAPI(generics.CreateAPIView):
    """
    API endpoint for creating a Company file_upload

    Sample Response:

{
    "id": 3,"user": 4,"title": "This is an awesome file","data_file": "https://{ url_to_some_storage :) }","comment": "Well it should be awesome...","timestamp": "2021-06-09T19:33:04.835268Z"
}
    """

    serializer_class = CompanyFileUploadSerializer


class ListCompanyFileUploadsAPI(generics.ListAPIView):
    """
    API endpoint for viewing all Company file_uploads

    Sample Response:
[
    {
        "id": 3,"timestamp": "2021-06-09T19:33:04.835268Z"
    }
]
    """
    serializer_class = CompanyFileUploadSerializer
    lookup_field = 'pk'
    filter_backends = (SearchFilter,OrderingFilter,DjangoFilterBackend,)
    search_fields = ["title","user__firstname"]

    def get_queryset(self):
        user = self.request.user

        return CompanyFileUpload.objects.filter(user=user).order_by("-timestamp")


class RetrieveCompanyFileUploadDetailsAPI(generics.RetrieveAPIView):
    """
    API endpoint for reading a Company single file_upload details

    Sample Response:
{
    "id": 3,"data_file": "https:{ url_to_some_storage :) }","timestamp": "2021-06-09T19:33:04.835268Z"
}
    """
    serializer_class = CompanyFileUploadSerializer
    lookup_field = 'pk'

    def get_queryset(self):
        user = self.request.user

        return CompanyFileUpload.objects.filter(user=user)


class DeleteCompanyUploadedFileAPI(generics.DestroyAPIView):
    """
    API endpoint to delete already uploaded Company files from local/blob storage
    """
    serializer_class = CompanyFileUploadSerializer

    queryset = CompanyFileUpload.objects
    lookup_field = "pk"

    def get_queryset(self):
        user = self.request.user
        return CompanyFileUpload.objects.filter(user=user)


class UpdateCompanyUploadedFileAPI(generics.UpdateAPIView):
    """
    API endpoint for updating an uploaded company file details/content
{
    "id": 2,"user": 2,"title": "lnlnl","comment": "Changed","file_size": "86.25 Kilobytes","timestamp": "2021-06-21T22:15:20.342044Z"
}
    """
    serializer_class = CompanyFileUploadSerializer
    queryset = CompanyFileUpload.objects
    lookup_field = "pk"

    def get_queryset(self):
        user = self.request.usclass CreateCompanyFileUploadAPI(generics.CreateAPIView):
    """
    API endpoint for creating a Company file_upload

    Sample Response:

{
    "id": 3,"timestamp": "2021-06-21T22:15:20.342044Z"
}
    """
    serializer_class = CompanyFileUploadSerializer
    queryset = CompanyFileUpload.objects
    lookup_field = "pk"

    def get_queryset(self):
        user = self.request.user

        return CompanyFileUpload.objects.filter(user=user)er

        return CompanyFileUpload.objects.filter(user=user)

电子邮件方式:

class Utils:

    @staticmethod
    def send_report_email(ctx):
        """utility service to handle report upload details email """

        message = get_template('mail.html').render(ctx)
        msg = EmailMessage(
            ctx["subject"],message,os.environ.get("EMAIL_HOST_USER"),[ctx["recepient"]],)
        msg.content_subtype = "html"  # Main content is now text/html
        msg.send()

我已经使用 docker compose 容器化了 django-app 和 nginx 服务器。使用天蓝色灯泡容器存储处理存储。

现在,问题是,如何将当前的 FileUpload CRUD 端点转换为批量文件上传(或目录上传)CRUD(至少对于创建端点)? 我尝试解决我在本文中找到的批量序列化程序; Efficient Bulk Create with Django Rest Framework,但尽管我发现将它用于其他端点的 CRUD 取得了一些成功,但到目前为止,我在为 fileUplaod 创建端点实施此方法时不幸失败,如果有人可以向我提供任何建议或可行的方法,我将不胜感激解决方案。

此 Rest-API 适用于企业系统软件,并且非常需要/需要效率。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)