I'm trying to create a drop down form as a filter but its not working, and I'm trying to have a text field along with it. The two model fields that the fields are pulling from are a TextField and CharField respectively.
filters.py
import django_filters as df
from django import forms
from django.utils.translation import ugettext_lazy as _
from .models import FoodTruck
class FoodTruckFilter(df.FilterSet):
category_queryset = FoodTruck.objects.exclude(category='').values_list('category', flat=True).distinct().order_by('category')
category_drop_down = df.ModelChoiceFilter(queryset=category_queryset)
class Meta:
model = FoodTruck
fields = {
'name': ['icontains'],
'category': ['icontains'],
}
labels = {
'name': _('Food Truck Name'),
'category': _('Category'),
}
#widget = {
# 'name': forms.TextInput(attrs={'class': 'form-control'}),
# 'category': forms.Select(attrs={'class': 'form-control'})
#}
models.py
class FoodTruck(models.Model):
name = models.CharField(max_length=25)
category = models.CharField(max_length=20)
bio = models.TextField()
avatar_url = models.URLField(blank=True)
avatar_alt_text = models.CharField(max_length=20, blank=True)
avatar_title = models.CharField(max_length=20, blank=True)
cover_photo_url = models.URLField(blank=True)
cover_photo_alt_text = models.CharField(max_length=20, default="No photo provided")
cover_photo_title = models.CharField(max_length=20, default="No photo provided")
website = models.URLField(blank=True, null=True)
facebook = models.URLField(max_length=100, blank=True, null=True)
instagram = models.CharField(max_length=30, blank=True, null=True)
twitter = models.CharField(max_length=50, blank=True, null=True)
def __str__(self):
return self.name
views.py
class TruckListView(generic.ListView):
model = FoodTruck
template_name = 'truckReviews/landing.html'
ordering = 'name'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = FoodTruckFilter(self.request.GET, queryset=self.get_queryset())
return context
landing.html
{% extends "truckReviews/base.html" %}
{% block content %}
<!--Filter Nav-->
<nav class="d-flex justify-content-center align-items-center sticky-top mt-2">
<form method="get" class="border rounded p-2 bg-light">
{% for field in filter.form %}
<span class="form-group">
<label for="{{ field.id_for_label }}" class="control-label">
{{ field.label }}:
</label>
{{ field }}
</span>
{% endfor %}
<button type="submit" class="btn btn-success">Search</button>
</form>
</nav>
<!--Food Truck Cards-->
<div class="d-flex flex-row flex-wrap justify-content-around">
{% for truck in filter.qs %}
<div class="card mb-2 mt-2" style="width: 20rem;">
<img src="{{ truck.cover_photo_url }}" alt="{{ truck.cover_photo_alt_text }}" class="card-img-top">
<div class="card-body">
<h5 class="card-title"> {{ truck.name }}</h5>
<h6 class="card-text text-muted">{{ truck.category }}</h6>
<p class="card-text" style="font-size: 0.8rem;"> {{ truck.bio }}</p>
<a href="{% url 'truck-review' truck.truck %}" class="btn btn-outline-info">View Truck</a>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
Here are some pictures trying to explain whats happening:
Filter nav: https://i.sstatic.net/W2VAY.png
When I try to search using 'category_drop_down', it still shows all the food trucks from all categories.
https://i.sstatic.net/y9Kxn.png
But when I use the text field, it filters the trucks properly.
https://i.sstatic.net/5pz4o.png
How can I make it so the filter uses the drop down menu instead of the text field?
Also, how can I change the labels of the form fields, and add classes to them. I tried using the code below but it didn't work.
labels = {
'name': _('Food Truck Name'),
'category': _('Category'),
}
widget = {
'name': forms.TextInput(attrs={'class': 'form-control'}),
'category': forms.Select(attrs={'class': 'form-control'})
}
Thank you in advance for any help.
To change the labels, add the following on your FoodTruckFilter:
def __init__(self, *args, **kwargs):
super(FoodTruckFilter, self).__init__(*args, **kwargs)
self.filters['name__icontains'].label = 'Food Truck Name'
self.filters['category__icontains'].label = 'Category'