Джанго действует именно так, как и должен.
Если запрос является запросом POST, то ваша форма привязана к данным из request.POST
и request.FILES
. instance=profile
просто сообщает форме, в какой конкретный объект сохранить, если все проверки пройдены. Даже если ваша форма недействительна, она все равно привязана к данным с очищенным изображением, и это то, что вы передаете render()
.
Во-первых, вы не должны создавать первую связанную форму, если метод запроса POST:
def test(request):
profile = request.user.get_profile()
if request.method == "POST":
form = TestForm(request.POST, request.FILES, instance=profile)
if form.is_valid():
form.save()
else:
form = TestForm(instance=profile)
return render(request, 'test.html', {'form':form})
Во-вторых, почему вы хотите, чтобы ваш пользователь дважды совершал одно и то же действие, если он действительно хотел удалить изображение, но просто пропустил другой флажок?
Если вам действительно нужно, чтобы Джанго действовал таким образом, я бы сделал одну из двух вещей. Либо создайте связанную форму из экземпляра UserProfile и передайте недопустимую форму и вновь созданную форму в шаблон и используйте недопустимую форму для отображения ошибок, а другую - для отображения остальной части формы:
def test(request):
profile = request.user.get_profile()
if request.method == "POST":
errors_form = TestForm(request.POST, request.FILES, instance=profile)
if errors_form.is_valid():
errors_form.save()
form = errors_form
else:
form = TestForm(instance=profile)
return render(request, 'test.html', {'form':form, 'errors_form': errors_form})
else:
form = TestForm(instance=profile)
return render(request, 'test.html', {'form':form})
ИЛИ я бы сделал то же самое, но сохранил бы ошибки из недействительной формы во вновь созданной форме, чтобы вы не получили renders()
повсюду:
def test(request):
profile = request.user.get_profile()
if request.method == "POST":
errors_form = TestForm(request.POST, request.FILES, instance=profile)
if errors_form.is_valid():
errors_form.save()
form = errors_form
else:
form = TestForm(instance=profile)
#this is left up to you to implement, but you'd do something like
#form.errors = errors_form.errors
#and also iterate through every form attribute.errors and assign it to
#errors_form attribute.errors etc...
else:
form = TestForm(instance=profile)
return render(request, 'test.html', {'form':form})
Оба не очень элегантные решения, и я не уверен, что второе будет работать, как и ожидалось, без дополнительных хаков, поскольку я не совсем знаком с реализацией Django Forms.
Не вижу, чтобы это стоило того. Как я уже говорил ранее, вы просто создаете больше работы для своего пользователя ...