如何在选择字段为ForeignKey时更改select中的显示文本? 我不仅需要显示FK的名称,还需要显示它的父名称。
任何人都可以提供线索吗?
答案 0 :(得分:51)
如果您希望它仅在admin中生效,而不是全局生效,那么您可以创建自定义ModelChoiceField
子类,在自定义ModelForm
中使用它,然后将相关的管理类设置为使用您的自定义表单。
以FK为例,介绍@Enrique使用的Person
模型:
class Invoice(models.Model):
person = models.ForeignKey(Person)
....
class InvoiceAdmin(admin.ModelAdmin):
form = MyInvoiceAdminForm
class MyInvoiceAdminForm(forms.ModelForm):
person = CustomModelChoiceField(queryset=Person.objects.all())
class Meta:
model = Invoice
class CustomModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return "%s %s" % (obj.first_name, obj.last_name)
答案 1 :(得分:47)
另一种方法(在更改查询集时很有用):
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['user'].queryset = User.objects.all()
self.fields['user'].label_from_instance = lambda obj: "%s %s" % (obj.last_name, obj.first_name)
'user'是您要覆盖的字段的名称。此解决方案为您提供了一个优势:您也可以覆盖查询集(例如,您想要User.objects.filter(username__startswith ='a'))
免责声明:在http://markmail.org/message/t6lp7iqnpzvlt6qp上找到并经过测试的解决方案。
答案 2 :(得分:10)
较新版本的django支持此功能,可以使用gettext进行翻译:
models.ForeignKey(ForeignStufg, verbose_name='your text')
答案 3 :(得分:9)
请参阅https://docs.djangoproject.com/en/1.3/ref/models/instances/#unicode
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
您必须定义要在模型的 unicode 方法中显示的内容(其中是ForeignKey)。
此致
答案 4 :(得分:4)
您也可以使用admin.ModelAdmin
从label_from_instance
实例直接完成此操作。例如:
class InvoiceAdmin(admin.ModelAdmin):
list_display = ['person', 'id']
def get_form(self, request, obj=None, **kwargs):
form = super(InvoiceAdmin, self).get_form(request, obj, **kwargs)
form.base_fields['person'].label_from_instance = lambda obj: "{} {}".format(obj.id, obj.first_name)
return form
admin.site.register(Invoice, InvoiceAdmin)
答案 5 :(得分:1)
第一个答案的替代方案:
class InvoiceAdmin(admin.ModelAdmin):
class CustomModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return "%s %s" % (obj.first_name, obj.last_name)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == 'person':
return self.CustomModelChoiceField(queryset=Person.objects)
return super(InvoiceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
答案 6 :(得分:0)
我刚发现您可以将查询集替换为另一个查询集,甚至删除查询集并将其替换为选项列表。我在change_view中这样做。
在这个例子中,我让父设置了返回值,然后从中获取特定字段并设置.choices:
def change_view(self, request, object_id, form_url='', extra_context=None):
#get the return value which includes the form
ret = super().change_view(request, object_id, form_url, extra_context=extra_context)
# let's populate some stuff
form = ret.context_data['adminform'].form
#replace queryset with choices so that we can specify the "n/a" option
form.fields['blurb_location'].choices = [(None, 'Subscriber\'s Location')] + list(models.Location.objects.filter(is_corporate=False).values_list('id', 'name').order_by('name'))
form.fields['blurb_location'].queryset = None
return ret
答案 7 :(得分:0)
在其他答案的基础上,这是处理ManyToManyField
的人的一个小例子。我们也可以直接在label_from_instance
中覆盖formfield_for_manytomany()
:
class MyAdmin(admin.ModelAdmin):
...
def formfield_for_manytomany(self, db_field, request, **kwargs):
formfield = super(MyAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)
# For example, we can add the instance id to the original string
formfield.label_from_instance = lambda instance: '{} (id={})'.format(instance.__str__(), instance.id)
...
我想这对formfield_for_foreignkey()
也适用。
从docs:
...
label_from_instance
。此方法将收到一个模型对象,并且 应该返回一个适合表示它的字符串。