更改 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
这种方法将保留字段的参数(您无需指定queryset
、required
等)。
【讨论】:
【参考方案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 以显示用户的全名而不是用户名的主要内容,如果未能解决你的问题,请参考以下文章