简体   繁体   English

将上传文件保存到动态目录并获取存储在db中的路径

[英]save upload file to dynamic directory and get the path for store in db

I'm uploading a file and additionally some data like file's id and file's title to the server. 我正在将文件以及文件ID和文件标题之类的一些数据上传到服务器。 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 . 我具有下面的视图来处理请求,并且我想将文件保存到动态路径,例如upload/user_id/thefile.txt

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

view class: 查看类别:

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")

and serializer clas: 和序列化器分类:

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

and related model class: 和相关模型类:

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. 首先是用户故事,然后是模型层。

There are Products and a Product can have many ProductVideos . 产品 ,一个产品可以有许多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. 当您上传特定产品ProductVideo时 ,您要将其保存在包含作者 ID的目录中。

Therefore we specify a callable for the FileField which should dynamically find out the id of the Author : 因此,我们为FileField指定了一个可调用的对象,该对象应动态找出Authorid

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)

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. 保存Product_Video实例时,应将上传的文件存储在目录中,该目录应具有基于作者ID的动态创建的路径名。

Further I'd suggest you to follow established coding conventions: 此外,我建议您遵循既定的编码约定:

  • don't use snake_case for class names, especially don't mix it with capital letters. 不要将snake_case用作类名,尤其是不要将其与大写字母混合使用。 Use PascalCase , preferably singular nouns, for class names: ProductVideo 使用PascalCase (最好是单数名词)作为类名: 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. 如果你的模型类是ProductVideo ,保持这个名字在所有后续类: ProductVideoSerializer为模型串行和ProductVideoAPIView的通用视图。
  • use verbs for methods and standalone functions, get_user_directory or upload_to_custom_path is better than user_directory_path . 为方法和独立函数使用动词, get_user_directoryupload_to_custom_path优于user_directory_path
  • also avoid suffixing the foreign key fields with _id . 还应避免在外键字段后缀_id Use rather product instead of p_id . 使用宁可product而不是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 . Django将允许您通过调用product访问相关对象,并通过调用product_id获取对象的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. 使用名称p_id意味着您将通过调用看起来很奇怪和令人困惑的p_id_id来访问相关对象的ID。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM