Cătălina Sîrbu
Cătălina Sîrbu

Reputation: 1283

Django filtering using multiple queries

On my homepage I have a search bar and when you search something it redirects you to a page with the results(titles and document types). On the left side of the page I want to implement a filter by document type.

After the search my url looks like this: http://127.0.0.1:8000/search/?q=something

After applying the filter: http://127.0.0.1:8000/search/?document_type=Tehnical+report

I don't know how to implement the filters to search just in the objects list filtered by the query (q) on the search page. Also, I'm not sure if the url should look like this : http://127.0.0.1:8000/search/?q=something&document_type=Tehnical+report or like this http://127.0.0.1:8000/search/?document_type=Tehnical+report after applying the filter.

models.py

DOCUMENT_TYPES = [
    ('Tehnical report','Tehnical report'),
    ('Bachelor thesis','Bachelor thesis'),
    ...
]

class Form_Data(models.Model):
    title           = models.CharField(unique=True, max_length=100, blank=False)
    author          = models.CharField(max_length=100)
    document_type   = models.CharField(choices=DOCUMENT_TYPES, max_length=255, blank=False, default=None)

views.py

def search_list(request):
    object_list = Form_Data.objects.none()
    document_types = DOCUMENT_TYPES

    query = request.GET.get('q')
    query_list = re.split("\s|(?<!\d)[,.](?!\d)", query)
    document_type_query = request.GET.get('document_type')

    for item in query_list:
        object_list |= Form_Data.objects.filter( Q(title__icontains=item) | Q(author__icontains=item))

    return render(request, "Home_Page/search_results.html")

home_page.html

<div class="Search">
    <form action="{% url 'home_page:search_results' %}" method="get">
        <input id="Search_Bar" type="text" name="q">
        <button id="Button_Search" type="submit"></button>
    </form>
</div>

search_results.html

{% for form_data in object_list %}
    <h5>{{ form_data.title }}</h5>
    <h5>{{ form_data.document_type }}</h5>
{% endfor %}

<form method="GET" action=".">
    <select class="form-control" name="document_type">
        {% for tag, label in document_types %}
            <option value="{{ tag }}">{{ tag }}</option>
        {% endfor %}
    </select>
</form>

Upvotes: 0

Views: 505

Answers (2)

Pulath Yaseen
Pulath Yaseen

Reputation: 415

In my opinion you are doing it the wrong way... I mean I didn't understand why you are looping your query for filtering. As far as I know it was looping every letters of your query.

I was doing it I would do it like this (using my own example):

<form action='{% url 'products:search' %}' method='get'>
    <input type='text' name='q' id='search' value='' >
    <select name='category' id='category'>
        <option value='' selected ></option>
        <option value='packet'>Packet</option>
        <option value='food'>Food</option>
        <option value='vegetable'>Vegetable</option>
    </select>
    <input type='button' value='submit' >
</form>

views.py:

def search(request):
    products = None
    query = request.GET.get('q')
    category = request.GET.get('category')
    
    if query:
        products = Product.objects.filter(
            Q(name__icontains=query)|
            Q(brand__icontains=query)
        )
    if category:
        # since it is a choice field in the model
        products |= Products.objects.filter(category=category) 

    context = {
        'products': products,
    }
    return render(request, 'products/search_products.html', context)

in this case if I press the submit button I would get a url like:

http://localhost:8000/products/search/?q=something&category=food

with this data I can filter products by name or any other fields I want.

I don't see any instance where someone would enter their query and search result will have all the products that has any of the letters entered in the input field.

Upvotes: 1

Horatiu Jeflea
Horatiu Jeflea

Reputation: 7424

This would be the model filtering:

query = request.GET.get('q')
document_type_query = request.GET.get('document_type')

object_list = FormData.objects.none()

for item in query.split():
    item_qs = FormData.objects.filter(Q(title__icontains=item) | Q(author__icontains=item))
    if document_type_query:
         item_qs = item_qs.filter(document_type=document_type_query)
    object_list |= item_qs

return render(request, "Home_Page/search_results.html", {"object_list": object_list})

And this is the URL:

http://127.0.0.1:8000/search/?q=something%20with%20spaces&document_type=Tehnical+report

Upvotes: 1

Related Questions