2014-10-29 4 views
5

Sono un Django novizio, cercando di creare un modulo "Ricerca" per il mio progetto utilizzando MySql con motore MyISAM. Finora, riesco a far funzionare il modulo, ma Django non sembra cercare tutti i campi allo stesso modo. I risultati sono casuali Esempio: Ricerca in region restituisce alcun risultato o di ricerca peggiore description funziona bene, mentre howtogetin non sembra applicare ..Come posso effettuare la ricerca di Django in più campi utilizzando QuerySets e MySql "Ricerca di testo completo"?

Ecco il mio modello:

class Camp(models.Model): 
    owner = models.OneToOneField(User) 
    name = models.CharField(max_length=100) 
    description = models.TextField() 
    address1 = models.CharField(max_length=128) 
    address2 = models.CharField(max_length=128) 
    zipcode = models.CharField(max_length=128) 
    region = models.CharField(max_length=128) 
    country = models.CharField(max_length=128) 
    phone = models.CharField(max_length=60) 
    howtogetin = models.TextField() 

    def __str__(self): 
     return self.name 

Qui è la mia opinione:

def campsearch(request): 
if request.method == 'POST': 
    form = CampSearchForm(request.POST) 
    if form.is_valid(): 
     terms = form.cleaned_data['search'] 
     camps = Camp.objects.filter(
      Q(name__search=terms)| 
      Q(description__search=terms)| 
      Q(address1__search=terms)| 
      Q(address2__search=terms)| 
      Q(zipcode__search=terms)| 
      Q(region__search=terms)| 
      Q(country__search=terms)| 
      Q(howtogetin__search=terms) 
      ) 
     return render(request, 'campsearch.html', {'form':form, 'camps':camps}) 
else: 
    form = CampSearchForm() 
    return render(request, 'campsearch.html', {'form':form}) 

Qualsiasi indizio?

risposta

7

vi consiglio di implementare questa:

#views.py 
def normalize_query(query_string, 
    findterms=re.compile(r'"([^"]+)"|(\S+)').findall, 
    normspace=re.compile(r'\s{2,}').sub): 

    ''' 
    Splits the query string in invidual keywords, getting rid of unecessary spaces and grouping quoted words together. 
    Example: 
    >>> normalize_query(' some random words "with quotes " and spaces') 
     ['some', 'random', 'words', 'with quotes', 'and', 'spaces'] 
    ''' 

    return [normspace(' ',(t[0] or t[1]).strip()) for t in findterms(query_string)] 

def get_query(query_string, search_fields): 

    ''' 
    Returns a query, that is a combination of Q objects. 
    That combination aims to search keywords within a model by testing the given search fields. 
    ''' 

    query = None # Query to search for every search term 
    terms = normalize_query(query_string) 
    for term in terms: 
     or_query = None # Query to search for a given term in each field 
     for field_name in search_fields: 
      q = Q(**{"%s__icontains" % field_name: term}) 
      if or_query is None: 
       or_query = q 
      else: 
       or_query = or_query | q 
     if query is None: 
      query = or_query 
     else: 
      query = query & or_query 
    return query 

E per ogni ricerca

#views.py 
def search_for_something(request): 
    query_string = '' 
    found_entries = None 
    if ('q' in request.GET) and request.GET['q'].strip(): 
     query_string = request.GET['q'] 
     entry_query = get_query(query_string, ['field1', 'field2', 'field3']) 
     found_entries = Model.objects.filter(entry_query).order_by('-something') 

    return render_to_response('app/template-result.html', 
      { 'query_string': query_string, 'found_entries': found_entries }, 
      context_instance=RequestContext(request) 
     ) 

E nel modello

#template.html 
<form class="" method="get" action="{% url 'search_for_something' model.pk %}"> 
    <input name="q" id="id_q" type="text" class="form-control" placeholder="Search" /> 
    <button type="submit">Search</button> 
</form> 

#template-result.html 
{% if found_entries %} 
    {% for field in found_entries %} 
     {{ model.field }} 
    {% endfor %} 
{% endif %} 

e l'URL

#urls.py 
url(r'^results/$', 'app.views.search_for_something', name='search_for_something'), 
+1

Ho visto qualcosa di simile su internet ma non riesco a capire come funziona. L'hai provato? puoi spiegare perché è un'implementazione migliore dell'implementazione predefinita di Django per ** search ** e ** incontains **? – adilbenseddik

+1

Ciao adilbenseddik, sì ce l'ho nel mio progetto e funziona benissimo. Questo approccio è stato dato da Julien Phalip in http://julienphalip.com/post/2825034077/adding-search-to-a-django-site-in-a-snap –

+1

Farò un tentativo. grazie per il riferimento. ancora, hai qualche idea su cosa non funziona con il mio codice? dovrebbe funzionare abbastanza fuori dagli schemi in base alla documentazione di Django. – adilbenseddik

1

__search funziona solo su campi di testo con indicizzazione di testo completo (sembra che il campo della descrizione sia questo). Invece di provare a utilizzare questo:

Q(name__icontains=terms) 

Questo è un case insensitive 'contiene' sui campi del 'Charfield'.


ricerca: https://docs.djangoproject.com/en/dev/ref/models/querysets/#search

icontains: https://docs.djangoproject.com/en/dev/ref/models/querysets/#icontains

+0

ho finito utilizzando sia di estendere la portata dei risultati con 'Q (name__search = termini) | Q (name__icontains = termini)' e lo ha fatto. Tuttavia, ci sono casi in cui i risultati sono casuali. per esempio se _foo_ e _foo2_ sono nel database la ricerca di '_foo_ _foo2_' non funziona mentre '_foo_ _and random string_' funziona bene. Alcuni termini di ricerca sembrano essere ignorati anche se corrispondono a un caso "Q" attuale. qualche indizio? – adilbenseddik