2014-01-14 30 views
3

TL; DR

有沒有辦法在使用ModelAdmin.get_urlsModelAdmins繼承擴展時定義好(命名空間)好名稱視圖?什麼是使用模型(admin)繼承時,名稱空間ModelAdmin.get_urls的Django方式?

最好不訴諸於ModelAdmin.model._meta或其他稍有問題的解決方案。使用和定製ModelAdmins繼承時

由頭通過get_urls添加

視圖名稱得到重寫。

即,視圖名稱admin:tighten被重寫在下面的例子:

class Screw(models.Model): 
    "A screw" 

class HexCapScrew(Screw): 
    "A hex cap screw" 


class ScrewAdmin(admin.ModelAdmin): 
    def get_urls(self): 
     urls = super(ScrewAdmin, self).get_urls() 
     extra_urls = patterns('', 
      url(r'^tighten/$', self.tighten, name='tighten'), 
     ) 
     return extra_urls + urls 

    def tighten(self, request): 
     pass 

class HexCapScrewAdmin(ScrewAdmin): 
    pass 


admin.site.register(Screw, ScrewAdmin) 
admin.site.register(HexCapScrew, HexCapScrewAdmin) 

在外殼會發生以下情況:

In [1]: reverse('admin:tighten') 
Out[1]: u'/admin/parts/hexscrew/tighten/' 

這是當然理解的,因爲的HexCapScrewAdmin登記會取代tightenScrewAdmin但是現在不可能將ScrewAdmin.tighten翻轉。

優選的溶液

但是我想能夠

  1. 參考兩個視圖separatedly和
  2. 優選具有在其自己的實例的命名空間的觀點。

迄今取得的進展

我想出如下設置最好(可複製&直接粘貼一些應用程序進行測試):

from django.contrib import admin 
from django.db import models 

class Screw(models.Model): 
    "A screw" 
    class Meta: 
     app_label = 'parts' 


class HexCapScrew(Screw): 
    "A hex cap screw" 
    class Meta: 
     app_label = 'parts' 
     proxy = True 


class ScrewAdmin(admin.ModelAdmin): 
    def tighten(self, request): 
     pass 

    def get_urls(self): 
     urls = super(ScrewAdmin, self).get_urls() 
     extra_urls = patterns('', 
      url(r'^tighten/$', self.tighten, name='tighten'), 
     ) 
     # Find out the slugified name of the model this admin is bound to 
     # TODO: Feels dirty 
     model_name = self.model._meta.model_name 

     # Add the to `extra_urls` to their own namespace 
     namespaced_extra_urls = patterns('', 
      url(r'^', include(extra_urls, namespace=model_name, app_name='screw')), 
     ) 
     return namespaced_extra_urls + urls 


class HexCapScrewAdmin(ScrewAdmin): 
    pass 

admin.site.register(Screw, ScrewAdmin) 
admin.site.register(HexCapScrew, HexCapScrewAdmin) 

現在我有如下:

In [1]: reverse('admin:screw:tighten') 
Out[1]: u'/admin/parts/screw/tighten/' 

In [2]: reverse('admin:hexscrew:tighten') 
Out[2]: u'/admin/parts/hexscrew/tighten/' 

In [3]: reverse('admin:screw:tighten', current_app='hexscrew') 
Out[3]: u'/admin/parts/hexscrew/tighten/' 

這是很好,但作品,但包括一點hackery。

這是最好的,或者我只是缺少一些東西?有什麼建議麼?

(至少一個其他的方式會做,因爲Django的ModelAdmin.get_urls使用ModelAdmin.model._metaparametrize the view names但我會用的命名空間。)

回答

1

如果你看的方式管理它here,你會看到,除了定義url之外,模型管理員還會將app_label和model_name作爲url名稱的前綴,從而避免出現子類問題。它還具有防止未經授權的用戶觀看的優勢(使用裝飾器self.admin_site.admin_view)。然後你get_urls()方法將成爲:

def get_urls(self): 
    from django.conf.urls import url 

    def wrap(view): 
     def wrapper(*args, **kwargs): 
      return self.admin_site.admin_view(view)(*args, **kwargs) 
     return update_wrapper(wrapper, view) 

    info = self.model._meta.app_label, self.model._meta.model_name 

    urlpatterns = super(ScrewAdmin, self).get_urls() 
    urlpatterns.append(
     url(r'^tighten/$', wrap(self.tighten), name='%s_%s_tighten' % info)) 
    return urlpatterns 

然後,你想看看你的網址,如:reverse('admin:app_screw_tighten')reverse('admin:app_hex_screw_tighten')

相關問題