尝试删除图像或在 Django 中创建新用户时 ImageField 上的 ValueError
ValueError on ImageField when trying to delete image or creating new user in Django
我已经在我的 Django 模型上放置了一个 ImageField,它可以使用预先存在的配置文件(图片上传),但我无法从管理面板中删除图片,也无法创建新的图片用户。
抛出的错误是:
ValueError at /admin/custom_user/customuser/1/
The 'avatar' attribute has no file associated with it.
Request Method: POST
Request URL: http://localhost:8000/admin/custom_user/customuser/1/
Django Version: 1.8
Exception Type: ValueError
Exception Value:
The 'avatar' attribute has no file associated with it.
Exception Location: /home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/db/models/fields/files.py in _require_file, line 46
Python Executable: /home/stefano/projects/blog-project/blogprojectenv/bin/python
Python Version: 2.7.6
Python Path:
['/home/stefano/projects/blog-project',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7/plat-x86_64-linux-gnu',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7/lib-tk',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7/lib-old',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7/lib-dynload',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages']
Server time: Thu, 24 Mar 2016 13:12:38 +0000
这是模型
class CustomUser(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(max_length=254, blank=True)
second_name = models.CharField(max_length=254, blank=True)
email = models.EmailField(blank=True, unique=True)
date_joined = models.DateTimeField(_('date joined'), default=datetime.now())
avatar = models.ImageField('profile picture', upload_to='images/avatars/', null=True, blank=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'second_name']
objects = CustomUserManager()
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def save(self, *args, **kwargs):
pil_image_obj = Image.open(self.avatar)
new_image = resizeimage.resize_width(pil_image_obj, 300)
new_image_io = BytesIO()
new_image.save(new_image_io, format='JPEG')
temp_name = self.avatar.name
self.avatar.delete(save=False)
self.avatar.save(
temp_name,
content=ContentFile(new_image_io.getvalue()),
save=False
)
super(CustomUser, self).save(*args, **kwargs)
我尝试在模型上设置 null=True 和 blank=True,但错误仍然存在。我试图在 forms.py
中的“init”方法上设置 required=False
class CustomUserChangeForm(forms.ModelForm):
email = forms.EmailField(label='', required=True, widget = forms.TextInput(
attrs = {
'placeholder': 'E-Mail',
'class': 'form-control'
}
))
first_name = forms.CharField(label='', required=True, widget=forms.TextInput(
attrs = {
'placeholder': 'First name',
'class': 'form-control'
}
))
second_name = forms.CharField(label='', required=True, widget=forms.TextInput(
attrs = {
'placeholder': 'Second name',
'class': 'form-control'
}
))
avatar = forms.ImageField(label='', required=False, widget=forms.FileInput(
attrs = {
'class': 'form-control',
'label': 'Profile pic'
}
))
class Meta:
model = CustomUser
fields = ('email', 'first_name', 'second_name', 'avatar')
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(CustomUserChangeForm, self).__init__(*args, **kwargs)
self.fields['avatar'].required = False
def clean_email_address(self):
email = self.cleaned_data.get('email')
if self.user and self.user.email == email:
return email
if CustomUser.objects.filter(email=email).count():
raise forms.ValidationError(u'That email address already exists.')
return email
def save(self, commit=True):
user = super(CustomUserChangeForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
还在。
可以做什么?
编辑:这是完整的回溯
Environment:
Request Method: POST
Request URL: http://localhost:8000/admin/custom_user/customuser/1/
Django Version: 1.8
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'custom_user',
'django_markdown',
'parsley')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Traceback:
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
616. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
110. response = view_func(request, *args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
233. return view(request, *args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in change_view
1519. return self.changeform_view(request, object_id, form_url, extra_context)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
34. return bound_func(*args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
110. response = view_func(request, *args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
30. return func.__get__(self, type(self))(*args2, **kwargs2)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in inner
145. return func(*args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in changeform_view
1467. self.save_model(request, new_object, form, not add)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in save_model
1078. obj.save()
File "/home/stefano/projects/blog-project/custom_user/models.py" in save
66. pil_image_obj = Image.open(self.avatar)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/PIL/Image.py" in open
2261. fp.seek(0)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/core/files/utils.py" in <lambda>
20. seek = property(lambda self: self.file.seek)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/db/models/fields/files.py" in _get_file
49. self._require_file()
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/db/models/fields/files.py" in _require_file
46. raise ValueError("The '%s' attribute has no file associated with it." % self.field.name)
Exception Type: ValueError at /admin/custom_user/customuser/1/
Exception Value: The 'avatar' attribute has no file associated with it.
我认为在打开头像图像之前询问是否 self.avatar
的条件可以工作,因为在我看来,如果没有头像就没有理由删除它。像这样:
def save(self, *args, **kwargs):
if self.avatar:
pil_image_obj = Image.open(self.avatar)
new_image = resizeimage.resize_width(pil_image_obj, 300)
new_image_io = BytesIO()
new_image.save(new_image_io, format='JPEG')
temp_name = self.avatar.name
self.avatar.delete(save=False)
self.avatar.save(
temp_name,
content=ContentFile(new_image_io.getvalue()),
save=False
)
super(CustomUser, self).save(*args, **kwargs)
我希望这可以帮助您找到解决方案。谢谢:)
创建实例时,磁盘上没有存储头像文件。所以你尝试打开不存在的文件。
我看到你想在这里删除更新后的旧文件?
所以你不需要覆盖 save
方法。您应该做的是使用 pre_save
、post_save
和 post_delete
方法。
在 pre_save
你存储当前头像,在 post_save
更新后你应该检查新实例的文件路径与旧实例。如果不同则按 os.remove
删除
在 post_delete
上删除文件。
我已经在我的 Django 模型上放置了一个 ImageField,它可以使用预先存在的配置文件(图片上传),但我无法从管理面板中删除图片,也无法创建新的图片用户。
抛出的错误是:
ValueError at /admin/custom_user/customuser/1/
The 'avatar' attribute has no file associated with it.
Request Method: POST
Request URL: http://localhost:8000/admin/custom_user/customuser/1/
Django Version: 1.8
Exception Type: ValueError
Exception Value: The 'avatar' attribute has no file associated with it.
Exception Location: /home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/db/models/fields/files.py in _require_file, line 46
Python Executable: /home/stefano/projects/blog-project/blogprojectenv/bin/python
Python Version: 2.7.6
Python Path:
['/home/stefano/projects/blog-project',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7/plat-x86_64-linux-gnu',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7/lib-tk',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7/lib-old',
'/home/stefano/projects/blog-project/blogprojectenv/lib/python2.7/lib-dynload',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages'] Server time: Thu, 24 Mar 2016 13:12:38 +0000
这是模型
class CustomUser(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(max_length=254, blank=True)
second_name = models.CharField(max_length=254, blank=True)
email = models.EmailField(blank=True, unique=True)
date_joined = models.DateTimeField(_('date joined'), default=datetime.now())
avatar = models.ImageField('profile picture', upload_to='images/avatars/', null=True, blank=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'second_name']
objects = CustomUserManager()
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def save(self, *args, **kwargs):
pil_image_obj = Image.open(self.avatar)
new_image = resizeimage.resize_width(pil_image_obj, 300)
new_image_io = BytesIO()
new_image.save(new_image_io, format='JPEG')
temp_name = self.avatar.name
self.avatar.delete(save=False)
self.avatar.save(
temp_name,
content=ContentFile(new_image_io.getvalue()),
save=False
)
super(CustomUser, self).save(*args, **kwargs)
我尝试在模型上设置 null=True 和 blank=True,但错误仍然存在。我试图在 forms.py
中的“init”方法上设置 required=Falseclass CustomUserChangeForm(forms.ModelForm):
email = forms.EmailField(label='', required=True, widget = forms.TextInput(
attrs = {
'placeholder': 'E-Mail',
'class': 'form-control'
}
))
first_name = forms.CharField(label='', required=True, widget=forms.TextInput(
attrs = {
'placeholder': 'First name',
'class': 'form-control'
}
))
second_name = forms.CharField(label='', required=True, widget=forms.TextInput(
attrs = {
'placeholder': 'Second name',
'class': 'form-control'
}
))
avatar = forms.ImageField(label='', required=False, widget=forms.FileInput(
attrs = {
'class': 'form-control',
'label': 'Profile pic'
}
))
class Meta:
model = CustomUser
fields = ('email', 'first_name', 'second_name', 'avatar')
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(CustomUserChangeForm, self).__init__(*args, **kwargs)
self.fields['avatar'].required = False
def clean_email_address(self):
email = self.cleaned_data.get('email')
if self.user and self.user.email == email:
return email
if CustomUser.objects.filter(email=email).count():
raise forms.ValidationError(u'That email address already exists.')
return email
def save(self, commit=True):
user = super(CustomUserChangeForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
还在。
可以做什么?
编辑:这是完整的回溯
Environment:
Request Method: POST
Request URL: http://localhost:8000/admin/custom_user/customuser/1/
Django Version: 1.8
Python Version: 2.7.6
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'custom_user',
'django_markdown',
'parsley')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Traceback:
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in wrapper
616. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
110. response = view_func(request, *args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/sites.py" in inner
233. return view(request, *args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in change_view
1519. return self.changeform_view(request, object_id, form_url, extra_context)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
34. return bound_func(*args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
110. response = view_func(request, *args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
30. return func.__get__(self, type(self))(*args2, **kwargs2)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/utils/decorators.py" in inner
145. return func(*args, **kwargs)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in changeform_view
1467. self.save_model(request, new_object, form, not add)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/contrib/admin/options.py" in save_model
1078. obj.save()
File "/home/stefano/projects/blog-project/custom_user/models.py" in save
66. pil_image_obj = Image.open(self.avatar)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/PIL/Image.py" in open
2261. fp.seek(0)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/core/files/utils.py" in <lambda>
20. seek = property(lambda self: self.file.seek)
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/db/models/fields/files.py" in _get_file
49. self._require_file()
File "/home/stefano/projects/blog-project/blogprojectenv/local/lib/python2.7/site-packages/django/db/models/fields/files.py" in _require_file
46. raise ValueError("The '%s' attribute has no file associated with it." % self.field.name)
Exception Type: ValueError at /admin/custom_user/customuser/1/
Exception Value: The 'avatar' attribute has no file associated with it.
我认为在打开头像图像之前询问是否 self.avatar
的条件可以工作,因为在我看来,如果没有头像就没有理由删除它。像这样:
def save(self, *args, **kwargs):
if self.avatar:
pil_image_obj = Image.open(self.avatar)
new_image = resizeimage.resize_width(pil_image_obj, 300)
new_image_io = BytesIO()
new_image.save(new_image_io, format='JPEG')
temp_name = self.avatar.name
self.avatar.delete(save=False)
self.avatar.save(
temp_name,
content=ContentFile(new_image_io.getvalue()),
save=False
)
super(CustomUser, self).save(*args, **kwargs)
我希望这可以帮助您找到解决方案。谢谢:)
创建实例时,磁盘上没有存储头像文件。所以你尝试打开不存在的文件。
我看到你想在这里删除更新后的旧文件?
所以你不需要覆盖 save
方法。您应该做的是使用 pre_save
、post_save
和 post_delete
方法。
在 pre_save
你存储当前头像,在 post_save
更新后你应该检查新实例的文件路径与旧实例。如果不同则按 os.remove
在 post_delete
上删除文件。