[英]Django ImageField: full or relative path?
I try to implement pictures uploading and processing in my Django project. 我尝试在我的Django项目中实现图片上传和处理。 The problem is with path for
ImageField
: 问题在于
ImageField
路径:
If I use path relative to the media
folder, then image.url
nicely returns /media/img_name.jpg
, and Django handles the pictures correctly. 如果我使用相对于
media
文件夹的路径,那么image.url
很好地返回/media/img_name.jpg
,并且Django可以正确处理图片。 But I cannot use image.width
property, it leads to the error: 但是我不能使用
image.width
属性,它导致错误:
SuspiciousFileOperation
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)合并的路径(/user_test/3d55d527-109d-4a07-b0f6-4de0304d41f6.jpg)位于基本路径组件的外部(/ Users / Aivan / Desktop / Code / MyProject / media)
If I use full path, then I can easily access the image.width
property. 如果使用完整路径,则可以轻松访问
image.width
属性。 But image.url
returns full path added to the media
folder: http://127.0.0.1:8000/media/Users/Aivan/Desktop/Code/MyProject/media/user_test/8f3219cd-0333-4488-9d29-2c5506707afb.jpg
但是
image.url
返回添加到media
文件夹的完整路径: http://127.0.0.1:8000/media/Users/Aivan/Desktop/Code/MyProject/media/user_test/8f3219cd-0333-4488-9d29-2c5506707afb.jpg
: http://127.0.0.1:8000/media/Users/Aivan/Desktop/Code/MyProject/media/user_test/8f3219cd-0333-4488-9d29-2c5506707afb.jpg
: image.url
What should I do in order to properly access both image.url
and image.width
? 我应该怎么才能正确地访问既做
image.url
和image.width
?
Of course, I can always set up full path and add save the relative path in some CharField
, or add an own method for relative URL extracting, but probably such solutions are bad. 当然,我总是可以设置完整路径,并将相对路径保存在某些
CharField
,或者添加自己的方法来提取相对URL,但是这种解决方案可能是不好的。
I guess, that's because Django uses relative paths for media files, but to deal with images it uses Pillow which needs full paths... Maybe it's a bug? 我猜这是因为Django使用媒体文件的相对路径,但是要处理图像,它使用需要完整路径的Pillow ...也许是一个错误?
My picture 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)
And it's static method for images uploading: 这是图片上传的静态方法:
@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
Which I call from a View like this: 我从这样的视图调用:
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]
)
The issue here I think is that res.image = folder + realname
is technically an absolute path because folder
begins with a hardcoded /
. 我认为这里的问题是
res.image = folder + realname
从技术上讲是绝对路径,因为folder
以硬编码/
开头。
The way to resolve, is to join the paths together using os.path.join
rather than using a /
explicitly, and then you should be safe to use the relative path when saving the image. 解决的方法是使用
os.path.join
而不是使用/
显式将路径连接在一起,然后在保存图像时应该相对使用相对路径。
See below - I have commented the modified lines. 参见下文-我评论了修改后的行。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.