I'm working on a project that uses both django registration and django profiles. I have a form that allows users edit/create a profile, which includes uploading a photo. Everything works fine in the following situations: a profile is created or edited and no image has ever been uploaded; a profile is edited/created and an image is uploaded; once an image is uploaded, the profile can be edited as long as the image that was previously uploaded is either changed or removed... The place I run into issues is if there is an existing profile image, and the user tries to edit his/her profile without making any changes to the current image (i.e. removing or replacing it). In that situation, I get the error 'ImageFieldFile' object has no attribute 'content_type'. Any ideas as to why this is happening. I have tried variations of other answers found in stack overflow, but couldn't get any of them to work as they were stated. What I currently have is a variation of one of those with changes I made:
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
Thanks for any help or advice.
Here is the full traceback:
Traceback:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "C:\Python27\lib\site-packages\django\contrib\auth\decorators.py" in _wrapped_view
20. return view_func(request, *args, **kwargs)
File "C:\Python27\lib\site-packages\profiles\views.py" in edit_profile
197. if form.is_valid():
File "C:\Python27\lib\site-packages\django\forms\forms.py" in is_valid
124. return self.is_bound and not bool(self.errors)
File "C:\Python27\lib\site-packages\django\forms\forms.py" in _get_errors
115. self.full_clean()
File "C:\Python27\lib\site-packages\django\forms\forms.py" in full_clean
270. self._clean_fields()
File "C:\Python27\lib\site-packages\django\forms\forms.py" in _clean_fields
290. value = getattr(self, 'clean_%s' % name)()
File "C:\Documents and Settings\user\projects\xlftv\lftv\userprofiles\forms.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'
When a file is uploaded, based on the file size it will be an instance of InMemoryUploadedFile
class or a TemporaryUploadedFile
class which are subclasses of UploadedFile
class.
And image model fields are saved as django.db.models.fields.files.ImageFieldFile
objects.
So when the form is submitted again without modifying the image field, that field will be an instance of django.db.models.fields.files.ImageFieldFile
rather the uploaded file django.core.files.uploadedfile.UploadedFile
instance. So check for the type of the form field before accessing the content_type
attribute.
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