更改 Django ModelChoiceField 以显示用户的全名而不是用户名

Posted

技术标签:

【中文标题】更改 Django ModelChoiceField 以显示用户的全名而不是用户名【英文标题】:Change Django ModelChoiceField to show users' full names rather than usernames 【发布时间】:2011-03-11 05:11:50 【问题描述】:

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

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

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

有什么办法可以做到吗?

谢谢!

【问题讨论】:

【参考方案1】:

您可以设置自定义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)

更多信息可以找到here

【讨论】:

谢谢!这行得通,但它不是 forms.UserModelChoiceField 它是 where_you_put_that_class.UserModelChoiceField 这对我不起作用,我收到错误 NameError: name 'UserModelChoiceField' is not defined。我在定义类UserModelChoiceField 之后把它说对了。我是否必须做其他事情,例如注册课程或其他事情? (我正在尝试在管理员中执行此操作。) 感谢您的解决方案,2022年,祝您新年快乐。【参考方案2】:

在使用 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://***.com/a/7805824/432992

【讨论】:

像魅力一样工作! 可能错误:'ModelForm 没有指定模型类'。需要将class MyModelForm(forms.ModelForm) 替换为class MyModelForm(forms.Form)【参考方案3】:

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

【讨论】:

【参考方案4】:

如果您想更改模型形式的字段选择,请尝试对 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 等)。

【讨论】:

【参考方案5】:

您还可以创建一个自定义 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。我不是一个 python 人,但这对我有用。

【讨论】:

以上是关于更改 Django ModelChoiceField 以显示用户的全名而不是用户名的主要内容,如果未能解决你的问题,请参考以下文章

响应 Django 中的模型更改?

Django迁移更改目录结构后未检测到更改

如果我更改 django 应用程序名称会出现啥问题?

我无法更改主 Django 项目设置文件

DJANGO:更改 ModelMultipleChoiceField 的字段大小?

更改 PostgreSQL 服务器更改了 Django 应用程序特征