Django's Form framework is excellent. It's intuitive and versatile and, best of all, easy to use. However, one little thing that is not so intuitive is how do you render a bound form with default/initial values when the form is never rendered unbound.
If you do this in Django:
class MyForm(forms.Form):
name = forms.CharField(required=False)
def view(request):
form = MyForm(initial={'name': 'Peter'})
return render(request, 'page.html', form=form)
# Imagine, in 'page.html' that it does this:
# <label>Name:</label>
#
...it will render out this:
<label>Name:</label>
<input type="text" name="name" value="Peter">
The whole initial
trick is something you can set on the whole form or individual fields. But it's only used in UN-bound forms when rendered.
If you change your view function to this:
def view(request):
form = MyForm(request.GET, initial={'name': 'Peter'}) # data passed!
if form.is_valid(): # makes it bound!
print(form.cleaned_data['name'])
return render(request, 'page.html', form=form)
Now, the form
is bound and the initial
stuff is essentially ignored.
Because name
is not present in request.GET
. And if it was present, but an empty string, it wouldn't be able to benefit for the default value.
My solution
I tried many suggestions and tricks (based on rapid Stackoverflow searching) and nothing worked.
I knew one thing: Only the view should know the actual initial values.
Here's what works:
import copy
class MyForm(forms.Form):
name = forms.CharField(required=False)
def __init__(self, data, **kwargs):
data = copy.copy(data)
for key, value in kwargs.get("initial", {}).items():
data[key] = data.get(key, value)
super().__init__(data, **kwargs)
Now, suppose you don't have ?name=something
in request.GET
the line print(form.cleaned_data['name'])
will print Peter
and the rendered form will look like this:
<label>Name:</label>
<input type="text" name="name" value="Peter">
And, as expected, if you have ?name=Ashley
in request.GET
it will print Ashley
and produce this rendered HTML too:
<label>Name:</label>
<input type="text" name="name" value="Ashley">
from Planet Python
via read more
No comments:
Post a Comment