Django ImageField:完整路径还是相对路径?
Django ImageField: full or relative path?
我尝试在我的Django项目中实现图片上传和处理。问题出在 ImageField
:
的路径上
选项 1。
如果我使用相对于 media
文件夹的路径,那么 image.url
很好 returns /media/img_name.jpg
,Django 会正确处理图片。但是我不能使用image.width
属性,它会导致错误:
SuspiciousFileOperation
The joined path (/user_test/3d55d527-109d-4a07-b0f6-4de0304d41f6.jpg) is located outside of the base path component (/Users/Aivan/Desktop/Code/MyProject/media)
选项 2。
如果我使用完整路径,那么我可以轻松访问 image.width
属性。但是 image.url
returns 添加到 media
文件夹的完整路径:http://127.0.0.1:8000/media/Users/Aivan/Desktop/Code/MyProject/media/user_test/8f3219cd-0333-4488-9d29-2c5506707afb.jpg
问题:
我应该怎么做才能正确访问 image.url
和 image.width
?
当然,我总是可以设置完整路径并在某些 CharField
中添加保存相对路径,或者添加自己的相对 URL 提取方法,但可能这样的解决方案不好。
我想,那是因为 Django 对媒体文件使用相对路径,但是为了处理图像,它使用需要完整路径的 Pillow...也许这是一个错误?
我的照片class:
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]
)
我认为这里的问题是 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
我尝试在我的Django项目中实现图片上传和处理。问题出在 ImageField
:
选项 1。
如果我使用相对于 media
文件夹的路径,那么 image.url
很好 returns /media/img_name.jpg
,Django 会正确处理图片。但是我不能使用image.width
属性,它会导致错误:
SuspiciousFileOperation
The joined path (/user_test/3d55d527-109d-4a07-b0f6-4de0304d41f6.jpg) is located outside of the base path component (/Users/Aivan/Desktop/Code/MyProject/media)
选项 2。
如果我使用完整路径,那么我可以轻松访问 image.width
属性。但是 image.url
returns 添加到 media
文件夹的完整路径:http://127.0.0.1:8000/media/Users/Aivan/Desktop/Code/MyProject/media/user_test/8f3219cd-0333-4488-9d29-2c5506707afb.jpg
问题:
我应该怎么做才能正确访问 image.url
和 image.width
?
当然,我总是可以设置完整路径并在某些 CharField
中添加保存相对路径,或者添加自己的相对 URL 提取方法,但可能这样的解决方案不好。
我想,那是因为 Django 对媒体文件使用相对路径,但是为了处理图像,它使用需要完整路径的 Pillow...也许这是一个错误?
我的照片class:
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]
)
我认为这里的问题是 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