Как я могу изменить отображаемый текст при выборе при выборе поля, которое является ForeignKey? Мне нужно отобразить не только имя FK, но и имя его родителя.
Кто-нибудь может дать ключ?
Как я могу изменить отображаемый текст при выборе при выборе поля, которое является ForeignKey? Мне нужно отобразить не только имя FK, но и имя его родителя.
Кто-нибудь может дать ключ?
Хорошо, если вы хотите, чтобы он вступил в силу только в admin, а не во всем мире, тогда вы можете создать пользовательский подкласс ModelChoiceField
, использовать его в пользовательском ModelForm
, а затем установить соответствующий класс администратора для использования вашей индивидуальной формы,
Пример, который имеет FK для модели Person
, используемой @Enrique:
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)
Другой способ сделать это (полезно при изменении набора запросов):
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 и протестировано.
Более новые версии django поддерживают это, которое можно перевести с помощью gettext:
models.ForeignKey(ForeignStufg, verbose_name='your text')
См. 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).
Привет,
Альтернатива первому ответу:
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)
Вы также можете сделать это прямо из вашего 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)
Я просто обнаружил, что вы можете заменить набор запросов другим набором запросов или даже удалить набор запросов и заменить его списком выбора. Я делаю это в 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 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\ Location')] + list(models.Location.objects.filter(is_corporate=False).values_list('id', 'name').order_by('name'))
form.fields['blurb_location'].queryset = None
return ret
Основываясь на других ответах, вот небольшой пример для тех, кто имеет дело с 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()
.
Из документов:
...
label_from_instance
. Этот метод получит модельный объект и должен вернуть строку, подходящую для ее представления.