Getting dynamic model choices in newforms

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from django import newforms as forms
from models import Language

# I put this on all required fields, because it's easier to pick up
# on them with CSS or JavaScript if they have a class of "required"
# in the HTML. Your mileage may vary.
attrs_dict = { 'class': 'required' }

class AddSnippetForm(forms.Form):
    """
    Form used for adding Snippets.
    
    """
    def __init__(self, *args, **kwargs):
        super(AddSnippetForm, self).__init__(*args, **kwargs)
        self.fields['language'].choices = [('', '----------')] + [(lang.id, lang.name) for lang in Language.objects.all()]
    
    title = forms.CharField(max_length=250, widget=forms.TextInput(attrs=attrs_dict))
    description = forms.CharField(widget=forms.Textarea(attrs=attrs_dict))
    code = forms.CharField(widget=forms.Textarea(attrs=attrs_dict))
    tag_list = forms.CharField(max_length=250, widget=forms.TextInput(attrs=attrs_dict))
    language = forms.ChoiceField(choices=(), widget=forms.Select(attrs=attrs_dict))

More like this

  1. assign fields dynamically in newforms by rubic 7 years, 1 month ago
  2. Reorder fields directly in the ModelForm by HM 5 years, 11 months ago
  3. A Lazy ChoiceField implementation by lsbardel 4 years, 6 months ago
  4. Enumeration field by nail.xx 5 years, 9 months ago
  5. Modify fields created by form_for_model by grahamu 7 years, 1 month ago

Comments

dschein (on March 1, 2007):

It is also easy to create a builder function. You can use the same caching mechanism you do with other functions and even return different forms depending on the arguments.

@memoize_to_cache
def schedule_form(schedule, category):
    def _get_subjects():
        # some time consuming returns your choices
        # ...

    if category == CR:
        class CreditCourseSearchForm (forms.Form):
            subjects = forms.MultipleChoiceField(_get_subjects(), required=False)
            advising_codes = forms.ChoiceField(ADVISING_CODE_CHOICES, required=False)
            # ... 
        return CreditCourseSearchForm
    else:
        class NonCreditCourseSearchForm (forms.Form):
            subjects = forms.MultipleChoiceField(_get_subjects(), required=False)
            learning_community = forms.MultipleChoiceField(COMMUNITIES, required=False)
            # ... 
        return CreditCourseSearchForm

#

wub (on July 23, 2007):

Thank you!!!

I have spent several days trying to figure out how to filter a lookup table based on a value passed at run time. I was on the verge of deciding it could not be done, when I discovered this Snippet.

My only wish now is that I could understand >why< this works, when nothing else I tried did, but fortunately many things that I do not understand work anyway.

#

max (on July 25, 2007):

Thank you for this snippet, one more question:

after

self.fields['language'].choices =

i put

'myfunction()'

, returning a list of choices and between '' because it is defined in another python file.

i got the following error at execution time:

need more than 1 value to unpack

What does it mean ???

Thank you very much

max

#

ben_eliott (on May 8, 2008):

Thank you for this helpful snippet ubernostrum.

If the form is bound and you want to filter the database query based on a value therein you can access it by: self.data.get('fieldname')

#

beuc (on November 3, 2009):

You can also use the 'queryset' field of ModelChoiceField:

class MyForm(forms.ModelForm):
    class Meta:
        model = my_models.MyModel

    def __init__(self, *args, **kwargs):
        dynarg = kwargs.pop('dynarg')
        self.base_fields['myfield'].empty_label = None
        self.base_fields['myfield'].queryset = my_models.MyField.objects.filter(myfilter=dynarg)
        super(MyForm, self).__init__(*args, **kwargs)

#

ashish (on May 10, 2012):

class MinorMessageForm( forms.Form):

#add choice by user

def __init__(self, *args, **kwargs):
    uid = kwargs.pop('uid')
    if uid: #remember to use exception handleing
        userdata = User.objects.get( id=uid)
        udata = userdata.minor_custodian
        l = []
        for u in udata:
             l.append(u.get('minor-name') +' - '+ u.get('custodian-email'))
    super(MinorMessageForm, self).__init__(*args, **kwargs)
    self.fields['for_user'].choices=  [('', '----------')]

its giving me key error at last line : for_user

#

(Forgotten your password?)