简体   繁体   中英

django-filters: How do I use ModelChoiceFilter, unable to add classes to form fields and unable to set form labels

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.stack.imgur.com/W2VAY.png

When I try to search using 'category_drop_down', it still shows all the food trucks from all categories.
https://i.stack.imgur.com/y9Kxn.png

But when I use the text field, it filters the trucks properly.
https://i.stack.imgur.com/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'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM