mharre
mharre

Reputation: 263

Django - Altering list view based on link that is pressed

I have a navbar above my products on my fake e commerce website that I am building. I render this view through list view. In this navbar I have a search area that works fine, and want to add the ability to filter the results based on what is pressed. For example, I have styles: realism, portrait, etc in the navbar. When I click on realism I want the results to change to all realism paintings that are in the DB.

My question is what would be the best way to accomplish this? Could I alter the original list view? Or would I just need to create an entirely new view based on the specific queries I need? Any help is greatly appreciated!

Also attached will be a picture to show you what I mean in case my explanation wasn't the best.

view:

class AllProductView(ListView):
    template_name = 'my_site/all_products.html'
    model = Product
    ordering=['id']
    paginate_by = 9
    context_object_name = 'products'

enter image description here

product model as requested:

class Product(models.Model):
    name = models.CharField(max_length=120)
    shortened_name = models.CharField(max_length=50)
    date_of_creation = models.CharField(max_length=20, null=True)
    history = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=9, decimal_places=2)
    discount_price = models.FloatField(blank=True, null=True)
    style = models.CharField(max_length=50)
    artist = models.ForeignKey(Artist, on_delete=models.SET_NULL, null=True)
    image = models.ImageField(upload_to='images', null=True)
    slug = models.SlugField()

Upvotes: 2

Views: 147

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476544

You can filter by overriding the .get_queryset(…) method [Django-doc]:

class AllProductView(ListView):
    template_name = 'my_site/all_products.html'
    model = Product
    ordering=['id']
    paginate_by = 9
    context_object_name = 'products'

    def get_queryset(self, *args, **kwargs):
        qs = super().get_queryset(*args, **kwargs)
        fltr = self.kwargs['style']
        if fltr != 'all':
            qs = qs.filter(style=self.kwargs['style'])
        return qs

In your urls.py, you can then use a <str:…> path converter to determine the style we want to filter on, so:

path('products/<str:style>/', AllProductView.as_view(), name='products')

In the templates, we can then write URLs with:

<a href="{% url 'products' style='realism' %}">Realism</a>

This will than link to a page that only shows Products with style='realism'.

Upvotes: 2

Related Questions