【问题标题】:How show related object in Django admin from the model with a foreign key point of view?如何从具有外键角度的模型中显示 Django admin 中的相关对象?
【发布时间】:2017-11-26 20:26:58
【问题描述】:

我有两个通过外键链接的 Django 模型:

class Author(models.Model):
    ...

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

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

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

class BookInline(admin.TabularInline):
    model = Book

class AuthorAdmin(admin.ModelAdmin):
    inlines = [
        BookInline,
    ]

admin.site.register(Author, AuthorAdmin)

通过这个示例,我们可以在管理员中查看所有作者,并为每个作者查看他们的书籍。

现在,我想反其道而行之。在管理中对每本书都有一个条目,并在书籍详细信息上显示作者信息(它可以是只读的)。我尝试了以下解决方案,但显然它不起作用:

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 报错:

<class 'my_app.admin.AuthorInline'>: (admin.E202) 'my_app.Author' has no ForeignKey to 'my_app.Book'.

你知道怎么做吗?

更多背景:

  • Django 1.11
  • 我想将 Book 和 Author 显示为完全只读,因此不会更改 Book 的外键(至少不会来自管理员)

【问题讨论】:

  • 给你一个提示,我认为你需要指定关系的 backref 属性,以便以两种方式识别继承。恐怕我不确定语法,尤其是 Django 1.11,但希望能给你一个线索。
  • 是的,我使用“related_name”属性,所以它可以从关系的双方使用:)

标签: python django django-admin


【解决方案1】:

正如错误所说:

class 'my_app.admin.AuthorInline'>: (admin.E202) 'my_app.Author' has no ForeignKey to 'my_app.Book'.

您需要在references Book表的Author表中添加外键

第一个有效,因为您将在 Book 中有一个引用 Author 的外键。

【讨论】:

  • 是的,但是在作者模型上有一个 FK 是没有意义的,一个作者可以出版几本书。
  • 我认为最好在两者之间的关系中添加一个backref,以便您可以从各自的模型中访问每个。
  • 您可以随时添加模型的关联对象类型。
【解决方案2】:

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

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

【讨论】:

  • 我想知道在这种情况下是否还有除 Inline 之外的其他内容,但似乎没有b> 解决方案甚至通过可调用对象显示。
  • 嗯,它可以完成。但没那么容易。这是它的gist。希望圆满。我是从我正在做的一个项目中考虑出来的。是的,没有文档,但至少向您展示了将外键作为内联表单获取的过程(当然,您可以将其设为只读)。
【解决方案3】:

这是我的解决方案,也许不是最好的,但它有效! :)

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

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)

对于模板,我只是复制/粘贴了template change_form.html from the admin

管理员/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 %}

我查看了 Django 管理员的模板,以便能够以与默认模板显示它们相同的方式显示我的书和作者。所以我的用户不会被这个视图打断。

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

【讨论】:

    【解决方案4】:

    ModelAdmin.readonly_fields 可以在 ModelAdmin 本身或模型上获取可调用对象,并将它们显示在添加/更改表单上。 (docs)

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

    class BookAdmin(admin.ModelAdmin):
        readonly_fields = ['get_author_name']
        [...]
    
        def get_author_name(self, book):
            return book.author.name
    

    所有只读字段都将显示在表单的常规字段下方。 您还可以通过修改ModelForm.get_fields()来自定义字段的显示方式。

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

    【讨论】:

      猜你喜欢
      • 2021-02-07
      • 2019-01-21
      • 1970-01-01
      • 1970-01-01
      • 2022-11-27
      • 2020-08-24
      • 1970-01-01
      • 2013-02-26
      • 2023-03-03
      相关资源
      最近更新 更多