Python 如何从带有外键的模型角度在Django admin中显示相关对象?

Python 如何从带有外键的模型角度在Django admin中显示相关对象?,python,django,django-admin,Python,Django,Django Admin,我用外键连接了两个Django模型: class Author(models.Model): ... class Book(models.Model): author = models.ForeignKey(Author) 请考虑下面的管理示例(我想做相反的事情): 通过这个例子,我们可以在管理员界面中看到所有作者,以及每个作者的书籍 现在,我想用另一种方式来解释它。在管理中为每本书设置en条目,并在书的详细信息上显示作者信息(可只读)。我尝试了下面的解决方案,但显然不起作用

我用外键连接了两个Django模型:

class Author(models.Model):
    ...

class Book(models.Model):
    author = models.ForeignKey(Author)

请考虑下面的管理示例(我想做相反的事情):

通过这个例子,我们可以在管理员界面中看到所有作者,以及每个作者的书籍

现在,我想用另一种方式来解释它。在管理中为每本书设置en条目,并在书的详细信息上显示作者信息(可只读)。我尝试了下面的解决方案,但显然不起作用:

from django.contrib import admin
from my_app.models import Author, Book

class AuthorInline(admin.TabularInline):
    model = Author

class BookAdmin(admin.ModelAdmin):
    inlines = [
        AuthorInline,
    ]

admin.site.register(Book, BookAdmin)
Django引发了一个错误:

:(admin.E202)“我的应用程序作者”没有“我的应用程序书”的外键。

你知道怎么做吗

更多背景:

  • Django 1.11
  • 我想将书和作者显示为完全只读,因此书的外键不会更改(至少不会从管理员处更改)
    • 正如错误所说:

      class 'my_app.admin.AuthorInline'>: (admin.E202) 'my_app.Author' has no ForeignKey to 'my_app.Book'.
      
      您需要在作者表中添加外键,该参考书籍


      第一个是有效的,因为书中有一个引用作者的外键。

      你不能这样做。内线仅在一个方向上有意义


      这样做的方法是定义author字段的显示,以便它自动为您提供足够的信息;例如,通过定义
      \uu str\uu
      方法。

      在这里,我的解决方案可能不是最好的,但它很有效!:)

      这个想法是改变模板,从而能够以我想要的方式显示它

      admin.py:

      class BookAdmin(admin.ModelAdmin):
          ...
          change_form_template = 'admin/book_details.html'
      
          def change_view(self, request, object_id, form_url='', extra_context=None):
              extra_context = extra_context or {}
              extra_context['book'] = Book.objects.get(id=object_id)
              extra_context['author'] = extra_context['book'].author
      
              return super().change_view(request, object_id, form_url, extra_context=extra_context)
      
      admin.site.register(Book, BookAdmin)
      
      对于模板,我只是复制/通过

      管理员/book_details.html:

      {% extends "admin/base_site.html" %}
      {% load i18n admin_urls static admin_modify %}
      
      
      {% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
      
      {% block coltype %}colM{% endblock %}
      
      {% block breadcrumbs %}
      <div class="breadcrumbs">
      <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
      &rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
      &rsaquo; {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
      &rsaquo; {% if add %}{% blocktrans with name=opts.verbose_name %}Add {{ name }}{% endblocktrans %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
      </div>
      {% endblock %}
      
      
      {% block content %}
      
      # Display here want you want !
      
      {% endblock %}
      
      {%extends“admin/base\u site.html”%}
      {%load i18n admin\u URL静态admin\u modify%}
      {%block extrastyle%}{{block.super}{%endblock%}
      {%block coltype%}colM{%endblock%}
      {%block breadcrumbs%}
      &rsaquo;
      &rsaquo;{%if拥有{u change_permission%}{%else%}{{opts.verbose_name_复数{124; capfirst}}{%endif%}
      &rsaquo;{%if add%}{%blocktrans with name=opts.verbose_name%}add{{name}{%endblocktrans%}{%else%}{{{original | truncatewords:“18”}{%endif%}
      {%endblock%}
      {%block content%}
      #在这里展示你想要的!
      {%endblock%}
      
      我查看了Django admin的模板,以便能够以与默认模板相同的方式显示我的书和作者。所以我的用户不会被这个视图打断


      如果你找到更好的方法,请告诉我!:)

      ModelAdmin.readonly\u字段
      可以在ModelAdmin本身或模型上调用,并在添加/更改表单上显示它们。()

      如果您想在管理员的图书更改表上显示作者姓名,您可以这样做:

      class BookAdmin(admin.ModelAdmin):
      只读_字段=['get_author_name']
      [...]
      def get_作者姓名(自我、书籍):
      返回book.author.name
      
      所有只读字段将显示在窗体的常规字段下。 您还可以通过修改
      ModelForm.get\u fields()
      自定义字段的显示方式


      如果您这样做,您就省去了覆盖模板的麻烦。

      为了给您一个提示,我认为您需要指定关系的backref属性,这样继承就可以双向识别。恐怕我不确定语法,尤其是Django 1.11,但希望这能给你一个线索。是的,我使用了“related_name”属性,这样它可以从关系的两侧使用:)是的,但在作者模型上使用FK没有意义,作者可以出版几本书。我认为最好在两者之间的关系中添加一个backref,以便您可以从各自的模型中访问每一本书。您始终可以添加一个类似于模型的关联对象。我想知道在这种情况下是否有内联以外的内容,但似乎没有:(事实上,我有太多关于我作者模型的信息,不能只显示str解决方案,甚至可以通过可调用项来显示。好吧,这是可以做到的。但不是那么容易。这是它的主要部分。希望完成。我从我正在做的一个项目中计算出来。是的,没有文档,但至少向您展示了获取外键作为内联键所要经历的困难。)表单(当然,您可以将其设置为只读)。
      {% extends "admin/base_site.html" %}
      {% load i18n admin_urls static admin_modify %}
      
      
      {% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
      
      {% block coltype %}colM{% endblock %}
      
      {% block breadcrumbs %}
      <div class="breadcrumbs">
      <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
      &rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
      &rsaquo; {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
      &rsaquo; {% if add %}{% blocktrans with name=opts.verbose_name %}Add {{ name }}{% endblocktrans %}{% else %}{{ original|truncatewords:"18" }}{% endif %}
      </div>
      {% endblock %}
      
      
      {% block content %}
      
      # Display here want you want !
      
      {% endblock %}