我有两个用外键链接的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'.
你知道怎么做吗?
更多背景信息:
答案 0 :(得分: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>
› <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ opts.app_config.verbose_name }}</a>
› {% if has_change_permission %}<a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst }}</a>{% else %}{{ opts.verbose_name_plural|capfirst }}{% endif %}
› {% 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管理员的模板,以便能够像默认模板显示的那样显示我的书和作者。所以我的用户不会受到这种观点的干扰。
如果您找到了更好的方法,请告诉我们! :)
答案 1 :(得分:0)
你不能这样做。内联只在一个方向上有意义。
这样做的方法是定义作者字段的显示,以便它自动为您提供足够的信息;例如,通过定义__str__
方法。
答案 2 :(得分:0)
有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()
自定义字段的显示方式。
如果这样做,就可以省去覆盖模板的麻烦。
答案 3 :(得分:-1)
正如错误所说:
class 'my_app.admin.AuthorInline'>: (admin.E202) 'my_app.Author' has no ForeignKey to 'my_app.Book'.
您需要在参考图书表的作者表格中添加外键。
第一个有效,因为你在Book中有一个引用作者的外键。