开发者

Dynamic choices for Django SelectMultiple Widget

I'm building a form (not modelForm) where i'd like to use the SelectMultiple Widget to display choices based on a query done during the init of the form.

I can think of a few way to do this but I am not exactly clear on the right way to do it. I see different options.

I get the "choices" I should pass to the widget in the form init but I am not sure how I should pass them.

class NavigatorExportForm(forms.Form):

def __init__(self,user, app_id, *args,**kwargs):
    super (NavigatorExportForm,self ).__init__(*args,**kwargs) # populates the form
    language_choices = Navigator.admin_objects.get(id=app_id).languages.all().values_list('language', flat=True)

languages = forms.CharFie开发者_如何学Cld(max_length=2, widget=forms.SelectMultiple(choices=???language_choices))


Why not use a ModelMultipleChoiceField instead?

You could do simply this :

class NavigatorExportForm(forms.Form):
    languages = forms.ModelMultipleChoiceField(queryset=Language.objects.all())

    def __init__(self, app_id, *args, **kwargs):
        super(NavigatorExportForm, self).__init__(*args, **kwargs)
        # Dynamically refine the queryset for the field
        self.fields['languages'].queryset = Navigator.admin_objects.get(id=app_id).languages.all()

This way you don't only restrict the choices available on the widget, but also on the field (that gives you data validation).

With this method, the displayed string in the widget would be the result of the __unicode__ method on a Language object. If it's not what you want, you could write the following custom field, as documented in ModelChoiceField reference :

class LanguageMultipleChoiceField(forms.ModelMultipleChoiceField):
    def label_from_instance(self, obj):
        return obj.language_code # for example, depending on your model

and use this class instead of ModelMultipleChoiceField in your form.


def __init__(self,user, app_id, *args,**kwargs):
super (NavigatorExportForm,self ).__init__(*args,**kwargs)
self.fields['languages'].widget.choices = Navigator.admin_objects.get(id=app_id).languages.all().values_list('language', flat=True)

that seems to do the trick, but even by not specifying a max_length, the widget only display the first letter of the choices...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