'ImageFieldFile'对象没有属性'content_type'只有在图片已经上传后才会更改或删除



我正在做一个同时使用django注册和django配置文件的项目。我有一个允许用户编辑/创建个人资料的表单,其中包括上传照片。在以下情况下一切都很好:创建或编辑了个人资料,但从未上传过任何图像;编辑/创建简档并且上传图像;一旦上传了图像,只要之前上传的图像被更改或删除,就可以编辑配置文件。。。我遇到问题的地方是,是否存在现有的配置文件图像,并且用户试图在不对当前图像进行任何更改(即删除或替换它)的情况下编辑他/她的配置文件。在这种情况下,我得到错误"ImageFieldFile"对象没有属性"content_type"。任何关于为什么会发生这种情况的想法。我尝试过在堆栈溢出中找到的其他答案的变体,但无法使其中任何一个按规定工作。我目前拥有的是我所做的改变之一的变体:

class UserProfileForm(ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
try:
self.fields['email'].initial = self.instance.user.email
except User.DoesNotExist:
pass
email = forms.EmailField(label="Primary email", help_text='')
class Meta:
model = UserAccountProfile
exclude = ('user', 'broadcaster', 'type')
widgets = {
...
}

def save(self, *args, **kwargs):
u = self.instance.user
u.email = self.cleaned_data['email']
u.save()
profile = super(UserProfileForm, self).save(*args,**kwargs)
return profile
def clean_avatar(self):
avatar = self.cleaned_data['avatar']            
if avatar:
w, h = get_image_dimensions(avatar)
max_width = max_height = 500
if w >= max_width or h >= max_height:
raise forms.ValidationError(u'Please use an image that is %s x %s pixels or less.' % (max_width, max_height))
main, sub = avatar.content_type.split('/')
if not (main == 'image' and sub in ['jpeg', 'pjpeg', 'gif', 'png']):
raise forms.ValidationError(u'Please use a JPEG, GIF or PNG image.')
if len(avatar) > (50 * 1024):
raise forms.ValidationError(u'Avatar file size may not exceed 50k.')
else:
pass
return avatar

谢谢你的帮助或建议。

以下是完整的回溯:

Traceback:
File "C:Python27libsite-packagesdjangocorehandlersbase.py" in get_response
111.                         response = callback(request, *callback_args, **callback_kwargs)
File "C:Python27libsite-packagesdjangocontribauthdecorators.py" in _wrapped_view
20.                 return view_func(request, *args, **kwargs)
File "C:Python27libsite-packagesprofilesviews.py" in edit_profile
197.         if form.is_valid():
File "C:Python27libsite-packagesdjangoformsforms.py" in is_valid
124.         return self.is_bound and not bool(self.errors)
File "C:Python27libsite-packagesdjangoformsforms.py" in _get_errors
115.             self.full_clean()
File "C:Python27libsite-packagesdjangoformsforms.py" in full_clean
270.         self._clean_fields()
File "C:Python27libsite-packagesdjangoformsforms.py" in _clean_fields
290.                     value = getattr(self, 'clean_%s' % name)()
File "C:Documents and Settingsuserprojectsxlftvlftvuserprofilesforms.py" in clean_avatar
146.          main, sub = avatar.content_type.split('/')
Exception Type: AttributeError at /instructor_profiles/edit
Exception Value: 'ImageFieldFile' object has no attribute 'content_type'

上传文件时,根据文件大小,它将是InMemoryUploadedFile类或TemporaryUploadedFile类的实例,它们是UploadedFile类的子类。

并且图像模型字段被保存为django.db.models.fields.files.ImageFieldFile对象。

因此,当表单在不修改图像字段的情况下再次提交时,该字段将是django.db.models.fields.files.ImageFieldFile的实例,而不是上传的文件django.core.files.uploadedfile.UploadedFile的实例。因此,在访问content_type属性之前,请检查表单字段的类型。

from django.core.files.uploadedfile import UploadedFile
from django.db.models.fields.files import ImageFieldFile
def clean_avatar(self):
avatar = self.cleaned_data['avatar']            
if avatar and isinstance(avatar, UploadedFile):
w, h = get_image_dimensions(avatar)
max_width = max_height = 500
if w >= max_width or h >= max_height:
raise forms.ValidationError(u'Please use an image that is %s x %s pixels or less.' % (max_width, max_height))
main, sub = avatar.content_type.split('/')
if not (main == 'image' and sub in ['jpeg', 'pjpeg', 'gif', 'png']):
raise forms.ValidationError(u'Please use a JPEG, GIF or PNG image.')
if len(avatar) > (50 * 1024):
raise forms.ValidationError(u'Avatar file size may not exceed 50k.')
elif avatar and isinstance(avatar, ImageFieldFile):
# something
pass
else:
pass
return avatar

因此,如果查看回溯中的最后一点,您会发现错误来自这一行main, sub = avatar.content_type.split('/'),它似乎来自clean_avatar方法。看起来你正在努力确保它是一个图像。。。我不得不想象还有另一种方法可以做到这一点。

看起来最坏的情况是,您应该能够解析avatar.name来检查文件扩展名(请参阅https://docs.djangoproject.com/en/dev/ref/files/file/#django.core.files.File)

顺便说一句,为一个实例获取content_type的方法是ContentType.get_for_model(avatar)

最新更新