I've a simple searching form and view:
# forms.py
class SearchForm(forms.Form):
q = forms.CharField(label='Search', max_length=1024, required=False)
# views.py
def search(request):
search_form = forms.SearchForm()
q = ''
if request.method == 'GET':
search_form = forms.SearchForm(request.GET)
if search_form.is_valid():
q = search_form.cleaned_data['q']
products = models.Product.objects.filter(publication_status='published')
if q.strip() != '': # If there's something to search for which not whitespaces
products = products.filter(
Q(title__contains=q) |
Q(description__contains=q) |
Q(main__name__contains=q) |
Q(sub__contains=q)
)
context = {
'products': products,
'search_form':search_form,
}
return render(request, 'search.html', context=context)
# search.html
{% if products %}
<h3>Products:</h3>
<ul>
{% for p in products %}
<li><ul>
<li><a href="{% url 'product' p.pk %}">{{ p }}</a></li>
<li>{{ p.description }}</li>
<li><a href="{% url 'main' p.main.pk %}">{{ p.main }}</a></li>
<li><a href="{% url 'sub' p.main.pk p.sub %}">{{ p.sub|verbose }}</a></li>
</ul></li><br>
{% endfor %}
</ul>
{% else %}
<h3>No products found matching your search!</h3>
{% endif %}
If the word "polo" is the title of product 2 and it's also the description of the product 1, The problem is when I'm trying to search for that word, The product 1 is rendered in the first place in the template (because it's the first matching).
What I'm trying to do is to sort the queryset first by title then by description then by sub category, so the product 2 is rendered first (because the queryset is sorted by its Q objects order)