2017-10-11 3 views
2

intérieur de mon modèle Profil J'ai la fonction suivante:Django, ayant filtre d'objet Q par fonction dans le modèle

Il sert à renvoyer le nom complet de l'utilisateur (ou une alternative si certaines données sont manquantes).

def full_name(self): 
     first_name = self.user.first_name.strip() 
     if first_name and self.user.last_name: 
      if not self.middle_name: 
       full_name = u'%s %s' % (first_name, self.user.last_name) 
      else: 
       full_name = u'%s %s %s' % (first_name, self.middle_name, 
             self.user.last_name) 
      return full_name.strip() 
     elif first_name: 
      return first_name 
     return self.user.username 

Maintenant, pour ma question: j'ai une vue où je filtre une queryset fonction de la variable « q » (qui est retourné d'un searchbox dans le modèle) comme ceci:

qs = qs.filter(tenant_demo_purchase=True).order_by('-id') 
    #Search users within results 
    q = self.request.GET.get('q', None) 
    if q: 
     qs = qs.filter(Q(user__username__icontains=q) | 
         Q(user__first_name__icontains=q) | 
         Q(user__last_name__icontains=q) | 
         Q(arrangement_period__arrangement__title__icontains=q) | 
         ).filter(tenant_demo_purchase=True).order_by('-id') 
    else: 
     pass 
    return qs 

Ce filtre fonctionne correctement si je lui donne un prénom, un nom d'utilisateur ou un nom de famille. Mais si je lui donne un prénom + nom (exemple: "John Doe") il ne renvoie aucun résultat.

La plupart de mes utilisateurs ont tendance à soumettre le nom complet, alors comme une solution, j'ai essayé d'avoir accès à la fonction Profile.full_name. En ajoutant la ligne suivante

Q(user__profile__fullname__icontains=q) 

Cependant, cette plante avec le message d'erreur suivant:

raise FieldError('Related Field got invalid lookup: {}'.format(lookups[0])) 
FieldError: Related Field got invalid lookup: fullname 

Interistengly, quand je regarde la page d'erreur de django il semble ignorer les noms d'utilisateur et d'échouer sur le ' requête « arrangement__title, en ignorant le reste:

Q(arrangement_period__arrangement__title__icontains=q) 

J'ai essayé de faire à l'évidence:

Q(user__profile.fullname__icontains=q) 

Mais ce que l'erreur jette suivant

SyntaxError: keyword can't be an expression 

Je veux juste une façon pour les utilisateurs d'entrer un nom complet (prénom + espace + nom) et ont encore le programme de retour des résultats corrects.

Est-ce que quelqu'un connaît un moyen de le faire?

Solution

Merci à Ivan sa réponse, les codes ci-dessous présente le résultat souhaité:

q = self.request.GET.get('q', None) 
    if q: 
     qs = qs.annotate(
      full_name=Concat(
       'user__first_name', 
       Value(' '), 
       'user__last_name', 
       output_field=CharField() 
      ) 
     ).filter(Q(full_name__icontains=q) | 
       Q(user__username__icontains=q) | 
       Q(user__first_name__icontains=q) | 
       Q(user__last_name__icontains=q) | 
       Q(arrangement_period__arrangement__title__icontains=q) 
       ).order_by('-id') 
+0

vous manque un opérateur OR après la ligne 'Q (user__first_name__icontains = q)' –

+0

Oups, il semble qu'il se soit perdu quand j'ai collé/édité la morue e pour le poste. – Jasper

Répondre

2

Essayez d'utiliser la fonction de base de données concat:

from django.db.models import CharField, Value 
from django.db.models.functions import Concat 


qs = qs.annotate(
    full_name=Concat(
     'user__first_name', 
     Value(' '), 
     'user__last_name', 
     output_field=CharField() 
    ) 
).filter(full_name__icontains=q) 
+0

Merci beaucoup! J'ai été capable d'utiliser ce code pour faire fonctionner mon programme. Je vais mettre à jour ma question en conséquence. – Jasper