2012-01-17 46 views
10

定製app_list我想定義Django的管理索引頁使用自定義的應用程序列表,因爲我想在一個特定的順序顯示,而不是默認的按字母順序排列的應用。通過各種SO帖子瀏覽,似乎無法在任何明顯的地方(例如admin.py,models.py)聲明所需的申請順序。現在定義在Django管理索引頁

,我可以看到,Django管理的index.html文件包含以下語句:

{% for app in app_list %} 
    # do stuff with the app object 

所以我想改變這種使用所謂的,比如說一個自定義列表對象,my_app_list。在蟒蛇我會做這個大意如下:

from django.db.models import get_app 
my_app_list = [get_app('myapp1'), get_app('myapp2'), ..., get_app('django.contrib.auth')] 
for app in my_app_list 
    ... 

我的問題則是,如何我的代碼的前兩行相當於上述進入我的本地index.html文件的副本?

,或者,什麼Python源文件,我應該插入的行成,使得可變my_app_list是index.html的範圍內使用。

在此先感謝。

菲爾

+0

這工作正常我=> http://djangosnippets.org/snippets/2613/ – Serafeim 2012-07-02 17:42:54

+0

@Serafeim感謝你。一旦我解決了由於升級服務器而導致出現的各種32位和64位python/django問題,我會放手一搏! – Phil 2012-07-12 16:00:00

回答

8

小類django.contrib.admin.site.AdminSite()。重寫.index()方法,做這樣的事情:

class MyAdminSite(django.contrib.admin.site.AdminSite): 
    def index(self, request, extra_context=None): 
     if extra_context is None: 
      extra_context = {} 
     extra_context["app_list"] = get_app_list_in_custom_order() 
     return super(MyAdminSite, self).index(request, extra_context) 

實例化這個子類的實例與my_admin_site = MyAdminSite(),附上你的模型,它(一般使用my_admin_site.register()),並將其連接到URL配置;應該這樣做。

(我沒有試過,我對我的AdminSite源的閱讀基礎這一點。)

+0

感謝您的建議 - 尚未有機會對其進行測試。我將有報告回來。看起來像一個可行的選擇,但。 – Phil 2012-01-19 15:43:48

+1

您建議的代碼片段很有意義,但是我不清楚它應該駐留在哪裏。我開始將它放在我的一個應用程序的admin.py模塊中,但是意識到這是沒有意義的,因爲它是一個站點範圍的代碼片段,並且不是特定於特定應用程序的。此外,我不確定如何或爲什麼要修改URLconf以使用此代碼,因爲我沒有更改任何網址。 – Phil 2012-01-20 12:48:17

+0

終於輪到嘗試這種方法。不幸的是我無法讓它工作。首先,get_app()函數返回一個模塊對象,而不是index.html預期的字典對象(我應該閱讀源代碼!)。其次,通過實例化AdminSite的子類,然後根據它註冊自己的應用程序,似乎您將失去對默認管理站點對象註冊的其他應用程序(如Auth)的可見性。因此,我無法找到一種方法來配置默認應用程序和您自己的應用程序一起出現在管理索引視圖中。 – Phil 2012-02-15 14:11:40

0

做什麼@AdminKG說index.html文件複製到admin目錄,你需要的根後在setting.py上聲明的templates目錄內創建。

如果你有一個明確的app_list排序邏輯,你可以在你的AdminSite的子類的.index()方法中實現它。否則,您需要在index.html上硬編碼應用程序列表。

要訪問東西在模板中只是有它在你的背景下,這樣的事情:

def index(self, request, extra_context=None): 
    context = { 
     'app1':get_app('myappname'), 
     'app2': get_app('mysecondappname'), 
     # ... 
    } 
    context.update(extra_context or {}) 
    context_instance = template.RequestContext(request, current_app=self.name) 
    return render_to_response(self.index_template or 'admin/terminal_index.html', context, 
     context_instance=context_instance 
    ) 

現在應用程式對象可對使用index.htm

+0

「否則,您將需要在index.html上對應用列表進行硬編碼。」的確,這就是我的問題的本質。在我的本地index.html文件中,如何獲取應用程序對象的句柄,因爲我只知道它的名稱。我可以在Python代碼中使用get_app('myappname')函數。 django的模板語言中是否有等價的函數?也許我在吠叫完全錯誤的樹! – Phil 2012-01-19 15:37:00

+0

@Phil我更新了答案 – tikider 2012-01-19 22:04:42

2

如果你不介意使用的django.contrib.admin.site.AdminSite()一個子類,如預期的情況下,當您需要customize your admin site,我認爲這是一個可行的思路改寫「指數」,並在派生類「app_index」的方法。您可以使用兩個詞典進行自定義排序,這兩個詞典在settings.py中存儲應用程序聲明順序以及模型的註冊順序。 然後重寫原始AdminSite().index()app_index()的代碼,儘管'name'通過本領域中添加和app_list爲了定製次序字段('order')。這是代碼,但不包括app_index(),類似於index()功能:

