我真的很讨厌样板。但是,我不能否认以下代码是一个巨大的好处。所以我的问题是,在Python中做什么来弥补它没有宏(模板)预处理器的事实?
一个想法是写一个工厂功能,但我愿意承认我不知道从哪里开始。 (请注意,这是Django的声明性类和有趣的“魔术”元类物质,我知道足够认识,如果我打破它就不足以理解或调试)
另一种方法是将其转换为模板并通过一个简单的预处理器导入它,该预处理器在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
的警告。引用的SO答案提到调试的行号作为一个问题。然后有这个http://lucumr.pocoo.org/2011/2/1/exec-in-python/警告微妙的问题,包括内存泄漏。我怀疑它们不适用于定义“永不”删除的类的代码,但另一方面,我不希望在生产环境中引入模糊问题的风险最小。
欢迎任何想法或指示。最好的办法是接受切割和粘贴样板吗?任何此类模板都不可能超过二十次修改,通常少于十次。
示例代码。标记为#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 :(得分:2)
Python和Django非常棒。
我阅读并重新阅读了用于动态创建类(https://docs.python.org/3/library/functions.html#type)的type
的3参数形式的(非常简短的)文档。我编写了一个简单的帮助程序例程Classfactory
,以便为type
提供更好的接口,并将类结构转换为函数调用,这些调用主要是剪切和粘贴!我到达了以下(我认为也证明你可以用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用法有几个细节要做。就在这儿。我的工厂功能已经发展并且更有能力,但不太容易与原始的非工厂类定义相关联。