2009-06-09 8 views
2

Je suis au courant des applications de recherche en texte intégral comme Django Solr et solango, etc.Recherche avancée pour un modèle spécifique Django

Ce que je suis à la recherche de construire est plus proche d'une recherche avancée pour un site immobilier. E.g ils peuvent choisir l'emplacement, le prix, etc. semblable à www.viewr.com recherche avancée.

Ce que je l'ai fait jusqu'à présent est ce, sous les modèles gestionnaire personnalisé:

def advanced_search(self, district, location, type, facilities, features, not_permitted): 
     q_objects = [] 
     l_objects = [] 
     t_objects = [] 
     fc_objects = [] 
     ft_objects = [] 
     np_objects = [] 

     if district: 
      if location: 
       for loc in location: 
        l_objects.append(Q(location__exact=loc)) 
      else: 
       l_objects.append(Q(location__district=district)) 


     if type:  
      for ty in type: 
       t_objects.append(Q(listing_type__exact=ty)) 

     if facilities:  
      for fc in facilities: 
       fc_objects.append(Q(property_facilities__exact=fc)) 

     if features: 
      for ft in features: 
       ft_objects.append(Q(property_features__exact=ft)) 
       ft_objects.append(Q(community_features__exact=ft)) 

     if not_permitted:  
      for np in not_permitted: 
       np_objects.append(Q(not_permitted__exact=np))        

     # Start with a bare QuerySet 
     qs = self.get_query_set() 

     if location: 
      qs = qs.filter(reduce(operator.or_, l_objects)) 
     if type: 
      qs = qs.filter(reduce(operator.or_, t_objects)) 
     if facilities: 
      qs = qs.filter(reduce(operator.or_, fc_objects)) 
     if features: 
      qs = qs.filter(reduce(operator.or_, ft_objects)) 
     if not_permitted: 
      qs = qs.filter(reduce(operator.or_, np_objects)) 
     # Use operator's or_ to string together all of your Q objects. 
     return qs 

En ce moment, je ne suis pas d'obtenir des résultats très prévisibles. Y a-t-il quelque chose que je puisse mal faire? Existe-t-il une meilleure façon de faire les différentes recherches OU jointures?

Répondre

2

Le plus proche que je suis venu à ce scénario est ce post par Jacob:

http://www.djangosnippets.org/snippets/32/

Ce que je l'ai fait est:

def advanced_search(self, form): 
     # It's easier to store a dict of the possible lookups we want, where 
     # the values are the keyword arguments for the actual query. 
     qdict = {'district': 'location__district', 
      'location': 'location', 
      'property_type': 'listing_type', 
      'max_price': 'price__lte', 
      'property_features': 'property_features', 
      'community_features': 'community_features', 
     } 

     # Then we can do this all in one step instead of needing to call 
     # 'filter' and deal with intermediate data structures. 
     q_objs = [Q(**{qdict[k]: form.cleaned_data[k]}) for k in qdict.keys() if form.cleaned_data.get(k, None)]   
     search_results = RealEstateListing.objects.select_related().filter(*q_objs) 
     return search_results 

Il fonctionne très bien quand je passe des choix simples , mais lorsqu'il passe plusieurs choix comme pour les propriétés, il s'étouffe et dit:

OperationalError: la sous-requête renvoie plus de 1 ligne

+0

j'ai compris comment faire plusieurs choix c'est simple comme ajouter un __in sur le terrain par exemple property_features__in – Rasiel

+2

La ligne avec 'q_objs = ...' ressemble beaucoup à de la magie pour moi. Souhaitez-vous réécrire votre exemple en code plus pythonique? –

1

http://code.google.com/p/djapian/ index peut les champs de votre choix et vous permettent de construire des recherches complexes quoique combinaison, la logique booléenne, etc.

2

Juste quelques idées.

Il est très utile d'utiliser kwargs unpacking pour fournir des arguments à la méthode de filtrage dans de tels cas. Quelque chose comme cela peut rendre le code plus simple:

kwargs = {'not_permitted':np,'property_features': ft} 
return qs.filter(**kwargs) 

Peut-être que vous devriez jeter un coup d'oeil au code de filtrage de django dans l'admin. Dans django, les paramètres admin not_permitted__exact sont passés via GET. Et puis, après un certain filtrage, toute la dict GET peut être passée en argument kwargs non compressé à la méthode filter. Cela rend les choses très simples lorsque vous avez beaucoup d'options de filtrage.

+0

Hmm, j'ai manqué le fait que vous vouliez OU opérateur, pas le ET. Dans ce cas, je pense que la meilleure solution est d'utiliser quelque chose comme Djapian et de définir des poids pour les champs individuels que vous voulez. Mais comme je peux le voir www.viewr.com recherche avancée utilise une approche ET pour leurs filtres, pas OU. –

+0

Salut, voir mon commentaire ci-dessous, le vôtre est proche de l'extrait de l'exemple montré – Rasiel

Questions connexes