29. Applying the filters

Now, with all the filters being properly displayed, we will be able to apply their functionalities.

Below is the updated code with the necessary changes, and a explanation for them.

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 '-'

    #! Applying the filters from the form
    if request.method == 'POST':
        data = request.POST.dict() #? converts the request data to a dictionary
        products = products.filter(price__gte=data.get('min_price'), price__lte=data.get('max_price'))
        if "size" in data :
            items = ItemStock.objects.filter(product__in=products, size=data.get('size')) 
            id_product = items.values_list("product", flat=True).distinct()
            products = products.filter(id__in=id_product)
        if "type" in data :
            products = products.filter(product_type__slug=data.get('type'))
        if "category" in data :
            products = products.filter(category__slug=data.get('category'))

    items = ItemStock.objects.filter(quantity__gt=0, product__in=products) #? getting the items of that product that have a quantity greater than 0
    sizes = items.values_list("size", flat=True).distinct() #? getting the sizes of the items, flat parameter makes it return a single-column list of values instead of tuple
    
    #? making only the available categories and types appear
    id_type = products.values_list("product_type", flat=True).distinct()
    types = Type.objects.filter(id__in=id_type)
    id_categories = products.values_list("category", flat=True).distinct()
    categories = Categoric.objects.filter(id__in=id_categories)

    
    min_price, max_price = min_max_price(products)

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

The changes made above were:

  • Add condition to handle form submission for filters.

  • Store filter data in a dictionary format upon form submission.

  • Filter products based on price immediately (default filter).

  • Check for additional filters: "size", "type", and "category".

    • Size Filter:

      • Obtain sizes from item stock class for specific product.

      • Update product list to include only products with matching sizes (using id_product).

    • Category and Type Filters:

      • Directly filter products using their slugs from the Product class (values from HTML form).

  • Ensure size, category, and type buttons appear based on product availability:

    • Obtain IDs and filter in respective classes.

    • Use values inside the context variable.

To maintain the immutability of the navbar content, we need to address the issue of duplicate names used in the store_view function. The type filter in the navbar shares the same variable names, leading to potential conflicts. To resolve this, we will rename the variables within the category_type function located in the new_context.py file. This ensures clarity and prevents naming collisions while preserving the integrity of the navbar's static content.

updated new_context.py
def category_type(request) :
    categories_navbar = Categoric.objects.all() 
    types_navbar = Type.objects.all()
    return {"categories_navbar" : categories_navbar, "types_navbar" : types_navbar}
The filtering functionalities are now operating as intended.

Last updated