【问题标题】:How to choose the value and label from Django ModelChoiceField queryset如何从 Django ModelChoiceField 查询集中选择值和标签
【发布时间】:2013-11-29 12:32:06
【问题描述】:

我试图创建一个 django 表单,我的一个字段包含一个 ModelChoiceField

class FooForm(forms.Form):

    person =  forms.ModelChoiceField(queryset=Person.objects.filter(is_active=True).order_by('id'), required=False)
    age = forms.IntegerField(min_value=18, max_value=99, required=False)

当我尝试上面的代码时,它作为 html 输出返回的内容是

<option value="1">Person object</option>

在我的 Person 模型上,我有字段 "id, fname, lname, is_active" 。是否可以指定我的下拉选项将使用“id”作为值并使用“lname”作为标签?预期的 html 应该是

<option value="1">My Last Name</option>

提前致谢!

【问题讨论】:

    标签: python html django forms model


    【解决方案1】:

    你可以在表单ie的init中添加对label_from_instance的调用

    通过添加类似的东西

    class TestForm(ModelForm):
        def __init__(self, *args, **kwargs):
            super(TestForm, self).__init__(*args, **kwargs)
    
            self.fields['field_name'].label_from_instance = self.label_from_instance
    
        @staticmethod
        def label_from_instance(obj):
            return "My Field name %s" % obj.name
    

    【讨论】:

    • 非常优雅的解决方案。使您能够更改特定表单的模型选择标签。
    • 这是一个很好的解决方案,因为它允许您使用字符串表示之外的其他标签。太好了!!!
    • 太棒了!!这正是所需的,而无需永久更改 str 表示
    【解决方案2】:

    来自 Django 文档:

    https://docs.djangoproject.com/en/dev/ref/forms/fields/#django.forms.ModelChoiceField

    模型的__unicode__(Python 3 上的__str__)方法将是 调用以生成对象的字符串表示形式以用于 领域的选择;提供定制的表示,子类 ModelChoiceField 并覆盖 label_from_instance。这种方法将 接收一个模型对象,并且应该返回一个适合的字符串 代表它。例如:

    from django.forms import ModelChoiceField
    
    class MyModelChoiceField(ModelChoiceField):
        def label_from_instance(self, obj):
            return "My Object #%i" % obj.id
    

    因此,您可以这样做,或者在您的模型类上覆盖 __str__ 以返回姓氏。

    【讨论】:

    • 您好 FogleBird,感谢您的回复。这个解决方案实际上可以为我工作。我只是有一个额外的问题,默认情况下,django ModelChoiceField 是否会在模型中查找某个列以用作选项上的标签?
    • 它首先要查找的是您在模型中定义的 unicode def。正如 FogleBird 所提到的,它在 Python 3 中的 str
    • 这个答案指向了正确的方向,ModelChoiceField 可以通过提供参数来自定义
    • 你如何实际使用它?我应该把它放在哪里,在模型中还是在表单中?
    【解决方案3】:

    在您的 Person 模型中添加:

    def __unicode__(self):
        return u'{0}'.format(self.lname)
    

    如果您使用的是 Python 3,则定义 __str__ 而不是 __unicode__

    def __str__(self):
        return u'{0}'.format(self.lname)
    

    【讨论】:

    • 谢谢!为我工作。我只是有一个我已经在上面发布的附加问题,ModelChoiceField 默认情况下会在模型中查找它用作标签的某个列或字段吗?
    • 但这不会将选项值设置为数字,是吗?
    • 但是如果你不想要 unicode 怎么办。你能告诉它用什么吗?
    • @Sloy 它只会以可读的方式改变实例的表示方式。
    【解决方案4】:

    您可以将ModelChoiceField 实例的label_from_instance 方法覆盖为您的自定义方法。您可以在表单的__init__ 方法内完成

    class FooForm(forms.Form):
        person =  forms.ModelChoiceField(queryset=Person.objects.filter(is_active=True).order_by('id'), required=False)
        age = forms.IntegerField(min_value=18, max_value=99, required=False)
    
        def __init__(self, *args, **kwargs):
            super(FooForm, self).__init__(*args, **kwargs)
    
            self.fields['person'].label_from_instance = lambda instance: instance.name
    

    【讨论】:

      【解决方案5】:

      要选择/更改可以使用“to_field_name”选项的值, 要更改选项的标签,您可以覆盖 ModelChoiceField 类中的“label_from_instance”函数,

      这是一个简单的例子,

      forms.py:

      from django import forms
      from .models import Group
      from django.forms import ModelChoiceField
      
      
      class MyModelChoiceField(ModelChoiceField):
          def label_from_instance(self, obj):
              return f"My Object {obj.group_name}"
      
      
      class MyPureDjangoForm(forms.Form):
      
          group = MyModelChoiceField(queryset=Group.objects.all(),
                                          widget=forms.Select(attrs={
                                              'class': 'form-control'
                                          }),
                                          to_field_name='id',                                   
                                          
                                          )
      

      欲了解更多信息,请访问以下网址:

      https://docs.djangoproject.com/en/3.2/ref/forms/fields/#django.forms.ModelChoiceField

      我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2013-03-14
        • 1970-01-01
        • 2014-11-15
        • 2011-12-31
        • 2011-07-13
        • 2016-12-02
        • 2013-03-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多