Elegant Disjunctive Normal Form in Django

Posted by Mike on Stack Overflow See other posts from Stack Overflow or by Mike
Published on 2010-05-28T00:40:54Z Indexed on 2010/05/28 0:41 UTC
Read the original article Hit count: 227

Filed under:
|

Let's say I've defined this model:

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

Each user will have multiple identifiers, each with a key and a value. I am 100% sure I want to keep the design like this, there are external reasons why I'm doing it that I won't go through here, so I'm not interested in changing this.

I'd like to develop a function of this sort:

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

The function will return all users that have one of the key=value pairs specified in **kwargs. Here's an example usage:

get_users_by_identifiers(a=1, b=2)

This should return all users for whom a=1 or b=2. I've noticed that the way I've set this up, this amounts to a disjunctive normal form...the SQL query would be something like:

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

I feel like there's got to be some elegant way to take the **kwargs input and do a Django filter on it, in just 1-2 lines, to produce this result. I'm new to Django though, so I'm just not sure how to do it. Here's my function now, and I'm completely sure it's not the best way to do it :)

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

Any ideas? :)

Thanks!

© Stack Overflow or respective owner

Related posts about python

Related posts about django