Use filter function after clicking on button

Hi everyone !

I’m trying to use a form in order to filter my objects.

index.html

        <form id="searchForm" action="" method="GET">
            <div>
                <input type="radio" id="offers" name="search_type" value="Offers" checked=True>
                <label type="text">Offers</label>

                <input type="radio" id="requests" name="search_type" value="Requests">
                <label type="text">Requests</label>
            </div>
            <div>
                {{ form.ad_category }}
                <input type="text" name="tags" placeholder="Type in Tags">
            </div>

            <input type="submit" value="Search">
        </form>

        <div id="ad_list">
            {% for ad in ad_list %}
            <div class="box">
                <div class="box_title">
                    {{ ad.ad_title }}
                </div>
                <br>
                {{ ad.ad_description }}
                <br>
                <p>Price : </p>
                {{ ad.ad_price }}
            </div>
            {% endfor %}
        </div>

models.py

    from django.db import models

# Create your models here.
class CategoryModel(models.Model):
    category_name = models.CharField(max_length=140, default="")

    def __str__(self):
        return self.category_name

class TagModel(models.Model):
    tag_name = models.CharField(max_length=20, default="")

    def __str__(self):
        return self.tag_name

class AdTypeModel(models.Model):
    type_name = models.CharField(max_length=20, default="")

    def __str__(self):
        return self.type_name

class AdModel(models.Model):
    ad_title = models.CharField(max_length=40, default="")
    ad_description = models.CharField(max_length=320, default="")
    ad_creation_date = models.DateTimeField(auto_now_add=True, blank=True)
    ad_price = models.PositiveIntegerField(default=0)
    ad_category = models.ForeignKey(CategoryModel, related_name="ad_category", on_delete=models.CASCADE, default="")
    ad_tags = models.ForeignKey(TagModel, related_name="ad_tags", on_delete=models.CASCADE, default="")
    ad_type = models.ForeignKey(AdTypeModel, related_name="ad_type", on_delete=models.CASCADE)

    def __str__(self):
        return self.ad_title

What I’d like to do is to use what the user indicated in the form “searchForm”. If we read the GET method of this form we obtain something like :

http://localhost:8000/?search_type=Offers&ad_category=1&tags=

How can I reuse those query search items in order to route them through a view which would then allow me to use the Model.objects.filter() function ?

Thanks in advance :smiley:

In your view, you have access to the request.GET object, which holds the query variables from the URL.

So for example, you could do something in your view similar to:

search_type = request.GET.get('search_type')

Note: I use the get method to return None if there isn’t a search_type supplied in the URL.

Ken

1 Like

Hi @KenWhitesell, OK got it :wink:

Now I have another issue, what if I want to use a category “All” ?

I’ve changed my views.py as you can see hereunder :

views.py :

    from django.shortcuts import render
    from .forms import AdForm
    from .models import AdModel

    # Create your views here.
    def index(request):
    if request.method == "GET":
        request_search_type = request.GET.get("search_type")
        request_ad_category = request.GET.get("ad_category")
        request_tags = request.GET.get("tags")

        if request_ad_category == "1":
            context = {
                "form":AdForm,
                "ad_list":AdModel.objects.filter(ad_type=request_search_type),
            }

        else:
            context = {
                "form":AdForm,
                "ad_list":AdModel.objects.filter(ad_type=request_search_type,ad_category=request_ad_category),
            }

    else:
        context = {}

    return render(request,"index.html",context)

yet I’d like to change the Id number of my “All” Category to 1 instead of 5 actually.

>>> CategoryModel.objects.filter(id=5).update(id=1) 

But it doesn’t work

<db purist mode on>
Well, you really don’t. From a Database perspective, the primary key is the one invariant of a row. You shouldn’t care what its numerical value is. You also never want to refer to the pk values in your code.
Your if on the request_ad_category could more properly look like:

if request_ad_category == str(CategoryModel.objects.get(category_name='All'))

<db purist mode off>

Now, aside from that, the reason your statement didn’t work is because you can only have 1 row in your table with a given primary key, and the update method works on a queryset - it could update multiple rows - and so Django prohibits its use on the pk. (See the second paragraph of the docs)

What you would more properly need to do to avoid a conflict is change the category_name value for those primary keys.

current_all = CategoryModel.objects.get(category_name='All').pk
cm = CategoryModel.objects.get(pk=1)
current_all.category_name = cm.category_name
cm.category_name = 'All'
cm.save()
current_all.save()

Ken

1 Like

Hi @KenWhitesell,

Thanks for your help.

Well the fact is that :

http://localhost:8000/?search_type=1&ad_category=5&tags=

The “ad_category” value returned by the form is an integer converted to a string so ad_category=“5” in that case.

I just added “.id” at the end of your line and it works !

if request_ad_category == str(CategoryModel.objects.get(category_name='All').id)

Yep, I missed that. Good catch!