使用django查询不违反DRY的重构方法?

dee*_*ena 0 python django refactoring dry django-queryset

我写了一个查询具有已知查找类型的模型.表示输入类型传递的标志kwargs.下面kwarg将解释查找以及传递的kwargs.

  1. 数据库哈希(随机对实例没有唯一性db_hash=True)
  2. 对象的名称("John"或"Sam"为name=True)
  3. 对象的ID.(obj.ids 124,或134as id=True)
  4. 实例(没有任何标志的objs)

例如,只是为了方法调用的名称,

self.check_all_routes("Sam", "452", name=True)
Run Code Online (Sandbox Code Playgroud)

我想重构下面的方法来减少它在违反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')
Run Code Online (Sandbox Code Playgroud)

可以做些什么来使它不违反DRY.

Dan*_*man 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')
Run Code Online (Sandbox Code Playgroud)

这有点神奇,但最重要的部分是建立一个字典,然后filter使用**dict扩展语法传递给它.

(注意,我不确定你的查询是否正确;这些都检查路由和驱动程序是否匹配值,这似乎不一定是真的.)