Reputation: 2147
I'm a newbie to django-autocomplete-light. I'm trying to implement something like the "global navigation autocomplete" (https://django-autocomplete-light.readthedocs.org/en/docs_rewrite/navigation.html#a-simple-view) however this shall be used to navigate between patients.
Here's the problem:
Which part am I missing? Is is the filtering or autocomplete which cannot cope with filtering based on two fields from a given model?
Here's a part of my simple model (please note that the url 'patient_detail' exists and works fine, just not pasting it here):
class Patient(models.Model):
name = models.CharField(max_length = 30, blank=False)
surname = models.CharField(max_length = 70, blank=False)
def __unicode__(self):
return '%s %s' % (self.name, self.surname)
def get_absolute_url(self):
return reverse('patient_detail', kwargs = {'pk':self.pk})
Than, I'm doing this (similar to what's described in the docs) in my view, where q get's all I'm typing into the field:
def pacjent_autocomplete(request, template_name = 'reception_autocomplete.html'):
q = request.GET.get('q','').strip()
queries = {}
queries['patients'] = Patient.objects.filter(Q(name__icontains=q) | Q(surname__icontains = q))
return render(request, template_name, queries)
The reception_autocomplete.html file looks like this:
<span class="separator">Patients</span>
{% for patient in patients %}
<a class="block choice" href="{{patient.get_absolute_url}}">{{patient}}</a>
{% endfor %}
In my main view I have a field which is the target of this script:
<script type="text/javascript">
$(document).ready(function() {
$('#id_new_patient').yourlabsAutocomplete({
url: "{% url 'reception_autocomplete' %}",
choiceSelector: 'a',
}).input.bind('selectChoice', function(e, choice, autocomplete) {
document.location.href = choice.attr('href');
});
});
</script>
Your help on how to show the right patient for input like "John Sm" is much appreciated!
Upvotes: 1
Views: 1618
Reputation: 157
If a simple query (using .filter()
on a single field) or a complex one using Q
(see @jpic's answer) is not fitting your needs, you might also make use of Django's search features (for Postgres only), especially SearchVector
:
It will allow you to combine multiple fields to be searched against.
>>> from django.contrib.postgres.search import SearchVector
>>> Entry.objects.annotate(
... search=SearchVector('body_text', 'blog__tagline'),
... ).filter(search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]
see https://docs.djangoproject.com/en/3.1/topics/db/search/#document-based-search and https://docs.djangoproject.com/en/3.1/ref/contrib/postgres/search/#django.contrib.postgres.search.SearchVector
Upvotes: 0
Reputation: 33420
That's not a problem with autocomplete_light, but with your Django query:
Patient.objects.filter(Q(name__icontains=q) | Q(surname__icontains = q))
That would select all Patient which have surname__icontains="John S"
or name__icontains="John S"
. That's why you get no result. Check how django-cities-light does search: https://github.com/yourlabs/django-cities-light/blob/stable/3.x.x/cities_light/abstract_models.py
Or use django-haystack and implement a haystack backend, or redis...
Or, fallback to raw sql in choices_for_request
to filter against a concatenation of name and surname.
Upvotes: 2