27. Side filter for price

Next, we will develop a sidebar that enables filtering of products based on category, type, size, and price inside the store page.

Note: The price filter will be implemented as a scrolling bar ranging from minimum to maximum, while the other options (size, type, and category) will be represented as clickable buttons. Users will apply the selected filters by clicking the "apply filter" button.

Inside our store.html file, we will create a new form segment with the following code:

sotre.html
<form method="POST" action="">
    {% csrf_token %}
    <p>Price</p>
    <input type="number" name="min_price" value= "{{ minimum }}"> 
    <input type="number" name="max_price" value= "{{ maximum }}"> 
    
    <p>Size</p>
    {% for size in sizes %}
        <input type="radio" name="size" value="{{ size }}"> <!--Radio button -> choose one option, all connected to the same name. Value is what is sent to the website-->
        <label for= "{{ size }}">{{ size }}</label> <!--Button text, for tag vinculates each button the the size-->
    {% endfor %}

    <!--!Creating buttons for each filter type-->
    <p>Category</p>
    {% for category in categories %}
        <input type="radio" name="category" value="{{ category.slug }}"> 
        <label for= "{{ category.slug }}">{{ category.name }}</label>  <!--What the person sees is after the for tag, category.name-->
    {% endfor %}

    <p>Type</p>
    {% for type in types %}
        <input type="radio" name="type" value="{{ type.slug }}"> 
        <label for= "{{ type.slug }}">{{ type.name }}</label> 
    {% endfor %}

    <button type="submit">Apply Filters</button>
</form>

The sections of the code above can be summarized as follows:

Method: POST

Now, we need to define the variables min_price, max_price, and sizes within the store view to utilize them in the HTML file. We will begin by creating the minimum and maximum variables:

As the function we will use will be a auxiliary/utility function, we will create it inside the utility.py file and call it on the views.py file.

First, we need to import the Max and Min functions from the Django library. These functions enable us to filter specific data from a attribute of a class and obtain their maximum and minimum values, respectively.

utility.py
from django.db.models import Max, Min

Next, we will create the min_max_price function that returns the minimum and maximum price of a list of products:

utility.py
def min_max_price (products) :
    min_price = 0
    max_price = 0

    if (len(products) > 0) : #? rounding function doesnt work for NaN values
        min_price = list(products.aggregate(Min("price")).values())[0] #? obtaining the maximum price (attribute from the Product class)
        max_price = list(products.aggregate(Max("price")).values())[0] #? obtaining the maximum price (attribute from the Product class)
        min_price = round(min_price, 2) #? rounding to two decimal places
        max_price = round(max_price, 2) #? rounding to two decimal places
    
    return min_price, max_price

Note: When utilizing the Max and Min functions, they return an object type, and applying .values() returns a dictionary of values. To obtain the desired element, we need to transform it into a list using list(.values())[0] as seen above.

Back in the views.py file, we need to import the newly created min_max_price function and call it within the store view function:

views.py
from .utility import filter_product, min_max_price
views.py
def store(request, filter = None):
    products = Product.objects.filter(active=True) #? grabbing all products from the database (queryset, result of the search of the database)
    products = filter_product(products, filter) #? using the filter_product function to split the url from '-'
    sizes = ["P", "M", "G"]

    min_price, max_price = min_max_price(products)

    context = {"products" : products, "min_price" : min_price, "max_price" : max_price, "sizes" : sizes} 
    return render(request, 'store.html', context) 

Note: The sizes variable is currently a placeholder for testing purposes. The appropriate filtering and querying functionalities will be implemented in the next chapter. Additionally, ensure that the newly created variables are added to the context dictionary with the same names so they can be utilized in the HTML file.

Now, all of the filter information is properly displayed in the store view.

Last updated