我写了一个查询具有已知查找类型的模型。表示输入类型作为kwargs
传递的标志。 kwarg
查找与下面的kwargs一起解释如下。
db_hash=True
name=True
)124
或134
为id=True
)例如,仅用于方法调用的名称,
self.check_all_routes("Sam", "452", name=True)
我想重构以下方法,以减少它在违反DRY时产生的混乱。
def check_all_routes(self, driver, route, **kwargs):
_hash = kwargs.get('db_hash')
_name = kwargs.get('name')
_id = kwargs.get('id')
if _hash:
return self.model.objects.filter(
driver__db_hash=driver,
route__db_hash=route
).prefetch_related().select_related().values_list('route_number')
if _name:
return self.model.objects.filter(
driver__name=driver,
route__name=route
).prefetch_related().select_related().values_list('route_number')
if _id:
return self.model.objects.filter(
driver_id=driver,
route_id=route
).prefetch_related().select_related().values_list('route_number')
return self.model.objects.filter(
driver=driver,
route=route
).prefetch_related().select_related().values_list('route_number')
可以做些什么来使它不会违反DRY。
答案 0 :(得分:5)
你可以这样做:
def check_all_routes(self, driver, route, **kwargs):
queries = {
"db_hash": ['driver__db_hash', 'route__db_hash'],
"name": ['driver__name', 'route__name'],
"id": ['driver_id', 'route_id'],
"default": ['driver', 'route']
}
arg = next((k for k, v in kwargs.items() if v), 'default')
params = queries[arg]
query = dict(zip(params, [driver, route]))
return self.model.objects.filter(**query).prefetch_related().select_related().values_list('route_number')
这有点神奇,但最重要的部分是建立一个字典,然后使用filter
dict扩展语法传递给**
。
(注意,我不确定你的查询是否正确;这些都检查路由和驱动程序是否匹配值,这似乎不一定是真的。)
答案 1 :(得分:0)
如果你足够勇敢,你可以使它成为过滤器的包装器,
def check_all_routes(self, **kwargs):
return self.model.objects.filter(
**kwargs
).prefetch_related().select_related().values_list('route_number')
所以不要传递
self.check_all_routes("Sam", "452", name=True)
你可以做到
self.check_all_routes(driver__name="Sam", route__name="452")
您不需要提供类型的地方。这样做的一个优点是可以混合使用类型。
self.check_all_routes(driver__name="Sam", route__db_hash="some%hash%string")