将上传文件保存到动态目录并获取存储在db中的路径 [英] save upload file to dynamic directory and get the path for store in db

查看:64
本文介绍了将上传文件保存到动态目录并获取存储在db中的路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将文件以及其他数据(例如文件的ID和文件的标题)上传到服务器.我有下面的视图来处理请求,我想将文件保存到动态路径,例如 upload/user_id/thefile.txt .

I'm uploading a file and additionally some data like file's id and file's title to the server. I have the view below to handle the request and I want to save the file to a dynamic path like upload/user_id/thefile.txt.

使用代码,下面的文件将直接保存在文件夹中并直接上传到文件夹中,并且我的 product_video 表还将创建具有相关ID和标题的新记录.
现在我不知道如何将文件保存在动态生成的目录中,例如: upload/user_id/thefile.txt 以及如何将生成的路径保存到数据库表列video_path ?

With code the below the file will be saved in and upload folder directly and also my product_video table will create a new record with the related id and the title.
Now I don't have any idea how can I save the file in a dynamically generated directory like: upload/user_id/thefile.txt and how to save the produced path to the database table column video_path?

视图类:

class FileView(APIView):
    parser_classes = (MultiPartParser, FormParser)

    def post(self, request, *args, **kwargs):
        if request.method == 'POST' and request.FILES['file']:
            myfile = request.FILES['file']
            serilizer = VideoSerializer(data=request.data)
            if serilizer.is_valid():
                serilizer.save()

            fs = FileSystemStorage()
            fs.save(myfile.name, myfile)

            return Response("ok")

        return Response("bad")

和序列化器分类:

class VideoSerializer(ModelSerializer):
    class Meta:
        model = Product_Video
        fields = [
            'p_id',
            'title',
            'video_length',
            'is_free',
        ]

和相关模型类:

def user_directory_path(instance, filename):
    return 'user_{0}/{1}'.format(instance.user.id, filename)


class Product_Video(models.Model):
    p_id = models.ForeignKey(Product, on_delete=models.CASCADE, to_field='product_id', related_name='product_video')
    title = models.CharField(max_length=120, null=True,blank=True)
    video_path = models.FileField(null=True, upload_to=user_directory_path,storage=FileSystemStorage)
    video_length = models.CharField(max_length=20, null=True, blank=True)
    is_free = models.BooleanField(default=False)

推荐答案

您将购物车放到了马的前面.从头开始,首先要做的是.首先是用户故事,然后是模型层.

You put the cart before the horse. Start from the beginning, first things first. And the first thing is the user story, then the model layer.

个产品,一个产品可以有许多 ProductVideos .产品具有作者(作者可以具有许多产品).上载特定产品 ProductVideo 时,您要将其保存在包含 Author ID的目录中.

There are Products and a Product can have many ProductVideos. A Product has an Author (the Author can have many Products). When you upload a ProductVideo for a particular Product, you want to save it in a directory which contains the Author ID.

因此,我们为 FileField 指定了一个可调用对象,该对象应动态找出 Author id :

Therefore we specify a callable for the FileField which should dynamically find out the id of the Author:

def user_directory_path(instance, filename):
    # get the id of the author
    # first get the Product, then get its author's id
    user_id = str(instance.p_id.author.id)
    # little bit cosmetics
    # should the filename be in uppercase
    filename = filename.lower()
    return 'user_{0}/{1}'.format(user_id, filename)

保存 Product_Video 的实例时,上载的文件应存储在目录中,该目录具有基于作者ID的动态创建的路径名.

When saving an instance of Product_Video the uploaded file should be stored in a directory with a dynamically created pathname based on the author's ID.

进一步,我建议您遵循既定的编码约定:

Further I'd suggest you to follow established coding conventions:

  • 请勿将 snake_case 用于类名,尤其是请勿将其与大写字母混合使用.使用 PascalCase (最好是单数名词)作为类名称: ProductVideo
  • 如果您的模型类是 ProductVideo ,请在所有后续类中保留该名称:用于模型序列化器的 ProductVideoSerializer 和用于通用视图的 ProductVideoAPIView
  • 将动词用于方法和独立功能, get_user_directory upload_to_custom_path 优于 user_directory_path .
  • 还应避免在外键字段后缀 _id .使用 product 代替 p_id .Django允许您通过调用 product 访问相关对象,并通过调用 product_id 获取对象的ID.使用名称 p_id 意味着您将通过调用看起来很奇怪和令人困惑的 p_id_id 来访问相关对象的ID.
  • don't use snake_case for class names, especially don't mix it with capital letters. Use PascalCase, preferably singular nouns, for class names: ProductVideo
  • if your model class is ProductVideo, keep that name in all subsequent classes: ProductVideoSerializer for the model serializer and ProductVideoAPIView for the generic view.
  • use verbs for methods and standalone functions, get_user_directory or upload_to_custom_path is better than user_directory_path.
  • also avoid suffixing the foreign key fields with _id. Use rather product instead of p_id. Django will allow you to access the related object by calling product and get the id of the object by calling product_id. Using the name p_id means you'll access the id of the related object by calling p_id_id which looks very weird and confusing.

这篇关于将上传文件保存到动态目录并获取存储在db中的路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