Django ImageField не обновляется при отправке формы
Описание выпуска
У меня есть модель, которая описывает UserProfile и специальная форма, позволяющая пользователю обновлять модель. За исключением photo (ImageField), все работает нормально. Проблема с полем photo заключается в том, что изображение не изменяется вообще при EditProfileForm. Другими словами, у меня есть одно и то же изображение, прикрепленное к этому полю до и после отправки формы, photo указывает на то же самое изображение, и ничего нового не было загружено на сервер.
Стоит отметить, что поле photo работает через форму из админ панели.
С другими полями, относящимися к UserProfile и User, проблем нет: все они могут быть обновлены, и обновление сохраняется в базе данных.
Подробности об окружающей среде
<На данный момент я использую Django версии 4.0.3, запущенный с
и собранный на сервере разработки.### 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?
попробуйте это
используйте multipart/form-data, если ваша форма включает в себя какие-либо элементы
в шаблонах
<form class="" action="" method="POST" enctype="multipart/form-data">