提交表单时 Django ImageField 未更新
问题描述
我有一个模型,它描述了用户配置文件和一个专用表单,以允许用户更新模型。除了 photo
(ImageField) 之外,一切正常。 photo
字段的问题是 EditProfileForm
根本没有更改图像。换句话说,在表单提交之前和之后,我在该字段中附加了相同的图像,photo
指向同一张图片,并且没有任何新内容上传到服务器。 值得注意的是,photo
字段是通过管理面板中的表单进行操作的。 与 UserProfile
和 User
相关的其他字段没有问题:所有这些字段都可以更新,并且更新保存在数据库中。
环境详细信息
目前,我使用 Django 4.0.3 版本,运行 DEBUG=True
并构建在开发服务器中。
代码
### Models
def get_image_save_path(
instance,
filename:str
) -> str:
save_dir = instance.__class__.__name__
file_name = uuid.uuid4().hex
file_extension = pathlib.Path(filename).suffix
return f"{save_dir}/{file_name}{file_extension}".lower()
def validate_image_size(image):
if not image:
raise ValidationError("No image found")
if image.size > 512*1024:
raise ValidationError("Max size is 512kb")
class UserProfile(models.Model):
user = models.OneToOneField(User,
on_delete=models.CASCADE,
related_name='user_profile',
primary_key=True)
photo = models.ImageField(upload_to=get_image_save_path,
verbose_name="Photo",
validators=[validate_image_size],
default="userprofile/default_photo.jpg",
null=False,
blank=False)
bio = models.TextField(default='', blank=True)
def __str__(self):
return f"{self.user.username}"
@receiver(post_save, sender=User)
def create_user_profile(
sender:ModelBase,
instance:User,
created:bool,
**kwargs:Dict) -> None:
if created:
UserProfile.objects.create(user=instance)
else:
return
@receiver(post_save, sender=User)
def save_user_profile(
sender: ModelBase,
instance: User,
**kwargs: Dict) -> None:
instance.user_profile.save()
### Forms
class EditUserForm(ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class EditProfileForm(ModelForm):
photo = ImageField(widget=FileInput(attrs={'class': 'form-control-file'}))
class Meta:
model = UserProfile
fields = ('photo', 'bio')
### Views
@login_required
def profile_view(request):
return render(request,
template_name="accounts/profile_view.html",
context = {})
@login_required
def profile_edit(request):
if request.method == 'POST':
userForm = EditUserForm(data=request.POST, instance=request.user)
profileForm = EditProfileForm(data=request.POST,
files=request.FILES,
instance=request.user.user_profile)
if userForm.is_valid() and profileForm.is_valid():
profileForm.save()
userForm.save()
return redirect('accounts_app:profile_view')
else:
userForm = EditUserForm(instance=request.user)
profileForm = EditProfileForm(instance=request.user.user_profile)
context = {"userForm": userForm, "profileForm": profileForm, }
return render(request, 'accounts/edit_profile.html', context)
### Template
{% block content %}
<div class="row">
<div class="panel panel-primary panel-login rounded-lg">
<div class="panel-body">
<form class="" action="" method="POST">
{% csrf_token %}
{% for field in userForm %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
{% for field in profileForm %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button class="btn btn-danger standard-btn" type="submit">Zapisz zmiany</button>
</form>
</div>
</div>
</div>
{% endblock %}
问题
我在代码中做错了什么,导致 photo
字段出现并描述了问题?
Issue describrion
I have a model which describes a UserProfile and a dedicated form to allow user to update the model. Except photo
(ImageField), everything is working fine. Issue with photo
field is that the image is not being changed at all with EditProfileForm
. In other words I have same image attached to this field before and after form submition, the photo
is pointing to the same picture, and nothing new was uploaded to the server.
It is worth to be noted that photo
field is working through the form from admin panel.
No issues with other fields related to UserProfile
and User
: all of them can be updated, and the update is saved in database.
Environment details
For a time being I am using Django in version 4.0.3 running with DEBUG=True
and build in development server.
Code
### Models
def get_image_save_path(
instance,
filename:str
) -> str:
save_dir = instance.__class__.__name__
file_name = uuid.uuid4().hex
file_extension = pathlib.Path(filename).suffix
return f"{save_dir}/{file_name}{file_extension}".lower()
def validate_image_size(image):
if not image:
raise ValidationError("No image found")
if image.size > 512*1024:
raise ValidationError("Max size is 512kb")
class UserProfile(models.Model):
user = models.OneToOneField(User,
on_delete=models.CASCADE,
related_name='user_profile',
primary_key=True)
photo = models.ImageField(upload_to=get_image_save_path,
verbose_name="Photo",
validators=[validate_image_size],
default="userprofile/default_photo.jpg",
null=False,
blank=False)
bio = models.TextField(default='', blank=True)
def __str__(self):
return f"{self.user.username}"
@receiver(post_save, sender=User)
def create_user_profile(
sender:ModelBase,
instance:User,
created:bool,
**kwargs:Dict) -> None:
if created:
UserProfile.objects.create(user=instance)
else:
return
@receiver(post_save, sender=User)
def save_user_profile(
sender: ModelBase,
instance: User,
**kwargs: Dict) -> None:
instance.user_profile.save()
### Forms
class EditUserForm(ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class EditProfileForm(ModelForm):
photo = ImageField(widget=FileInput(attrs={'class': 'form-control-file'}))
class Meta:
model = UserProfile
fields = ('photo', 'bio')
### Views
@login_required
def profile_view(request):
return render(request,
template_name="accounts/profile_view.html",
context = {})
@login_required
def profile_edit(request):
if request.method == 'POST':
userForm = EditUserForm(data=request.POST, instance=request.user)
profileForm = EditProfileForm(data=request.POST,
files=request.FILES,
instance=request.user.user_profile)
if userForm.is_valid() and profileForm.is_valid():
profileForm.save()
userForm.save()
return redirect('accounts_app:profile_view')
else:
userForm = EditUserForm(instance=request.user)
profileForm = EditProfileForm(instance=request.user.user_profile)
context = {"userForm": userForm, "profileForm": profileForm, }
return render(request, 'accounts/edit_profile.html', context)
### Template
{% block content %}
<div class="row">
<div class="panel panel-primary panel-login rounded-lg">
<div class="panel-body">
<form class="" action="" method="POST">
{% csrf_token %}
{% for field in userForm %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
{% for field in profileForm %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="color: grey">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button class="btn btn-danger standard-btn" type="submit">Zapisz zmiany</button>
</form>
</div>
</div>
</div>
{% endblock %}
Question
What I did wrong in the code, that is causing and described issue with photo
field?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请尝试使用 multipart/form-data
任何元素时,
当您的表单包含模板中的
try this
use multipart/form-data when your form includes any elements
in templates