Why django form.as_p call form.clean method when t

2019-05-31 20:32发布

问题:

I have this sample of django code:

# views.py
def test_view(request):
    form = TestForm(
        request.POST or { 'text': 'some text'},
    )
    data = {
        'form': form,
    }
    print 'before rendering'
    return render(request, 'test.html', data)

# forms.py
class TestForm(forms.Form):
    text = forms.CharField()

    def __init__(self, *args, **kwargs):
        print 'init'
        super(TestForm, self).__init__(*args, **kwargs)

    def clean(self):
        print 'in clean'

and this template:

#test.html
<form id='test-form' method="post" action="some url" enctype="multipart/form-data">
    {{ form.as_p }}
    <input type="submit" value="Save"/>
</form>

when i send get request to this file i have this output in console:

before rendering
init
in clean

when I write {{ form.text }} instead of {{ form.as_p }} I have only:

before rendering
init

It seams to me that as_p method calls clean() internally in process of rendering template. Before that I mentioned that as_p method only is some kind of shortcut(I understand that it's a method of Form class) and doesn't realize logic.
Why does it happen? Is it a bug or some usefull feature?

Version of Django==1.5.1

回答1:

As far as I can see in the source django has a _html_output helper function to return the function form.as_p(). If there is data bound to the form (like yours), then the BaseForm class property errors is called. This function calls the forms full clean. So I think this behaviour is intentionally to render form errors.



回答2:

Change your view like this:

# views.py
def test_view(request):

    if request.POST:
        form = TestForm(request.POST)
        # this is usually used when there's an actual post request
        # and in this block you do validation
    else:
        form = TestForm(initial={'somekey': 'somevalue'})

    data = {
        'form': form,
    }
    print 'before rendering'
    return render(request, 'test.html', data)

and clean() won't be called anymore



回答3:

The problem is that I unproper initialize form, I should use Form(initial={#something#})



标签: django forms