class MyAdminSite(AdminSite): 

    def __init__(self, name='admin', app_name='admin'): 
     super(MyAdminSite, self).__init__(name, app_name) 

     # Model's registration ordering. It's not necessary to 
     # categorize by app. 
     self._registry_ord = {} 

     # App ordering determined by declaration 
     self._app_ord = { 'auth' : 0 } 
     app_position = 1 
     for app in settings.INSTALLED_APPS: 
      self._app_ord[app] = app_position 
      app_position += 1 

    def register(self, model_or_iterable, admin_class=None, **options): 
     super(MyAdminSite, self).register(model_or_iterable, admin_class, **options) 

     if isinstance(model_or_iterable, ModelBase): 
      model_or_iterable = [model_or_iterable] 
     for model in model_or_iterable: 
      if model in self._registry: 
       if self._registry_ord: 
        self._registry_ord[model._meta.object_name] = max(self._registry_ord.values()) + 1 
       else: 
        self._registry_ord[model._meta.object_name] = 1 

    @never_cache 
    def index(self, request, extra_context=None): 
     """ 
     Displays the main admin index page, which lists all of the installed 
     apps that have been registered in this site. 
     """ 
     app_dict = {} 
     user = request.user 
     for model, model_admin in self._registry.items(): 
      app_label = model._meta.app_label 
      has_module_perms = user.has_module_perms(app_label) 

      if has_module_perms: 
       perms = model_admin.get_model_perms(request) 

       # Check whether user has any perm for this module. 
       # If so, add the module to the model_list. 
       if True in perms.values(): 
        info = (app_label, model._meta.module_name) 
        model_dict = { 
         'name': capfirst(model._meta.verbose_name_plural), 
         'perms': perms, 
         'order': self._registry_ord[model._meta.object_name] 
        } 
        if perms.get('change', False): 
         try: 
          model_dict['admin_url'] = reverse('admin:%s_%s_changelist' % info, current_app=self.name) 
         except NoReverseMatch: 
          pass 
        if perms.get('add', False): 
         try: 
          model_dict['add_url'] = reverse('admin:%s_%s_add' % info, current_app=self.name) 
         except NoReverseMatch: 
          pass 
        if app_label in app_dict: 
         app_dict[app_label]['models'].append(model_dict) 
        else: 
         app_dict[app_label] = { 
          'name': app_label.title(), 
          'app_url': reverse('admin:app_list', kwargs={'app_label': app_label}, current_app=self.name), 
          'has_module_perms': has_module_perms, 
          'models': [model_dict], 
          'order': self._app_ord[app_label], 
         } 

     # Sort the apps alphabetically. 
     app_list = app_dict.values() 
     app_list.sort(key=lambda x: x['order']) 

     # Sort the models alphabetically within each app. 
     for app in app_list: 
      app['models'].sort(key=lambda x: x['order']) 

     context = { 
      'title': _('Site administration'), 
      'app_list': app_list, 
     } 
     context.update(extra_context or {}) 
     return TemplateResponse(request, [ 
      self.index_template or 'admin/index.html', 
     ], context, current_app=self.name) 

如果使用自定義AdminSite並且要包含你可能需要這個,地方在你的代碼驗證模型(我在一個特定使它應用extend user information

from django.contrib.auth.models import User, Group 
from myproject import admin 

admin.site.register(User) 
admin.site.register(Group) 
0

既然你所關心的順序,你可以找到我的解決方案有幫助
基本上,我創建了一個過濾器,其移動app_list的所需元素的開頭

@register.filter 
def put_it_first(value, arg): 
    '''The filter shifts specified items in app_list to the top, 
    the syntax is: LIST_TO_PROCESS|put_it_first:"1st_item[;2nd_item...]" 
    ''' 
    def _cust_sort(x): 
     try: 
      return arg.index(x['name'].lower()) 
     except ValueError: 
      return dist 
    arg = arg.split(';') 
    arg = map(unicode.lower, arg) 
    dist = len(arg) + 1 
    value.sort(key=_cust_sort) 
    return value 

但是,如果您需要刪除一些元素,你可以使用:

@register.filter 
def remove_some(value, arg): 
    '''The filter removes specified items from app_list, 
    the syntax is: LIST_TO_PROCESS|remove_some:"1st_item[;2nd_item...]" 
    ''' 
    arg = arg.split(';') 
    arg = map(unicode.lower, arg) 
    return [v for v in value if v['name'].lower() not in arg] 

過濾器可以鏈接,這樣你就可以在同一時間同時使用。
過濾功能的寫法並不會讓他們加速惡魔,但是這個模板並沒有經常被定義。