2016-09-29 37 views
0

我真的很討厭樣板文件。但是,我不能否認像下面這樣的代碼是一個巨大的好處。所以我的問題是,在Python中做了什麼來彌補它不具有宏(模板)預處理器的事實?如何減少基於Django類的視圖樣板文件

一個想法是編寫一個工廠函數,但我會自願承認我不知道從哪裏開始。 (請注意,這是Django及其聲明性類和有趣的「魔術」metaclassy的東西在下面,我知道足夠的認識,並不足以理解或調試,如果我打破它)

另一個將轉這成爲一個模板,並通過在Bash中實現類似${var:-default}的簡單預處理器導入它。 (見What is an alternative to execfile in Python 3?),

with my_preprocessor("somefile.py") as f: 
    code = compile(f.read(), "somefile.py", 'exec') 
    exec(code) # in the current namespace 

但也有許多關於exec警告,我已經看到多年來的。引用的答案提到了用於調試的行號作爲一個問題。然後是這個,http://lucumr.pocoo.org/2011/2/1/exec-in-python/,包括內存泄漏在內的細微問題的警告。我懷疑他們不會適用於定義「永不」被刪除的類的代碼,但另一方面,我不希望在生產環境中引入模糊問題。

任何想法或指針歡迎。最好的做法是接受剪切和粘貼樣板文件?任何這樣的模板都不可能有超過20次的粘貼修改,通常少於10次。

示例代碼。標有#V的行是唯一可以定製的行。前兩個類只使用一次,到第三個使用。

#--- this is boilerplate for a select-view ---- 
#--- just replace the string "User" by the relevant model and customize 

class UserSelectPopupTable(tables.Table): 

    id = SelectorColumn(clickme='<span class="glyphicon glyphicon-unchecked"></span>') #V 

    class Meta: 
     model=User 
     attrs={ 'class':'paleblue' } 
     empty_text='Sorry, that search did not match anything.' 
     fields=('name','address',)  #V 
     sequence=('id','name','address',) #V 

class UserFilter2(django_filters.FilterSet): 
    name = django_filters.CharFilter(lookup_expr='icontains')  #V 
    address = django_filters.CharFilter(lookup_expr='icontains') #V 
    class Meta: 
     model = User 
     fields = ('name','address',) #V (usually same as previous) 

class UserSelectPopup(FilterTableView): 
    model=User 
    table_class=UserSelectPopupTable 
    filterset_class=UserFilter2 
    template_name='redacted/select_in_popup.html' 

#--- end boilerplate 
+0

你能舉一個你想如何使用這些生成的類的例子嗎? –

+0

as views:'url(r'^ UserSelectPopup/$',views.UserSelectPopup。as_view(),name ='userselectpopup'),' – nigel222

+0

寫一個工廠比我想象的要容易得多。我閱讀並重新閱讀'type' 3-arg文檔,然後......將在更多測試和整理之後回答自己的問題。 – nigel222

回答

2

Python和Django很棒。

我閱讀並重新閱讀了用於動態創建類的type的3參數形式(相當簡短)的文檔(https://docs.python.org/3/library/functions.html#type)。我寫了一個簡單的幫助程序例程Classfactorytype提供更好的接口,並將類結構轉換爲函數調用,這些函數調用通常是剪切和粘貼的!我得出了以下的(我認爲也證明了你可以用Python編寫JavaScript ...本能插入分號是強)

def Classfactory(classname, inheritsfrom=(object,), **kwargs): 
    inh = inheritsfrom if isinstance(inheritsfrom, tuple) else (inheritsfrom,) 
    return type(classname, inh, kwargs) 

ThisPopupFilter = Classfactory('ThisPopupFilter', django_filters.FilterSet, 

    name = django_filters.CharFilter(lookup_expr='icontains') , 
    address = django_filters.CharFilter(lookup_expr='icontains') , 
    Meta = Classfactory('Meta', 
     model = User, 
     fields = ('name','address',), 
    ), 
) 
ThisPopupTable = Classfactory('ThisPopupTable', tables.Table, 

    id = SelectorColumn(clickme='<span class="glyphicon glyphicon-unchecked"></span>'), 

    Meta = Classfactory('Meta', # default inherit from object 
     model=User, 
     attrs={ 'class':'paleblue' }, 
     empty_text='Sorry, that search did not match anything.', 
     fields=('name','address',) , 
     sequence=('id','name','address',) , 
    ), 
) 

UserSelectPopup = Classfactory('UserSelectPopup', FilterTableView, 
    model=User, 
    table_class=ThisPopupTable, 
    filterset_class=ThisPopupFilter, 
    template_name='silson/select_in_popup.html', # this template handles any such view 
) 

現在,我突然意識到,這不僅僅是Django的Meta類,可在其他類中定義。任何其他地方不需要的類都可以嵌套在需要的範圍內。讓我感動的第三裏面的前兩類,然後用多一點重新安排我能夠移動到帶有參數的工廠函數...

def SelectPopupFactory(Model, fields, sequence=None, 
       clickme='<span class="glyphicon glyphicon-unchecked"></span>' , 
       empty_text='Sorry, that search did not match anything.',): 
    return Classfactory('UserSelectPopup', FilterTableView, 

    model=Model, 
    template_name='silson/select_in_popup.html', # this template handles any such view 

    table_class=Classfactory('ThisPopupTable', tables.Table, 
     id = SelectorColumn(clickme=clickme), 
     Meta = Classfactory('Meta', # default inherit from object 
      model=Model, 
      attrs={ 'class':'paleblue' }, 
      empty_text=empty_text, 
      fields=fields, 
      sequence=sequence, 
    )), 
    filterset_class=Classfactory('ThisPopupFilter', django_filters.FilterSet, 
     name = django_filters.CharFilter(lookup_expr='icontains') , 
     address = django_filters.CharFilter(lookup_expr='icontains') , 
     Meta = Classfactory('Meta', 
      model = Model, 
      fields = ('name','address',), 
    )), 
) 

UserSelectPopup = SelectPopupFactory(User, 
    fields=('name','address',), 
    sequence=('id','name','address',) , 
    ) 

任何人都可以看到什麼根本性的錯誤呢? (我感到有點驚訝,它都跑了,並沒有崩潰的第一次嘗試,模塊輸入錯誤)

更新一個工作日晚些時候:我認爲這是可以作爲一個例子/證明的概念(它是代碼跑沒有崩潰),但是有幾個細節可以用於實際的django_filters和django_tables2用法,這些用法並不在這裏。我的工廠功能已經發展並且功能更強大,但不易與原始的非工廠類定義相關聯。