假设我的披萨应用程序有Topping和Pizza课程,他们会在Django Admin中显示:
PizzaApp
-
Toppings >>>>>>>>>> Add / Change
Pizzas >>>>>>>>>> Add / Change
但我希望他们这样:
PizzaApp
-
Pizzas >>>>>>>>>> Add / Change
Toppings >>>>>>>>>> Add / Change
如何在admin.py中配置它?
答案 0 :(得分:29)
您可以尝试的解决方法是调整models.py,如下所示:
class Topping(models.Model):
.
.
.
class Meta:
verbose_name_plural = "2. Toppings"
class Pizza(models.Model):
.
.
.
class Meta:
verbose_name_plural = "1. Pizzas"
不确定它是否违反了django的最佳做法,但它有效(使用django trunk测试)。
祝你好运!PS:对不起,如果这个答案发布得太晚,但在未来的类似情况下可以帮助其他人。
答案 1 :(得分:18)
如果你想在10秒内解决这个问题,只需使用verbose_name_plural中的空格,例如:
class Topping(models.Model):
class Meta:
verbose_name_plural = " Toppings" # 2 spaces
class Pizza(models.Model):
class Meta:
verbose_name_plural = " Pizzas" # 1 space
当然,它不是优雅的,但在我们得到更好的解决方案之前可能会工作一段时间。
答案 2 :(得分:18)
由于这个Django snippet,我最终设法做到了,您只需要了解ADMIN_REORDER
设置:
ADMIN_REORDER = (
('app1', ('App1Model1', 'App1Model2', 'App1Model3')),
('app2', ('App2Model1', 'App2Model2')),
)
app1
不得以项目名称为前缀,即使用app1
代替mysite.app1
。
答案 3 :(得分:15)
现在有一个很好的Django包:
答案 4 :(得分:10)
这实际上涵盖在Part 2 of the Django Tutorial的最底层。
以下是相关部分:
自定义管理员索引页
在类似的说明中,您可能想要 定制的外观和感觉 Django管理员索引页。
默认情况下,它会显示所有应用 在已安装的INSTALLED_APPS中 在管理员申请中注册, 按字母顺序排列。你可能想要 做出重大改变 布局。毕竟,索引是 可能是最重要的一页 管理员,应该很容易 使用
要自定义的模板是 管理员/ index.html的。 (与之相同 以前的admin / base_site.html 部分 - 从默认值中复制它 目录到您的自定义模板 目录。)编辑文件,你就可以了 看到它使用一个名为的模板变量 app_list。该变量包含每个 安装了Django应用程序。而不是使用 那,你可以硬链接到链接 特定于对象的管理页面 你认为最好的方式。
答案 5 :(得分:6)
以下是Emmanuel使用的片段,更新了Django 1.8:
在templatetags / admin_reorder.py中:
from django import template
from django.conf import settings
from collections import OrderedDict
register = template.Library()
# from http://www.djangosnippets.org/snippets/1937/
def register_render_tag(renderer):
"""
Decorator that creates a template tag using the given renderer as the
render function for the template tag node - the render function takes two
arguments - the template context and the tag token
"""
def tag(parser, token):
class TagNode(template.Node):
def render(self, context):
return renderer(context, token)
return TagNode()
for copy_attr in ("__dict__", "__doc__", "__name__"):
setattr(tag, copy_attr, getattr(renderer, copy_attr))
return register.tag(tag)
@register_render_tag
def admin_reorder(context, token):
"""
Called in admin/base_site.html template override and applies custom ordering
of apps/models defined by settings.ADMIN_REORDER
"""
# sort key function - use index of item in order if exists, otherwise item
sort = lambda order, item: (order.index(item), "") if item in order else (
len(order), item)
if "app_list" in context:
# sort the app list
order = OrderedDict(settings.ADMIN_REORDER)
context["app_list"].sort(key=lambda app: sort(order.keys(),
app["app_url"].strip("/").split("/")[-1]))
for i, app in enumerate(context["app_list"]):
# sort the model list for each app
app_name = app["app_url"].strip("/").split("/")[-1]
if not app_name:
app_name = app["name"].lower()
model_order = [m.lower() for m in order.get(app_name, [])]
context["app_list"][i]["models"].sort(key=lambda model:
sort(model_order, model["admin_url"].strip("/").split("/")[-1]))
return ""
在settings.py中:
ADMIN_REORDER = (
('app1', ('App1Model1', 'App1Model2', 'App1Model3')),
('app2', ('App2Model1', 'App2Model2')),
)
(在此处插入您自己的应用名称。管理员会在列表末尾放置缺少的应用或模型,只要您在每个应用中列出至少两个模型。)
在您的base_site.html副本中:
{% extends "admin/base.html" %}
{% load i18n admin_reorder %}
{% block title %}{{ title }} | {% trans 'Django site admin' %}{% endblock %}
{% block branding %}
{% admin_reorder %}
<h1 id="site-name">{% trans 'Django administration' %}</h1>
{% endblock %}
{% block nav-global %}{% endblock %}
答案 6 :(得分:3)
2018年6月答复
此答案类似于Vasil's idea
我试图解决类似的问题,然后看到了这样的the fragment。
我根据此剪辑进行了一些修改。代码如下。
# myproject/setting.py
...
# set my ordering list
ADMIN_ORDERING = [
('pizza_app', [
'Pizzas',
'Toppings'
]),
]
# Creating a sort function
def get_app_list(self, request):
app_dict = self._build_app_dict(request)
for app_name, object_list in ADMIN_ORDERING:
app = app_dict[app_name]
app['models'].sort(key=lambda x: object_list.index(x['object_name']))
yield app
# Covering django.contrib.admin.AdminSite.get_app_list
from django.contrib import admin
admin.AdminSite.get_app_list = get_app_list
...
请注意,此排序功能中使用的排序列表包含系统中所有应用及其模块的排序。如果不需要,请根据自己的需要设计排序功能。
在Django 2.0上效果很好
答案 7 :(得分:2)
我把它添加到Django的trac:
答案 8 :(得分:2)
答案 9 :(得分:0)
我的解决方案是制作django.contrib.admin.sites.AdminSite和django.contrib.admin.options.ModelAdmin的子类。
我这样做了所以我可以为每个应用显示更具描述性的标题,并在每个应用中订购模型的外观。所以我在settings.py中有一个dict,它将app_labels映射到描述性名称和它们应该出现的顺序,模型按照我在每个ModelAdmin中提供的序数字段进行排序,当我向管理站点注册时。
虽然在文档中鼓励创建自己的AdminSite和ModelAdmin子类,但我的解决方案最终看起来像是一个丑陋的黑客。
答案 10 :(得分:0)
这只是一个黑暗中的疯狂刺,但你有可能调用admin.site.register(&lt; Model class&gt;,&lt; ModelAdmin class&gt;)的顺序可以确定显示顺序?实际上,我怀疑这会有效,因为我相信Django维护着一个模型的注册表 - &gt; ModelAdmin对象实现为标准Python字典,不保持迭代排序。
如果这不符合您的要求,您可以随时使用django / contrib / admin中的源代码。如果需要维护迭代顺序,可以将AdminSite类(在admin / sites.py中)中的_registry对象替换为维护键的插入顺序的UserDict或DictMixin。 (但是请大家接受这个建议,因为我自己从未做过这些改变,而且我只是在猜测Django如何迭代ModelAdmin对象的集合。我认为django / contrib /admin/sites.py是查找此代码的地方,特别是AdminSite类和register()以及index()方法就是你想要的。)
显然,最好的方法是在您自己的/admin.py模块中指定一个简单的选项。我确信这是你希望得到的那种答案。不过,我不确定这些选项是否存在。
答案 11 :(得分:0)
这是一个为您提供更多灵活性的版本,即:
apps.py
并检查class Config(AppConfi):
的name属性,或者在不存在的情况下,使用项目中应用程序的目录。将此代码添加到settings.py
文件中的某个位置:
# ======[Setting the order in which the apps/modules show up listed on Admin]========
# set my ordering list
ADMIN_ORDERING = [
('crm', '*'),
('property', '*'),
]
# Creating a sort function
def get_app_list(self, request):
"""
Returns a sorted list of all the installed apps that have been
registered in this site.
Allows for:
ADMIN_ORDERING = [
('app_1', [
'module_1',
'module_2'
]),
('app_2', '*'),
]
"""
app_dict = self._build_app_dict(request)
# Let's start by sorting the apps alphabetically on a list:
app_list = sorted(app_dict.values(), key=lambda x: x['name'].lower())
# Sorting the models alphabetically within each app.
for app in app_list:
if app['app_label'] in [el[0] for el in ADMIN_ORDERING]:
app_list.remove(app)
else:
app['models'].sort(key=lambda x: x['name'])
# Now we order the app list in our defined way in ADMIN_ORDERING (which could be a subset of all apps).
my_ordered_apps = []
if app_dict:
for app_name, object_list in ADMIN_ORDERING:
app = app_dict[app_name]
if object_list == '*':
app['models'].sort(key=lambda x: x['name'])
else:
app['models'].sort(key=lambda x: object_list.index(x['object_name']))
my_ordered_apps.append(app)
# Now we combine and arrange the 2 lists together
my_ordered_apps.extend(app_list)
return my_ordered_apps
# Covering django.contrib.admin.AdminSite.get_app_list
from django.contrib import admin
admin.AdminSite.get_app_list = get_app_list
# =========================================
这无非是覆盖Django在文件python2.7 / site-packages / django / contrib / admin / sites.py中定义的功能。
get_app_list
的{{1}}方法会生成项目上所有应用程序的数据结构,包括Django的auth应用程序,例如:
class AdminSite(object):
答案 12 :(得分:0)
将lib\site-packages\django\contrib\admin\templates\admin\index.html
模板复制到project1\templates\admin\
目录,其中project1
是项目的名称。
在复制的文件project1\templates\admin\index.html
中,替换行:
{% block content %}
...
{% endblock %}
具有:
{% block content %}
<div id="content-main">
{% if app_list %}
<div class="module">
<table>
<caption>App 1</caption>
<tr> <th> <a href="/admin/app1/model1/">Model 1</a> </th> <td>Description of model 1</td> </tr>
<tr> <th> <a href="/admin/app1/model2/">Model 2</a> </th> <td>Description of model 1</td> </tr>
<tr> <th> <a href="..." >...</a> </th> <td>...</td> </tr>
</table>
</div>
<div class="module">
<table>
<caption>Authentication and authorization</caption>
<tr> <th> <a href="/admin/auth/user/" >Users</a> </th> <td>List of users</td> </tr>
<tr> <th> <a href="/admin/auth/group/" >Groups</a> </th> <td>List of users' groups</td> </tr>
</table>
</div>
{% else %}
<p>{% trans "You don't have permission to view or edit anything." %}</p>
{% endif %}
</div>
{% endblock %}
其中:
app1
是带有模型的应用程序的名称,modeli
是app1
中第i个模型的名称。如果您在项目中使用模型定义了多个应用程序,则只需在上述index.html
文件中添加另一个表即可。
由于我们更改了模板,因此可以自由更改其HTML代码。例如,我们可以添加上面显示的模型描述。您还可以恢复 Add 和 Change 链接-我删除了它们,因为我认为它们是多余的。
答案是Dave Kasper's answer中解决方案的实践证明。
答案 13 :(得分:0)
custom_admin.py
from django.contrib.admin import AdminSite
class CustomAdminSite(AdminSite):
def get_urls(self):
urls = super(MyAdminSite, self).get_urls()
return urls
def get_app_list(self, request):
app_dict = self._build_app_dict(request)
ordered_app_list = []
if app_dict:
# TODO: change this dict
admin_ordering = {
'app1': ('Model1', 'Model2'),
'app2': ('Model7', 'Model4'),
'app3': ('Model3',),
}
ordered_app_list = []
for app_key in admin_ordering:
app = app_dict[app_key]
app_ordered_models = []
for model_name in admin_ordering[app_key]:
for model in app_dict[app_key]['models']:
if model['object_name'] == model_name:
app_ordered_models.append(model)
break
app['models'] = app_ordered_models
ordered_app_list.append(app)
return ordered_app_list
admin_site = CustomAdminSite()
urls.py
from custom_admin import admin_site
urlpatterns = [
path('admin/', admin_site.urls),
]
答案 14 :(得分:0)
将以下代码添加到您的 settings.py:
def get_app_list(self, request):
"""
Return a sorted list of all the installed apps that have been
registered on this site.
"""
ordering = {
# for superuser
'Group': 1,
'User': 2,
# fist app
'TopMessage': 101,
'Slider': 102,
'ProductCategory': 103,
'Product': 104,
'ProductPicture': 105,
# 2nd app
'ProductReview': 201,
'Promotion': 202,
'BestSeller': 203,
}
app_dict = self._build_app_dict(request)
app_list = sorted(app_dict.values(), key=lambda x: x['name'].lower())
for app in app_list:
app['models'].sort(key=lambda x: ordering[x['object_name']])
return app_list
admin.AdminSite.get_app_list = get_app_list
并更改排序字典以匹配您的应用和模型。就是这样。
我的解决方案的好处是,如果用户是超级用户,它将显示“身份验证”模型。
答案 15 :(得分:0)
默认情况下,Django 按字母顺序对 admin 中的模型进行排序。所以Event admin中模型的顺序是Epic, EventHero, EventVillain, Event
相反,您希望订单是
用于呈现管理索引页面的模板是 admin/index.html
,视图函数是 ModelAdmin.index
。
def index(self, request, extra_context=None):
"""
Display the main admin index page, which lists all of the installed
apps that have been registered in this site.
"""
app_list = self.get_app_list(request)
context = {
**self.each_context(request),
'title': self.index_title,
'app_list': app_list,
**(extra_context or {}),
}
request.current_app = self.name
return TemplateResponse(request, self.index_template or
'admin/index.html', context)
方法get_app_list
,设置模型的顺序。:
def get_app_list(self, request):
"""
Return a sorted list of all the installed apps that have been
registered in this site.
"""
app_dict = self._build_app_dict(request)
# Sort the apps alphabetically.
app_list = sorted(app_dict.values(), key=lambda x: x['name'].lower())
# Sort the models alphabetically within each app.
for app in app_list:
app['models'].sort(key=lambda x: x['name'])
return app_list
所以要设置我们覆盖 get_app_list
的顺序:
class EventAdminSite(AdminSite):
def get_app_list(self, request):
"""
Return a sorted list of all the installed apps that have been
registered in this site.
"""
ordering = {
"Event heros": 1,
"Event villains": 2,
"Epics": 3,
"Events": 4
}
app_dict = self._build_app_dict(request)
# a.sort(key=lambda x: b.index(x[0]))
# Sort the apps alphabetically.
app_list = sorted(app_dict.values(), key=lambda x: x['name'].lower())
# Sort the models alphabetically within each app.
for app in app_list:
app['models'].sort(key=lambda x: ordering[x['name']])
return app_list
代码 app['models'].sort(key=lambda x: ordering[x['name']])
设置固定顺序。您的应用现在看起来像这样。
答案 16 :(得分:0)
在 Settings.py
文件中设置应用程序/模块在管理中列出的显示顺序
设置我的订购清单
ADMIN_ORDERING = [
('Your_App1', '*'),
('Your_App2', '*'),
]
在 ADMIN_ORDERING 下面创建一个排序函数
def get_app_list(self, request):
"""
You Can Set Manually Ordering For Your Apps And Models
ADMIN_ORDERING = [
('Your_App1', [
'module_1',
'module_2'
]),
('Your_App2', '*'),
]
"""
app_dict = self._build_app_dict(request)
# Let's start by sorting the apps alphabetically on a list:
app_list = sorted(app_dict.values(), key=lambda x: x['name'].lower())
# Sorting the models alphabetically within each app.
for app in app_list:
if app['app_label'] in [el[0] for el in ADMIN_ORDERING]:
app_list.remove(app)
else:
app['models'].sort(key=lambda x: x['name'])
# Now we order the app list in our defined way in ADMIN_ORDERING (which could be a subset of all apps).
my_ordered_apps = []
if app_dict:
for app_name, object_list in ADMIN_ORDERING:
app = app_dict[app_name]
if object_list == '*':
app['models'].sort(key=lambda x: x['name'])
else:
app['models'].sort(key=lambda x: object_list.index(x['object_name']))
my_ordered_apps.append(app)
# Now we combine and arrange the 2 lists together
my_ordered_apps.extend(app_list)
return my_ordered_apps
# Covering django.contrib.admin.AdminSite.get_app_list
from django.contrib import admin
admin.AdminSite.get_app_list = get_app_list