2009-12-23 4 views
0

Comme je suis un lecteur impressionné de Stack Overflow je veux poser ma première question ici. Depuis que j'ai rencontré un problème avec un extrait et je ne sais pas si j'ai fait une erreur ou c'est un bug dans le code que j'utilise.Django fonctionnalité de recherche - bug avec requête de recherche de longueur 2

J'adapté ce code pour mon propre site:

http://blog.tkbe.org/archive/django-admin-search-functionality/

Il fonctionne très bien et il est vraiment un grand bout. Mais si ma requête de recherche a une longueur de 2, je pense que les résultats ne sont pas corrects.

Ainsi, par exemple si je recherche « re » au prénom et nom, je reçois les résultats suivants:

Mr. Tom Krem 
Ms. Su Ker 

Ce qui est assez étrange. Pour les requêtes de longueur> 2 je ne rencontre pas ce problème. Alors peut-être que cet article lit quelqu'un qui utilise l'extrait ci-dessus et peut me dire s'il rencontre le même problème.

Si personne d'autre ne rencontre le problème, je sais au moins que j'ai un bug quelque part dans mon code. Peut-être dans la forme que j'utilise, ou quelque chose est foiré dans le contexte de la requête.

Comment puis-je résoudre ce problème?

Edit 1:

L'étiquette d'inclusion:

from django import template 
from crm.views import SEARCH_VAR 

def my_search_form(context): 
    return { 
     'context': context, 
     'search_var': SEARCH_VAR 
    } 

register = template.Library() 
register.inclusion_tag('custom_utilities/my_search_form.html')(my_search_form) 

Le my_search_form.html:

<div id="toolbar"><form 
     id="changelist-search" 
     action="" 
     method="get"> 
     <div><!-- DIV needed for valid HTML --> 
      <label 
       for="searchbar"><img src="{{ context.media_url }}/crm/img/search.png" 
       class="icon" 
       alt="Search" /></label> 
      <input 
       type="text" 
       size="40" 
       name="{{ search_var }}" 
       value="{{ context.query }}" 
       id="searchbar" /> 
      <input type="submit" value="Search" /> 
     </div> 
    </form> 
</div> 
<script 
    type="text/javascript">document.getElementById("searchbar").focus(); 
</script> 

La vue:

@login_required 
def crm_contacts(request): 
    query = request.GET.get('q', '') 
    #pass additional params to the SortHeaders function 
    #the additional params will be part of the header <a href...> 
    #e.g. use it for pagination/use it to provide the query string 
    additional_params_dict = {'q': query} 
    foundContacts = search_contact(request,query) 
    sort_headers = SortHeaders(request, LIST_HEADERS, default_order_field=1, additional_params=additional_params_dict) 
    if foundContacts is not None: 
     contact_list = foundContacts.order_by(sort_headers.get_order_by()) 
    else: 
     contact_list = Contact.objects.order_by(sort_headers.get_order_by()) 
    context = { 
     'contact_list' : contact_list, 
     'headers': list(sort_headers.headers()), 
     'query' : query, 
    } 
    return render_to_response("crm/contact_list.html", context, 
          context_instance=RequestContext(request)) 

Le formulaire de recherche de contact:

#models 
from crm.models import Contact 
from django.db.models import Q 

''' 
A search form from 
http://blog.tkbe.org/archive/django-admin-search-functionality/ 
adapted to search for contacts. 
''' 
def search_contact(request,terms=None): 
    if terms is None: 
     return Contact.objects.all() 
    query = Contact.objects 
    for term in terms: 
     query = query.filter(
      Q(first_name__icontains=term) 
      | Q(last_name__icontains=term)) 
    return query 

Une autre édition:

J'utilise cet extrait pour trier le tableau. Probablement on devrait le savoir afin de comprendre le code affiché ci-dessus.

Puisque je ne peux pas publier de liens (protection anti-spam), je vais essayer de vous expliquer où le trouver. Aller sur Google. Tapez: django snippet table sort

Ensuite, il devrait être le deuxième coup. Trier les en-têtes de tableau. extrait nr. 308.

Edit: Ajouter la fonction SortHeaders()

ORDER_VAR = 'o' 
ORDER_TYPE_VAR = 'ot' 

