【问题标题】:Django ImageField: full or relative path?Django ImageField:完整路径还是相对路径?
【发布时间】:2018-05-01 09:08:04
【问题描述】:

我尝试在我的Django项目中实现图片上传和处理。问题在于ImageField 的路径:

选项 1。

如果我使用相对于media 文件夹的路径,那么image.url 会很好地返回/media/img_name.jpg,并且Django 会正确处理图片。但是我不能使用image.width属性,会导致错误:

可疑文件操作
连接路径 (/user_test/3d55d527-109d-4a07-b0f6-4de0304d41f6.jpg) 位于基本路径组件之外 (/Users/Aivan/Desktop/Code/MyProject/media)


选项 2。

如果我使用完整路径,那么我可以轻松访问image.width 属性。但image.url 返回添加到media 文件夹的完整路径:http://127.0.0.1:8000/media/Users/Aivan/Desktop/Code/MyProject/media/user_test/8f3219cd-0333-4488-9d29-2c5506707afb.jpg


问题:

我应该怎么做才能正确访问image.urlimage.width

当然,我总是可以设置完整路径并在某些CharField中添加保存相对路径,或者添加自己的相对URL提取方法,但可能这样的解决方案不好。

我猜,那是因为 Django 使用媒体文件的相对路径,但是为了处理图像,它使用需要完整路径的 Pillow...也许这是一个错误?


我的图片课:

def path_user_photo(instance, filename):
    return 'user_{0}'.format(instance.account.user.username)

class Photo(models.Model):
    image = models.ImageField(upload_to=path_user_photo)
    name = models.CharField(max_length=32, unique=True)

而且是图片上传的静态方法:

    @classmethod
    def create_file(cls, fl, user, written_name, ext):
        folder = '/user_{0}'.format(user.username)
        realname = '/' + str(uuid.uuid4()) + '.' + ext
        write_path = settings.MEDIA_ROOT + folder
        # Create directory if it doesn't exist
        if not os.path.exists(write_path):
            os.makedirs(write_path)
        # Write data
        write_path = write_path + realname
        with open(write_path, 'wb+') as destination:
            for chunk in fl.chunks():
                destination.write(chunk)
        
        res = cls()
        # Option 1. Relative path
        res.image = folder + realname
        # Option 2. Full path
        res.image = write_path
        res.name = written_name
        res.save()
        return res

我从这样的视图中调用:

Photo.create_file(
    # the file
    request.FILES['file_img'],
    # current user
    request.user,
    # written name
    request.POST['written_name'],
    # real file extension
    file.name.split('.')[-1]
)

【问题讨论】:

    标签: python django django-models path imagefield


    【解决方案1】:

    我认为这里的问题是res.image = folder + realname 在技术上是一条绝对路径,因为folder 以硬编码的/ 开头。

    解决方法是使用os.path.join 将路径连接在一起,而不是显式使用/,然后在保存图像时使用相对路径应该是安全的。

    见下文 - 我已经评论了修改后的行。

    import os.path
    
    @classmethod
    def create_file(cls, fl, user, written_name, ext):
        folder = 'user_{0}'.format(user.username)  # Drop the leading slash
        realname = str(uuid.uuid4()) + '.' + ext  # Drop the leading slash
        write_path = os.path.join(settings.MEDIA_ROOT, folder)  # Join the paths
        # Create directory if it doesn't exist
        if not os.path.exists(write_path):
            os.makedirs(write_path)
        # Write data
        write_path = os.path.join(write_path, realname)  # Join the path and name
        with open(write_path, 'wb+') as destination:
            for chunk in fl.chunks():
                destination.write(chunk)
    
        res = cls()
        # Option 1. Relative path
        res.image = os.path.join(folder, realname)  # Join the folder and name
        res.name = written_name
        res.save()
        return res
    

    【讨论】:

    • 太棒了!谢谢。
    猜你喜欢
    • 2015-11-13
    • 2011-11-25
    • 1970-01-01
    • 2019-09-09
    • 2011-12-11
    • 1970-01-01
    • 2014-03-09
    • 2011-10-16
    • 2018-09-17
    相关资源
    最近更新 更多