0

I want to add such filters to my internet shop:

Color:
 # red
 # blue
 # green
Material:
 # plastic
 # wood
 # metal

where each of points is a checkbox, color and material are fields of some Django model.

For example if i'm looking for red or blue toys with plastic material, i'll find it in such way:

filtered = SomeModel.objects.filter(material=plastic, color=red, color=blue)

But how to filter it dynamically?(if i have many filters)

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Ihor
  • 97
  • 10

4 Answers4

1
# Import
from django.db.models import Q

filter_query = Q()

# Get colors to be filtered
filter_color_list = ['red', 'blue']

# Add Filter by colors
filter_query.add(Q(color__in=filter_color_list), Q.AND)

# Get materials to be filtered
filter_material_list = ['plastic']

# Add filter by material
filter_query.add(Q(material__in=filter_material_list), Q.AND)

# Get filtered objects
filtered = SomeModel.objects.filter(filter_query)

You can add as many filters you want in filter_query, and if none of the filters added it will return all objects of the model.

ksmehta
  • 61
  • 3
0

You can do like

query = SomeModel.objects.filter(material='plastic')
if any_bool_condition:
    query = query.filter(color='red')

and you can keep adding filter on query.

For OR condition, you should look https://stackoverflow.com/a/6567918/3864717

Aniket Singh
  • 2,464
  • 1
  • 21
  • 32
0

Build your tuple with the colours you want, then use that in the query with __in.

Also, I've put strings in here, but if you're not already doing it, I'd suggest using an enum for things like this (unless the colours are user defined somehow maybe).

# this would be set from incoming checkbox values, and may be empty:
colours_to_filter = ('red', 'blue', 'green')
materials_to_filter = ()

query = SomeModel.objects.all()
if colours_to_filter:
    query = query.filter(colour__in=colours_to_filter)

if materials_to_filter:
    query = query.filter(material__in=materials_to_filter)

michjnich
  • 2,796
  • 3
  • 15
  • 31
  • How to connect checkboxes to filters? And what if user doesn't want to choose colors(it's not important for him)? – Ihor Jun 15 '21 at 07:33
  • If you're doing this with "pure" django and no javascript filtering, then you would have the checkbox values in your view and could handle them accordingly. How you handle which parameters are used for selection is up to you, but a simple solution might be if they select no colours, to not use that filter at all. – michjnich Jun 15 '21 at 07:49
  • I updated my answer to give you an idea how to handle that ... – michjnich Jun 15 '21 at 07:51
0

I usually do these filterings by using query parameters.
It's based on what users checks for filtering whether it's multiple values or None values.

qs = SomeModel.objects.all()

material = request.GET.get("material")
color = request.GET.get("color")

if material:
    qs = qs.fitler(material__in=material)
if color:
    qs = qs.fitler(color__in=color)  

Notice that there is a package called django-filter. you can use this package for your filterings and it's pretty useful.
And your form would be like this: (EXAMPLE)

<form action="{% url 'view_url' %}" method="GET">
    <input type="checkbox" name="color" value="RED">
    <input type="checkbox" name="color" value="GREEN">
    <input type="checkbox" name="color" value="BLUE">
    <button type="submit" value="Submit">Submit</button>
</form>
Mojtaba Arezoomand
  • 2,140
  • 8
  • 23
  • how to connect both variables material and color to group of checkboxes? – Ihor Jun 15 '21 at 09:01
  • what do you mean? users checks the colors or etc that he wants and your filtering will work, do you mean what is the html code ? – Mojtaba Arezoomand Jun 15 '21 at 09:03
  • I don't understand where material and color gets information. I need to create checkboxes for it?Or django-filter does it myself? Or i need to create forms for every item and all my checked checkboxes will be included into request.GET? – Ihor Jun 15 '21 at 09:04
  • no you don't need to create check box for all of your items, you create a form with the `get` method for your page. whenever user select some filtering and submit the form you can get them in your view with `request.GET`. because your form method is `GET` so they will go in the `request.GET` – Mojtaba Arezoomand Jun 15 '21 at 09:10
  • if for example your user check filtering for the color then the `color = request.GET.get("color")` won't be `None` and you will filter your query by using the color or colors that user has checked `qs = qs.fitler(color__in=color)` – Mojtaba Arezoomand Jun 15 '21 at 09:12
  • Could you show me an example?It'd be helpful for me – Ihor Jun 15 '21 at 09:13
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/233784/discussion-between-ihor-and-mojixcoder). – Ihor Jun 15 '21 at 09:18
  • i have updated the answer check it out @Ihor – Mojtaba Arezoomand Jun 15 '21 at 09:20