ModelForm с ImageFields, не очищается должным образом, если ошибка проверки - PullRequest
0 голосов
/ 06 сентября 2011

Сначала код. ModelForm (im1 и im2 - модели. ImageField):

class TestForm(forms.ModelForm):
    checkme = forms.BooleanField(required=True)

    class Meta:
        model = UserProfile
        fields = ('im1', 'im2')

Мнение:

def test(request):
    profile = request.user.get_profile()
    form = TestForm(instance=profile)
    if request.method == "POST":
        form = TestForm(request.POST, request.FILES, instance=profile)
        if form.is_valid():
            form.save()
    return render(request, 'test.html', {'form':form})

Шаблон:

<html>
<head>
<title>Test</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" />
</form>
</body>
</html>

Проблемы:

Если im1 содержит действительное изображение, и я отмечаю флажок рядом с ним, но не проверяю checkme и не отправляю, форма возвращается с ошибкой, сообщающей, что checkme требуется. Хотя форма возвращается с ошибкой, похоже, что im1 был очищен. На самом деле это не так, потому что, если я перезагружаю форму, im1 снова показывает файл и снимает флажок.

Мой вопрос: как я могу это исправить? Это то, что я делаю, или это как-то связано с django?

1 Ответ

0 голосов
/ 07 сентября 2011

Джанго действует именно так, как и должен.

Если запрос является запросом 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.

Не вижу, чтобы это стоило того. Как я уже говорил ранее, вы просто создаете больше работы для своего пользователя ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...