<p>I have a web report that uses a Django form (new forms) for fields that control the query used to generate the report (start date, end date, ...). The issue I'm having is that the page should work using the form's initial values (unbound), but I can't access the cleaned_data field unless I call <code>is_valid()</code>. But <code>is_valid()</code> always fails on unbound forms.</p>
<p>It seems like Django's forms were designed with the use case of editing data such that an unbound form isn't really useful for anything other than displaying HTML.</p>
<p>For example, if I have:</p>
<pre><code>if request.method == 'GET':
    form = MyForm()
else:
    form = MyForm(request.method.POST)

if form.is_valid():
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
</code></pre>
<p>is_valid() will fail if this is a GET (since it's unbound), and if I do:</p>
<pre><code>if request.method == 'GET':
    form = MyForm()
    do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
else:
    form = MyForm(request.method.POST)
    if form.is_valid():
       do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
</code></pre>
<p>the first call to do_query triggers exceptions on form.cleaned_data, which is not a valid field because <code>is_valid()</code> has not been called. It seems like I have to do something like:</p>
<pre><code>if request.method == 'GET':
    form = MyForm()
    do_query(form['start_date'].field.initial, form['end_date'].field.initial)
else:
    form = MyForm(request.method.POST)
    if form.is_valid():
       do_query(form.cleaned_data['start_date'], form.cleaned_data['end_date'])
</code></pre>
<p>that is, there isn't a common interface for retrieving the form's values between a bound form and an unbound one.</p>
<p>Does anyone see a cleaner way to do this?</p>

[{'answer_id': 75815, 'author': 'Justin Voss', 'author_id': 5616, 'author_profile': 'https://Stackoverflow.com/users/5616', 'pm_score': 0, 'selected': False, 'text': '<p>You can pass a dictionary of initial values to your form:</p>\n\n<pre><code>if request.method == "GET":\n    # calculate my_start_date and my_end_date here...\n    form = MyForm( { \'start_date\': my_start_date, \'end_date\': my_end_date} )\n...\n</code></pre>\n\n<p>See the <a href="http://docs.djangoproject.com/en/dev/ref/forms/api/" rel="nofollow noreferrer">official forms API documentation</a>, where they demonstrate this.</p>\n\n<p><strong>edit</strong>: Based on answers from other users, maybe this is the cleanest solution:</p>\n\n<pre><code>if request.method == "GET":\n    form = MyForm()\n    form[\'start_date\'] = form[\'start_date\'].field.initial\n    form[\'end_date\'] = form[\'end_date\'].field.initial\nelse:\n    form = MyForm(request.method.POST)\nif form.is_valid():\n    do_query(form.cleaned_data[\'start_date\'], form.cleaned_data[\'end_date\'])\n</code></pre>\n\n<p>I haven\'t tried this though; can someone confirm that this works? I think this is better than creating a new method, because this approach doesn\'t require other code (possibly not written by you) to know about your new \'magic\' accessor.</p>\n'}, {'answer_id': 75923, 'author': 'Matthew Christensen', 'author_id': 2123, 'author_profile': 'https://Stackoverflow.com/users/2123', 'pm_score': 4, 'selected': True, 'text': "<p>If you add this method to your form class:</p>\n\n<pre><code>def get_cleaned_or_initial(self, fieldname):\n        if hasattr(self, 'cleaned_data'):\n            return self.cleaned_data.get(fieldname)\n        else:\n            return self[fieldname].field.initial\n</code></pre>\n\n<p>you could then re-write your code as:</p>\n\n<pre><code>if request.method == 'GET':\n    form = MyForm()\nelse:\n    form = MyForm(request.method.POST)\n    form.is_valid()\n\ndo_query(form.get_cleaned_or_initial('start_date'), form.get_cleaned_or_initial('end_date'))\n</code></pre>\n"}, {'answer_id': 81301, 'author': 'zgoda', 'author_id': 12138, 'author_profile': 'https://Stackoverflow.com/users/12138', 'pm_score': 2, 'selected': False, 'text': '<p><em>Unbound</em> means there is no data associated with form (either initial or provided later), so the validation may fail. As mentioned in other answers (and in your own conclusion), you have to provide initial values and check for both bound data and initial values.</p>\n\n<p>The use case for forms is form processing <strong>and</strong> validation, so you must have some data to validate before you accessing <code>cleaned_data</code>.</p>\n'}]
['https://Stackoverflow.com/questions/75621', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/8247/']