【问题标题】:Dynamic choices for Django SelectMultiple WidgetDjango SelectMultiple 小部件的动态选择
【发布时间】:2011-02-07 02:02:51
【问题描述】:

我正在构建一个表单(不是 modelForm),我想使用 SelectMultiple 小部件根据表单初始化期间完成的查询来显示选择。

我可以想到几种方法来做到这一点,但我并不完全清楚正确的方法。我看到了不同的选择。

我得到了我应该以 init 形式传递给小部件的“选择”,但我不确定应该如何传递它们。

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.CharField(max_length=2, widget=forms.SelectMultiple(choices=???language_choices))

【问题讨论】:

    标签: django forms widget


    【解决方案1】:

    为什么不改用ModelMultipleChoiceField

    你可以这样做:

    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()
    

    这样,您不仅可以限制小部件上的可用选项,还可以限制字段上的可用选项(这为您提供数据验证)。

    使用此方法,小部件中显示的字符串将是Language 对象上的__unicode__ 方法的结果。如果这不是您想要的,您可以编写以下自定义字段,如 ModelChoiceField reference 中所述:

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

    并在您的表单中使用此类而不是 ModelMultipleChoiceField

    【讨论】:

    • 我见过提到 ModelMultipleChoiceField,但不确定它的用途。现在正在尝试。谢谢。
    • 完美运行,看起来比我的干净一点。再次感谢
    • mmm 实际上,我在验证表单时收到“AttributeError: 'unicode' object has no attribute 'get'”。我的语言模型确实是一个 char 字段...
    • 您必须提供有关此错误的更多详细信息,它发生在哪个文件中?上下文是什么?它可能来自您清理或操作表单中已清理数据的方式吗?另外,您的意思是:我的语言模型确实是一个字符字段...
    【解决方案2】:
    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)
    

    这似乎可以解决问题,但即使不指定 max_length,小部件也只会显示选项的第一个字母...

    【讨论】:

    • choices 必须是以下元组的列表/元组 (int_or_str_key, 'name')
    猜你喜欢
    • 2010-10-13
    • 2011-05-11
    • 2020-06-10
    • 2011-03-28
    • 2019-03-27
    • 1970-01-01
    • 2012-06-10
    • 2022-01-26
    • 1970-01-01
    相关资源
    最近更新 更多