2012-01-17 31 views
10

Tôi muốn xác định danh sách ứng dụng tùy chỉnh để sử dụng trong trang chỉ mục quản trị của django vì tôi muốn các ứng dụng được hiển thị theo thứ tự cụ thể, chứ không phải thứ tự chữ cái mặc định. Trawling thông qua các bài viết SO khác nhau, nó sẽ xuất hiện mà nó chưa thể tuyên bố thứ tự ứng dụng mong muốn ở bất kỳ nơi nào rõ ràng (ví dụ: admin.py, models.py).Xác định một app_list tùy chỉnh trong trang chỉ mục quản trị django

Bây giờ, tôi có thể thấy rằng tập tin index.html django của admin chứa các tuyên bố sau:

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

Vì vậy, tôi muốn thay đổi điều này để sử dụng một đối tượng danh sách tùy chỉnh được gọi, nói rằng, my_app_list. Trong python, tôi sẽ làm điều này theo các dòng sau:

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 
    ... 

Câu hỏi của tôi là, làm cách nào để mã tương đương với 2 dòng đầu tiên trên bản sao cục bộ của tệp index.html?

Hoặc, cách khác, tệp nguồn python nào tôi nên chèn những dòng đó vào để biến my_app_list có sẵn trong index.html.

Xin cảm ơn trước.

Phil

+0

Điều này làm việc tốt cho tôi => http://djangosnippets.org/snippets/2613/ – Serafeim

+0

@Serafeim Cảm ơn vì điều này. Tôi sẽ cung cấp cho nó một đi một khi tôi đã giải quyết khác nhau 32-bit vs 64-bit python/django vấn đề đã cắt lên như là một kết quả của máy chủ của chúng tôi đang được nâng cấp! – Phil

Trả lời

8

Phân lớp django.contrib.admin.site.AdminSite(). Ghi đè lên các phương pháp .index(), và làm điều gì đó như thế này:

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) 

Khởi tạo một thể hiện của lớp con này với my_admin_site = MyAdminSite(), đính kèm mô hình của bạn với nó (bằng cách sử dụng thông thường my_admin_site.register()), và đính kèm nó vào URLconf; nên làm vậy.

(Tôi đã không cố gắng này, tôi dựa trên việc đọc của tôi về nguồn AdminSite.)

+0

Cảm ơn đề xuất này - chưa có cơ hội thử nghiệm nó. Sẽ báo cáo lại khi tôi có. Hình như là một lựa chọn khả thi. – Phil

+1

đoạn mã bạn đã đề xuất có ý nghĩa, nhưng không rõ ràng nơi tôi nên cư trú. Tôi bắt đầu đặt nó bên trong mô-đun admin.py cho một trong các ứng dụng của tôi, nhưng nhận ra rằng không có ý nghĩa bởi vì nó là một đoạn mã toàn trang, và không cụ thể cho một ứng dụng cụ thể. Ngoài ra, tôi đã không chắc chắn làm thế nào hoặc tại sao một trong những sẽ sửa đổi các URLconf để sử dụng mã này kể từ khi tôi đã không thay đổi bất kỳ url. – Phil

+0

Cuối cùng cũng đã tìm cách thử phương pháp này. Thật không may tôi không thể làm cho nó hoạt động. Thứ nhất, hàm get_app() trả về một đối tượng mô-đun, thay vì đối tượng dict được index.html mong đợi (tôi nên đọc nguồn!). Thứ hai, bằng cách khởi tạo một lớp con của AdminSite, và sau đó đăng ký các ứng dụng của riêng bạn với nó, có vẻ như bạn mất khả năng hiển thị của các ứng dụng khác (như Auth) được đăng ký với đối tượng trang quản trị mặc định. Do đó tôi không thể tìm thấy cách để cấu hình những thứ như vậy mà cả ứng dụng mặc định và ứng dụng của riêng bạn sẽ xuất hiện cùng nhau trong chế độ xem chỉ mục quản trị. – Phil

0

Sau khi thực hiện những gì @AdminKG nói copy file index.html vào thư mục gốc của thư mục admin mà bạn cần để tạo bên trong thư mục templates bạn đã khai báo cho bạn setting.py.

nếu bạn có logic sắp xếp rõ ràng cho app_list, bạn có thể triển khai theo phương thức .index() của lớp con AdminSite của bạn. Nếu không, bạn sẽ cần phải mã hóa cứng danh sách ứng dụng trên index.html.

Để truy cập vào một cái gì đó trong mẫu của bạn chỉ có nó trong ngữ cảnh của bạn, một cái gì đó như thế:

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 
    ) 

Bây giờ ứng dụng đối tượng có sẵn để sử dụng trên của bạn index.htm

+0

"Nếu không, bạn sẽ cần phải mã hóa cứng danh sách ứng dụng trên index.html." Thật vậy, đó là bản chất của câu hỏi của tôi. Làm thế nào để có được, trong tập tin index.html địa phương của tôi, một xử lý cho một đối tượng ứng dụng cho rằng tôi chỉ biết tên của nó. Tôi có thể sử dụng hàm get_app ('myappname') trong mã python. Có một chức năng tương đương trong ngôn ngữ templating của django? Có lẽ tôi đang sủa hoàn toàn cây sai! – Phil

+0

@Phil tôi đã cập nhật câu trả lời – tikider

2

Nếu bạn không nhớ để sử dụng một lớp con của django.contrib.admin.site.AdminSite(), như mong đợi trong trường hợp khi bạn cần customize your admin site, tôi nghĩ rằng đó là một ý tưởng khả thi viết lại các phương pháp "index" và "app_index" trong lớp dẫn xuất. Bạn có thể đặt hàng tùy chỉnh bằng cách sử dụng hai bộ từ điển lưu trữ thứ tự khai báo ứng dụng trong settings.py và thứ tự đăng ký của các mô hình. Sau đó viết lại mã của AdminSite().index()app_index() ban đầu, thêm trường đơn hàng tùy chỉnh ('order') vào app_list và đặt hàng theo trường này mặc dù 'name'.Đây là mã, trừ app_index(), đó là tương tự như index() chức năng:

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) 

Nếu bạn sử dụng AdminSite tùy chỉnh và bạn muốn bao gồm mô hình Auth có thể bạn cần này, ở đâu đó trong mã của bạn (Tôi đã thực hiện nó trong một cụ thể ứng dụng để extend user information:.

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

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

Vì bạn đang lo ngại về trình tự, bạn có thể tìm thấy giải pháp của tôi hữu ích
về cơ bản, tôi đã tạo ra một bộ lọc, trong đó di chuyển các yếu tố mong muốn của app_list để đầu

.
@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 

Tuy nhiên, nếu bạn cần phải loại bỏ một số yếu tố mà bạn có thể sử dụng:

@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] 

Bộ lọc có thể bị xiềng xích, vì vậy bạn có thể sử dụng cả hai cùng một lúc.
Chức năng lọc không được viết theo cách sẽ làm cho chúng tăng tốc độ, nhưng mẫu này không được hiển thị quá thường xuyên theo định nghĩa.

Các vấn đề liên quan