Disons que je l'ai défini ce modèle:forme normale élégante disjonctif dans Django
class Identifier(models.Model):
user = models.ForeignKey(User)
key = models.CharField(max_length=64)
value = models.CharField(max_length=255)
Chaque utilisateur aura plusieurs identifiants, chacun avec une clé et une valeur. Je suis sûr à 100% que je veux garder le design comme ça, il y a des raisons externes pour lesquelles je le fais que je ne vais pas passer par ici, donc je ne suis pas intéressé à changer cela.
Je voudrais développer une fonction de ce genre:
def get_users_by_identifiers(**kwargs):
# something goes here
return users
La fonction retournera tous les utilisateurs qui ont l'une des paires clé = valeur spécifiée dans kwargs **. Voici un exemple d'utilisation:
get_users_by_identifiers(a=1, b=2)
Ceci devrait retourner tous les utilisateurs pour lesquels a = 1 ou b = 2. J'ai remarqué que la façon dont je l'ai mis tout ça, cela revient à une forme normale disjonctive ... la requête SQL serait quelque chose comme:
SELECT DISTINCT(user_id) FROM app_identifier
WHERE (key = "a" AND value = "1") OR (key = "b" AND value = "2") ...
Je me sens comme il doit y avoir une façon élégante de prenez l'entrée ** kwargs et faites-y un filtre Django, en seulement 1-2 lignes, pour produire ce résultat. Je suis nouveau à Django, donc je ne suis pas sûr de savoir comment le faire. Voici ma fonction maintenant, et je suis complètement sûr que ce n'est pas la meilleure façon de le faire :)
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
Des idées? :)
Merci!
Merci! Excellent moyen de le faire. J'ai dû légèrement le modifier cependant. Comme vous l'avez écrit, pour moi, il s'est traduit par "SyntaxError: L'expression du générateur doit être entre parenthèses sinon l'unique argument". J'ai changé la ligne sceond pour lire "q = réduire (operator.or_, (Q (identifiant__key = k, identifiant__value = v) pour (k, v) dans kwargs.iteritems()))" et cela a fonctionné parfaitement. – MikeC8
En fait, encore une petite modification nécessaire pour le faire fonctionner exactement comme je l'ai spécifié ci-dessus. Vous devez changer la dernière ligne pour lire "return User.objects.filter (q) .distinct()" – MikeC8