Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django form with choices but also with freetext option?

What I'm looking for: A single widget that gives the user a drop down list of choices but then also has a text input box underneath for the user to enter a new value.

The backend model would have a set of default choices (but wouldn't use the choices keyword on the model). I know I can (and I have) implemented this by having the form have both a ChoicesField and CharField and have code use the CharField if ChoicesField is left at the default, but this feels "un-django" like.

Is there a way (either using Django-builtins or a Django plugin) to define something like ChoiceEntryField (modeled after the GtkComboboxEntry which IIRC does this) for a form?

In case anyone finds this, note that there is a similar question on how to best do what I was looking for from a UX perspective at https://ux.stackexchange.com/questions/85980/is-there-a-ux-pattern-for-drop-down-preferred-but-free-text-allowed

like image 326
Foon Avatar asked Jul 16 '14 14:07

Foon


People also ask

What is the difference between form and ModelForm in Django?

The differences are that ModelForm gets its field definition from a specified model class, and also has methods that deal with saving of the underlying model to the database. Show activity on this post. Show activity on this post. Form is a common form that is unrelated to your database (model ).

What is form Is_valid () in Django?

The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute.

How many types of Django forms are there?

Django form fields define two types of functionality, a form field's HTML markup and its server-side validation facilities.

What is get and post method in Django?

GET and POST Django's login form is returned using the POST method, in which the browser bundles up the form data, encodes it for transmission, sends it to the server, and then receives back its response. GET , by contrast, bundles the submitted data into a string, and uses this to compose a URL.


1 Answers

I would recommend a custom Widget approach, HTML5 allows you to have a free text input with a dropdown list which would work as a pick-one-or-write-other type of field, this is how I made it:

fields.py

from django import forms  class ListTextWidget(forms.TextInput):     def __init__(self, data_list, name, *args, **kwargs):         super(ListTextWidget, self).__init__(*args, **kwargs)         self._name = name         self._list = data_list         self.attrs.update({'list':'list__%s' % self._name})      def render(self, name, value, attrs=None, renderer=None):         text_html = super(ListTextWidget, self).render(name, value, attrs=attrs)         data_list = '<datalist id="list__%s">' % self._name         for item in self._list:             data_list += '<option value="%s">' % item         data_list += '</datalist>'          return (text_html + data_list) 

forms.py

from django import forms from myapp.fields import ListTextWidget  class FormForm(forms.Form):    char_field_with_list = forms.CharField(required=True)     def __init__(self, *args, **kwargs):       _country_list = kwargs.pop('data_list', None)       super(FormForm, self).__init__(*args, **kwargs)      # the "name" parameter will allow you to use the same widget more than once in the same     # form, not setting this parameter differently will cuse all inputs display the     # same list.        self.fields['char_field_with_list'].widget = ListTextWidget(data_list=_country_list, name='country-list') 

views.py

from myapp.forms import FormForm  def country_form(request):     # instead of hardcoding a list you could make a query of a model, as long as     # it has a __str__() method you should be able to display it.     country_list = ('Mexico', 'USA', 'China', 'France')     form = FormForm(data_list=country_list)      return render(request, 'my_app/country-form.html', {         'form': form     }) 
like image 179
Viktor eXe Avatar answered Sep 20 '22 17:09

Viktor eXe