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

时间:2018-02-25 14:36:58

标签: python django django-rest-framework

我正在上传一个文件,还有一些数据,比如文件的id和文件的标题到服务器。我有以下视图来处理请求,我想将文件保存到动态路径,如upload/user_id/thefile.txt

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

和序列化器clas:

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)

1 个答案:

答案 0 :(得分:1)

你把车放在马前。从头开始,先做好第一件事。首先是用户故事,然后是模型层。

产品产品可以包含多个 ProductVideos 产品作者作者可以有多个产品)。当您为特定产品上传 ProductVideo 时,您希望将其保存在包含作者 ID的目录中。

因此,我们为id指定了一个可调用的,可以动态找出作者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

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

此外,我建议您遵循既定的编码惯例:

  • 不要将PascalCase用于类名,尤其不要将其与大写字母混合使用。使用ProductVideo,最好是单数名词,用于类名:ProductVideo
  • 如果您的模型类为ProductVideoSerializer,请在所有后续类中保留该名称:模型序列化程序为ProductVideoAPIView,通用视图为get_user_directory
  • 将动词用于方法和独立函数,upload_to_custom_pathuser_directory_path优于_id
  • 也避免使用product为外键字段添加后缀。请使用p_id代替product。 Django允许您通过调用product_id来访问相关对象,并通过调用p_id来获取对象的ID。使用名称p_id_id意味着您将通过调用{{1}}来访问相关对象的ID,这看起来非常奇怪且令人困惑。