Django中的文件上传和处理
我已经连续工作了三天,快要崩溃了。希望有人能一步一步地解释一下这个过程到底发生了什么,以及每一步的数据是什么样子的。
我有一个模型,里面有一个ImageField()。我根据这个模型创建了一个表单。然后我把这个表单传递给一个模板,模板再把填写好的表单数据传给一个视图。接着,我把请求中的文件数据(request.FILES)绑定到模型/表单的一个实例上,然后保存它。
我想做的是把这个上传的文件用作用户的头像,并且希望在保存到模型之前先调整一下它的大小。
在我验证完数据后,我把请求中的文件数据(request.FILES['file'])传入一个函数。在这个函数里,PIL(一个处理图像的库)打开了这些数据。每次打开都没问题,PIL能够直接从内存文件中读取这些数据。然而,我就是无法让PIL输出编辑后的数据,符合Django在ImageField()中所需要的格式。我基本上想要的是把这个上传的数据调整大小、重命名,然后通过ImageField()保存,让Django后续处理。
视图代码:
if request.method == "POST":
user_form = EditUserProfile(request.POST, instance=User.objects.get(id=request.user.id))
siteprofile_form = EditSiteProfile(request.POST, request.FILES, instance=SiteProfile.objects.get(user=request.user))
if user_form.is_valid() and siteprofile_form.is_valid():
user_form.save()
temp_siteprofile = siteprofile_form.save(commit=False)
temp_siteprofile.profile_image = process_image_string(request.FILES['profile_image'], (100, 100))
temp_siteprofile.save()
return user_profile(request, request.user.username)
函数代码:
def process_image_string(f, size):
f_image = Image.open(f)
f_image = f_image.resize(size)
output = StringIO()
f_image.save(output, "JPEG")
return output
请注意,这个函数在过去三天里可能改了100次,这个版本在我看来是最接近成功的。
1 个回答
1
你可以试试 django-stdimage
这个工具。它是 ImageField
的一个扩展,可以帮你自动调整图片大小,下面是一个示例代码:
class MyClass(models.Model):
image1 = StdImageField(upload_to='path/to/img') # works as ImageField
image2 = StdImageField(upload_to='path/to/img', blank=True) # can be deleted through admin
image3 = StdImageField(upload_to='path/to/img', size=(640, 480)) # resizes image to maximum size to fit a 640x480 area
image4 = StdImageField(upload_to='path/to/img', size=(640, 480, True)) # resizes image to 640x480 croping if necessary
image_all = StdImageField(upload_to='path/to/img', blank=True, size=(640, 480), thumbnail_size=(100, 100, True)) # all previous features in one declaration
使用这个工具,你可以直接保存你的模型表单 EditUserProfile
,而不需要自己去处理图片。缺点是这个库特别依赖于 PIL 这个库。