38

我的 Django 应用程序(不在管理员中)中有一个表单,允许工作人员从下拉列表中选择用户。

forms.ModelChoiceField(queryset = User.objects.filter(is_staff=False), required = False)

问题是下拉菜单按用户名显示用户,而我宁愿它从 user.get_full_name() 显示他们的全名,并且仅在不可用时才使用用户名。我只需要在此页面上进行此更改,在管理员等其他地方,我不在乎它是否使用用户名。

有没有办法我可以做到这一点?

谢谢!

4

5 回答 5

77

您可以设置一个自定义ModelChoiceField,它将返回您想要的任何标签。

在 fields.py 或任何适用的地方放置类似的内容。

class UserModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
         return obj.get_full_name()

然后在创建表单时,只需使用该字段

 UserModelChoiceField(queryset=User.objects.filter(is_staff=False), required = False)

更多信息可以在这里找到

于 2010-07-02T17:27:49.543 回答
31

在使用 ModelForm 时,我发现以下内容最有用,因此我不必重新定义我的查询集 - 特别是因为我在模型定义中使用了 limit_choices_to:

class MyModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MyModelForm, self).__init__(*args, **kwargs)
        self.fields['user'].label_from_instance = lambda obj: "%s" % obj.get_full_name()

从这个答案定制https://stackoverflow.com/a/7805824/432992

于 2013-04-05T18:43:17.143 回答
2

您可以使用自定义覆盖该字段并将函数ModelChoiceField更改label_from_instance为返回get_full_name。请参阅文档ModelChoiceFieldhttp ://docs.djangoproject.com/en/1.2/ref/forms/fields/#modelchoicefield

于 2010-07-02T17:27:32.507 回答
2

如果您想以模型形式更改字段的选择,请尝试对 Bartek 的回答进行此改编:

模型:

class MyModel(models.Model)
    user = models.ForeignKey(...)

表单域:

class UserModelChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, obj):
        return obj.get_full_name()

形式:

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = ['user']
        field_classes = {
            'user': UserModelChoiceField
        }

这种方法将保留该字段的参数(您不需要指定querysetrequired等等)。

于 2019-12-27T20:32:39.613 回答
0

您还可以创建一个自定义 ModelChoiceField,您可以将函数传递给该字段。这样,如果您有不同的字段希望显示不同的属性,则只能有 1 个类:

class CustomModelChoiceField(forms.ModelChoiceField):
name_function = staticmethod(lambda obj: obj)

def __init__(self, name_function, *args, **kwargs):
    if not name_function is None: self.name_function = name_function
    super(CustomModelChoiceField, self).__init__(*args, **kwargs)

def label_from_instance(self, obj):
     return self.name_function(obj);

然后,您可以像这样简单地调用它:

form_field = CustomModelChoiceField(
    lambda obj: obj.get_full_name(),
    queryset=Whatever.objects.all(),
)

如果你正在做一些动态的事情,你也可以传递 None ,它基本上默认为一个常规的 ModelChoiceField。我不是一个蟒蛇人,但这对我有用。

于 2020-05-21T06:42:48.083 回答