11👍
By slightly modifying Gonzalo’s solution, this is the right way:
class Form(forms.Form):
name = forms.CharField(required=False, initial='Hello world')
def clean_name(self):
if not self['name'].html_name in self.data:
return self.fields['name'].initial
return self.cleaned_data['name']
If you need this, you may have a look at django-filter app. I have discovered it quite recently.
5👍
initial
isn’t really meant to be used to set default values for form fields.
Instead, it’s really more a placeholder utility when displaying forms to the user, and won’t work well if the field isn’t required (like in your example).
What you can do is define a clean_<fieldname>
method that checks if there’s an empty value for that field and return the default:
class Form(forms.Form):
name = forms.CharField(required=False, initial='Hello world')
def clean_name(self):
name = self.cleaned_data['name']
if name is None:
return self.fields['name'].initial
return name
- Fabric + buildout as opposed to Fabric + pip + virtualenv
- Could not import settings 'myproject.settings' (Is it on sys.path?): No module named pinax
- Is there a Python3 compatible Django storage backend for Amazon S3?
- How to pass an url as parameter of include
4👍
I use the following pattern for setting default values as initial values given for the form-
class InitialDefaultForm(forms.Form):
def clean(self):
cleaned_data = super(InitialDefaultForm, self).clean()
# if data is not provided for some fields and those fields have an
# initial value, then set the values to initial value
for name in self.fields:
if not self[name].html_name in self.data and self.fields[name].initial is not None:
cleaned_data[name] = self.fields[name].initial
return cleaned_data
This ensures that all fields which have an initial value and do not get values from user get populated by their initial value.
2👍
request.GET
is a dictionary like object.
initial
only works in case of unbound form.
Forms have an attribute named data
. This attribute is provided as first positional argument or as a data
keyword argument during form initialization.
Bound forms are those in which you provide some data as first argument to the form and unbound form has data
attribute set as None.
Here in your initialization of form form=Form(request.GET)
, you are providing the first positional argument, so data
attribute is being set on the form and it becomes a bound form. This happens even if request.GET
is an empty dictionary. And since your form becomes a bound form so initial
of name
field has no effect on it.
So, In you GET request you should either do:
form = Form()
and your initial
of name
field would be honoured.
Or, if you want to read name
from request.GET and if its there then want to use it instead of field’s initial then have following in your view.
name = request.GET.get(name)
form_level_initial = {}
if name:
form_level_initial['name'] = name
form = Form(initial=form_level_initial)
- Unable to find/build a commenting system similar as at Djangobook
- What is the correct way to deal with DB migration while using South, Django and Git?
- Access form field attributes in templated Django
- Django: taking input and showing output in the same page
2👍
Will this work:
initial_form_data = {'name': 'Hello World'} #put all the initial for fields in this dict
initial_form_data.update(request.GET) #any field available in request.GET will override that field in initial_form_data
form = Form(initial_form_data)
if form.is_valid():
name = form.cleaned_data['name']
- Problem reusing serializers with django and drf-yasg
- Django ORM, CharField and blank=True
- Django: Creating a superuser with a custom User model
- Docker-compose to run django with mongodb
2👍
The proposed solutions either didn’t work for me or just seemed not very elegant. The documentation specifies that initial does not work for a bound form, which seems to be the original questioners (and my) use case:
This is why initial values are only displayed for unbound forms. For bound forms, the HTML output will use the bound data.
https://docs.djangoproject.com/en/1.10/ref/forms/fields/#initial
My solution is to see if the form should be bound or not:
initial = {'status': [Listing.ACTIVE], 'min_price': 123} # Create default options
if request.method == 'GET':
# create a form instance and populate it with data from the request:
if len(request.GET):
form = ListingSearchForm(request.GET) # bind the form
else:
form = ListingSearchForm(initial=initial) # if GET is empty, use default form
You could also use the other ways of initializing the form (mentioned above).
0👍
None of the answers actually does exactly what clime asked for. So here is my solution for the same problem:
class LeadsFiltersForm(forms.Form):
TYPE_CHOICES = Lead.TYPES
SITE_CHOICES = [(site.id, site.name) for site in Site.objects.all()]
type = forms.MultipleChoiceField(
choices=TYPE_CHOICES, widget=forms.CheckboxSelectMultiple(),
required=False
)
site = forms.MultipleChoiceField(
widget=forms.CheckboxSelectMultiple(), required=False,
choices=SITE_CHOICES
)
date_from = forms.DateField(input_formats=['%m-%d-%Y',], required=False,
widget=forms.TextInput(attrs={'placeholder': 'Date From'}),
initial=timezone.now() - datetime.timedelta(days=30))
date_to = forms.DateField(input_formats=['%m-%d-%Y',], required=False,
widget=forms.TextInput(attrs={'placeholder': 'Date To'}))
defaults = {
'type': [val[0] for val in TYPE_CHOICES],
'site': [val[0] for val in SITE_CHOICES],
'date_from': (timezone.now() - datetime.timedelta(days=30)).strftime('%m-%d-%Y'),
'date_to': timezone.now().strftime('%m-%d-%Y')
}
def __init__(self, data, *args, **kwargs):
super(LeadsFiltersForm, self).__init__(data, *args, **kwargs)
self.data = self.defaults.copy()
for key, val in data.iteritems():
if not data.get(key):
continue
field = self.fields.get(key)
if field and getattr(field.widget, 'allow_multiple_selected', False):
self.data[key] = data.getlist(key)
else:
self.data[key] = data.get(key)
- Django and Folium integration
- Django REST Framework and generic relations
- Readonly fields in django formset
- Django – missing 1 required positional argument: 'request'
- How can I use Django Social Auth to connect with Twitter?