Skip to main content
 首页 » 编程设计

python之Django 中优雅的析取范式

2025年05月04日23exmyth

假设我已经定义了这个模型:

class Identifier(models.Model): 
    user = models.ForeignKey(User) 
    key = models.CharField(max_length=64) 
    value = models.CharField(max_length=255) 

每个用户都有多个标识符,每个标识符都有一个键和一个值。我 100% 确定我想保持这样的设计,我这样做有外部原因,我不会在这里讨论,所以我对改变它不感兴趣。

我想开发这样的功能:

def get_users_by_identifiers(**kwargs): 
    # something goes here 
    return users 

该函数将返回具有 **kwargs 中指定的键=值对之一的所有用户。这是一个示例用法:

get_users_by_identifiers(a=1, b=2) 

这应该返回 a=1 或 b=2 的所有用户。我注意到我设置它的方式相当于析取范式……SQL 查询类似于:

SELECT DISTINCT(user_id) FROM app_identifier  
    WHERE (key = "a" AND value = "1") OR (key = "b" AND value = "2") ... 

我觉得必须有一些优雅的方法来获取 **kwargs 输入并对其进行 Django 过滤器,仅需 1-2 行即可产生此结果。不过我是 Django 的新手,所以我不确定该怎么做。现在这是我的功能,我完全确定这不是最好的方法:)

def get_users_by_identifiers(**identifiers): 
    users = [] 
    for key, value in identifiers.items(): 
        for identifier in Identifier.objects.filter(key=key, value=value): 
            if not identifier.user in users: 
                users.append(identifier.user) 
 
    return users 

有什么想法吗? :)

谢谢!

请您参考如下方法:

def get_users_by_identifiers(**kwargs): 
    q = reduce(operator.or_, Q(identifier__key=k, identifier__value=v) 
        for (k, v) in kwargs.iteritems()) 
    return User.objects.filter(q)