Администратор Django - изменить отображаемый текст ForeignKey - PullRequest
37 голосов
/ 27 июля 2011

Как я могу изменить отображаемый текст в select при выборе поля как ForeignKey?Мне нужно отобразить не только имя FK, но и имя его родителя.

Кто-нибудь может дать подсказку?

Ответы [ 8 ]

51 голосов
/ 28 июля 2011

Ну, если вы хотите, чтобы он вступил в силу только в admin, а не в глобальном масштабе, то вы можете создать собственный подкласс ModelChoiceField, использовать его в пользовательском ModelForm, а затем настроить соответствующий класс admin для использования своей настроенной формы , Возьмем пример с 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)
47 голосов
/ 18 октября 2011

Другой способ сделать это (полезно при изменении набора запросов):

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 и проверено.

10 голосов
/ 07 февраля 2014

Новые версии django поддерживают это, что можно перевести с помощью gettext:

models.ForeignKey(ForeignStufg, verbose_name='your text')
9 голосов
/ 27 июля 2011

См. 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).

С уважением,

5 голосов
/ 17 июля 2018

Вы также можете выполнить это прямо из своего экземпляра 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)
1 голос
/ 30 сентября 2016

Альтернатива первому ответу:

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)
0 голосов
/ 03 декабря 2018

Основываясь на других ответах, вот небольшой пример для тех, кто имеет дело с 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.Этот метод получит объект модели и должен вернуть строку, подходящую для его представления.

0 голосов
/ 30 марта 2014

Я только что обнаружил, что вы можете заменить набор запросов другим набором запросов или даже удалить набор запросов и заменить его списком выбора. Я делаю это в 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
...