如何从 Django ModelChoiceField 查询集中选择值和标签

Posted

技术标签:

【中文标题】如何从 Django ModelChoiceField 查询集中选择值和标签【英文标题】:How to choose the value and label from Django ModelChoiceField queryset 【发布时间】: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>

提前致谢!

【问题讨论】:

【参考方案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

我希望这会有所帮助。

【讨论】:

以上是关于如何从 Django ModelChoiceField 查询集中选择值和标签的主要内容,如果未能解决你的问题,请参考以下文章

Django,如何将变量从 Django 管理员传递到模板?

Django:如何从模板调用视图函数?

如何从 django 信号返回数据?

如何从 python 代码中调用 django 模板标签?

如何从 json 数据推断 Django 模型?

Django:如何从模板中识别调用视图?