5 votes

Queryset : Comparer un champ avec une sous-chaîne d'un autre champ du même modèle

J'essaie de vérifier si les 3 premiers caractères d'un Charfield (charfield_1) sont similaires à un autre Charfield (charfield_2) du même modèle.

Essayé :

User.objects.filter(charfield_2__startswith=Substr('charfield_1', 1, 3))

J'ai essayé d'utiliser F et Func sans succès. Je continue à obtenir :

django.db.utils.DataError: invalid input syntax for integer: "1%"
LINE 1: ...CE(REPLACE((SUBSTRING("model_name"."charfield_2", '1%', 3)),...

Une idée de comment faire pour que cela fonctionne ? J'aimerais une solution utilisant l'ORM pour éviter les problèmes de performance.

Mise à jour :

Après avoir vérifié la requête générée par l'ORM et le message d'erreur, il semble que le deuxième paramètre Substr soit remplacé par un non-entier lorsque j'utilise l'expression de recherche startswith ou contains.

ex : Substr('charfield_1', 1, 3) est remplacé par Substr('charfield_1', '%1%', 3)

J'utilise la version 2.0.2.

Un ticket a été ouvert et accepté : https://code.djangoproject.com/ticket/29155

3voto

albar Points 1958

Erreur étrange, on dirait un bug de Django ? Chez moi, en utilisant la 1.11, cela fonctionne :

User.objects.annotate(f1=Substr('charfield_1', 1, 3), f2=Substr('charfield_2', 1, 3)).filter(f1=F('f2'))

2voto

David D. Points 3589

Vous pouvez écrire une méthode User (ou une fonction si vous utilisez la classe User intégrée) qui compare vos champs.

Par exemple avec une méthode :

class User:
    def has_same_start(self):
       return self.charfield_1[0:3] == self.charfield_2[0:3]

Ensuite, pour votre queryset :

all_users = User.objects.all()

# method1 - returns a list of User objects
my_selected_users = [user if user.has_same_start() for user in all_users]  

# method2 - returns a queryset
my_selected_users = User.objects.filter(pk__in=[user.pk if user.has_same_start() for user in all_users])

Je ne dis pas que c'est la meilleure solution. C'est juste une solution, mais il y a peut-être mieux, en termes de performances. Cependant, lorsque j'ai besoin de faire des comparaisons délicates, je préfère utiliser des méthodes séparées afin de faciliter les tests unitaires.

0voto

F. Caron Points 371

Après avoir vérifié la requête générée par l'ORM et le message d'erreur, il semble que le deuxième paramètre Substr soit remplacé par un non-entier lorsque j'utilise la méthode suivante startswith o contains expression de recherche.

ex : Substr('charfield_1', 1, 3) est remplacé par Substr('charfield_1', '%1%', 3)

Je vais signaler le bogue sur django. J'utilise la version 2.0.2 au fait.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X