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