【问题标题】:How to change ForeignKey display text in the Django Admin?如何在 Django Admin 中更改 ForeignKey 显示文本?
【发布时间】:2011-10-13 18:49:42
【问题描述】:

如何在选择ForeignKey 字段时更改<select> 字段中的显示文本?

我不仅需要显示ForeignKey 的名称,还需要显示其父级的名称。

【问题讨论】:

    标签: django django-admin


    【解决方案1】:

    如果您希望它仅在管理中生效,而不是全局生效,那么您可以创建一个自定义 ModelChoiceField 子类,在自定义 ModelForm 中使用它,然后设置相关的管理类以使用您的自定义表单。 使用具有 @Enrique 使用的 Person 模型的 ForeignKey 的示例:

    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)
    

    【讨论】:

      【解决方案2】:

      另一种方法(在更改查询集时很有用):

      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 2.1.9,但所选答案有效。
      【解决方案3】:

      较新版本的django支持这个,可以用gettext翻译:

      models.ForeignKey(ForeignStufg, verbose_name='your text')
      

      【讨论】:

      【解决方案4】:

      您也可以使用label_from_instance 直接从您的admin.ModelAdmin 实例完成此操作。例如:

      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 inst: "{} {}".format(inst.id, inst.first_name)
              return form
      
      
      admin.site.register(Invoice, InvoiceAdmin)
      

      【讨论】:

      • 这很好用。唯一的问题是,在使用管理员“+”选项添加值后,它仍然显示“field_name(id)”值。重新加载页面后,它显示正确。知道如何让它正确显示而无需重新加载?
      【解决方案5】:

      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 在哪里)。

      问候,

      【讨论】:

      • 我知道,但我想在其他地方的 admin 上只更改 1 个位置,不应该更改,因为这种方法对我不利。
      • @robos85:检查我的答案,了解您要查找的内容。您还应该更新您的问题。
      【解决方案6】:

      在其他答案的基础上,这里有一个小例子,供那些处理ManyToManyField 的人使用。

      我们可以直接在formfield_for_manytomany()中覆盖label_from_instance

      class MyAdmin(admin.ModelAdmin):
          def formfield_for_manytomany(self, db_field, request, **kwargs):
              formfield = super().formfield_for_manytomany(db_field, request, **kwargs)
              if db_field.name == 'person':
                  # For example, we can add the instance id to the original string
                  formfield.label_from_instance = lambda obj: f'{obj} ({obj.id})'
              return formfield
      

      这也适用于formfield_for_foreignkey()formfield_for_dbfield()

      来自ModelChoiceField docs

      将调用模型的__str__() 方法来生成对象的字符串表示形式,以用于字段的选择。要提供自定义表示,请继承 ModelChoiceField 并覆盖 label_from_instance。此方法将接收一个模型对象,并应返回一个适合表示它的字符串。

      【讨论】:

        【解决方案7】:

        第一个答案的替代方案:

        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)
        

        【讨论】:

          【解决方案8】:

          我刚刚发现您可以用另一个查询集替换查询集,甚至可以删除查询集并用选择列表替换它。我在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
          

          【讨论】:

            猜你喜欢
            • 2021-04-28
            • 1970-01-01
            • 2011-03-05
            • 2016-02-03
            • 2022-12-15
            • 2014-04-18
            • 2012-01-13
            • 1970-01-01
            • 2016-03-28
            相关资源
            最近更新 更多