class SortHeaders: 
    """ 
    Handles generation of an argument for the Django ORM's 
    ``order_by`` method and generation of table headers which reflect 
    the currently selected sort, based on defined table headers with 
    matching sort criteria. 

    Based in part on the Django Admin application's ``ChangeList`` 
    functionality. 
    """ 
    def __init__(self, request, headers, default_order_field=None, 
      default_order_type='asc', additional_params=None): 
     """ 
     request 
      The request currently being processed - the current sort 
      order field and type are determined based on GET 
      parameters. 

     headers 
      A list of two-tuples of header text and matching ordering 
      criteria for use with the Django ORM's ``order_by`` 
      method. A criterion of ``None`` indicates that a header 
      is not sortable. 

     default_order_field 
      The index of the header definition to be used for default 
      ordering and when an invalid or non-sortable header is 
      specified in GET parameters. If not specified, the index 
      of the first sortable header will be used. 

     default_order_type 
      The default type of ordering used - must be one of 
      ``'asc`` or ``'desc'``. 

     additional_params: 
      Query parameters which should always appear in sort links, 
      specified as a dictionary mapping parameter names to 
      values. For example, this might contain the current page 
      number if you're sorting a paginated list of items. 
     """ 
     if default_order_field is None: 
      for i, (header, query_lookup) in enumerate(headers): 
       if query_lookup is not None: 
        default_order_field = i 
        break 
     if default_order_field is None: 
      raise AttributeError('No default_order_field was specified and none of the header definitions given were sortable.') 
     if default_order_type not in ('asc', 'desc'): 
      raise AttributeError('If given, default_order_type must be one of \'asc\' or \'desc\'.') 
     if additional_params is None: additional_params = {} 

     self.header_defs = headers 
     self.additional_params = additional_params 
     self.order_field, self.order_type = default_order_field, default_order_type 

     # Determine order field and order type for the current request 
     params = dict(request.GET.items()) 
     if ORDER_VAR in params: 
      try: 
       new_order_field = int(params[ORDER_VAR]) 
       if headers[new_order_field][1] is not None: 
        self.order_field = new_order_field 
      except (IndexError, ValueError): 
       pass # Use the default 
     if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'): 
      self.order_type = params[ORDER_TYPE_VAR] 

    def headers(self): 
     """ 
     Generates dicts containing header and sort link details for 
     all defined headers. 
     """ 
     for i, (header, order_criterion) in enumerate(self.header_defs): 
      th_classes = [] 
      new_order_type = 'asc' 
      if i == self.order_field: 
       th_classes.append('sorted %sending' % self.order_type) 
       new_order_type = {'asc': 'desc', 'desc': 'asc'}[self.order_type] 
      yield { 
       'text': header, 
       'sortable': order_criterion is not None, 
       'url': self.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}), 
       'class_attr': (th_classes and ' class="%s"' % ' '.join(th_classes) or ''), 
      } 

    def get_query_string(self, params): 
     """ 
     Creates a query string from the given dictionary of 
     parameters, including any additonal parameters which should 
     always be present. 
     """ 
     params.update(self.additional_params) 
     return '?%s' % '&amp;'.join(['%s=%s' % (param, value) \ 
            for param, value in params.items()]) 

    def get_order_by(self): 
     """ 
     Creates an ordering criterion based on the current order 
     field and order type, for use with the Django ORM's 
     ``order_by`` method. 
     """ 
     return '%s%s' % (
      self.order_type == 'desc' and '-' or '', 
      self.header_defs[self.order_field][1], 
     ) 
+0

Quel est le backend de votre base de données? PostgreSQL? MySQL? Pourriez-vous poster votre version adaptée du code que vous pointez sur le blog ci-dessus? – cethegeek

+0

J'utilise mysql. Je posterai la version adaptée du code ci-dessous. –

+0

Vous devriez vraiment avoir tout le code que vous avez ajouté en guise de réponse à la question. Je ne cherche pas à pinailler, c'est juste que vous savez juste marqué votre question en réponse (ce qui réduit le trafic, et l'espoir d'obtenir une réponse), et confond les futurs lecteurs en pensant que tout ce code fait partie d'un solution à la question. – cethegeek

Répondre

0

Si vous exécutez manage.py shell puis:

>>> from crm.models import Contact 
>>> from django.db.models import Q 
>>> list=Contact.objects.filter(Q(first_name__icontains='re')|Q(last_name__icontains='re')) 
>>> print list 

Quelle est la sortie?


Edit: droit, donc si vous essayez:

>>> list=Contact.objects.filter(Q(first_name__icontains='mot')|Q(last_name__icontains='mot')) 
>>> print list 

(je suis en train de restreindre les conditions qui vous donnent problème et j'ai vu votre dernier commentaire)

Quelle est la sortie?


Edit: Si les deux requêtes ci-dessus travaillent dans le shell, quelque chose d'autre est en train de modifier votre queryset quelque part et en ajoutant des critères supplémentaires ...

Etes-vous sûr sort_headers() est de ne pas modifier le queryset avec plus qu'une simple commande par clause? Pourriez-vous poster sort_headers() à votre question?

+0

sortie est-> M. Tom Krem ce serait correct! donc il y a probablement un problème dans le transfert de la chaîne de requête? –

+0

ok les deux requêtes ci-dessus fonctionnent bien. donc probablement quelque part j'ajoute probablement quelque chose à ma requête. Je vais vérifier le code demain. C'est trop tard maintenant ;-) merci beaucoup pour votre aide! –

+0

Je suppose que j'ai trouvé le problème. c'est le terme en question. il semble que chaque personnage est filtré et ajouté à l'ensemble de résultats ..!? query = request.GET.get ('q', '') foundContacts = search_contact (demande, requête) >>> >>> QueryResult = Contact.objects >>> pour expression dans la requête: . .. terme d'impression ... QueryResult = queryresult.filter ( ... Q (first_name__icontains = terme) ... | Q (last_name__icontains = terme)) ... m o t >>> print queryresult [, , , , , , ... –

Questions connexes