2016-09-29 64 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用法,这些用法并不在这里。我的工厂功能已经发展并且功能更强大,但不易与原始的非工厂类定义相关联。

相关问题