JSS
JSS

Reputation: 174

How to format labels and form boxes when using django_filter

Very new here to django/python. I have a web page that makes use of django_filters for filtering a product view by category, and then orders them by price. I am not sure how to actually format the output in the template. Any help is appreciated:

views.py

class HomeView(ListView):
    model = Post #indicating which model to use from models.py
    template_name = 'home.html' #specify which html file to use as the template
    context_object_name = 'all_posts_list' #Default: object_list
    ordering = ['price'] #reorder by price
    paginate_by = 16
    #queryset = Post.objects.all() #Default: Model.objects.all()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['filter'] = PostFilter(self.request.GET, queryset=self.get_queryset())
        return context

filters.py

    class PostFilter(django_filters.FilterSet):

    CHOICES = (
        ('highToLow', 'Highest-to-Lowest'),
        ('lowToHigh', 'Lowest-to-Highest'),
    )

    ordering = django_filters.ChoiceFilter(label='Price', choices=CHOICES, method='filter_by_order')

    class Meta:
        model = Post
        fields = ['category']

    def filter_by_order(self, queryset, name, value):
        expression = 'price' if value == 'highToLow' else '-price'
        return queryset.order_by(expression)

html template

{% load bootstrap %}

{% block menubar %}
        <form class="form-inline" method="GET" style="color: white; font-weight: bold;">
          {{ filter.form|bootstrap }}
          &nbsp;&nbsp;<button type="submit" class="btn btn-warning">Go</button>
        </form>
{% endblock %}

Template Output

I am not sure how to actually format the labels and dropdowns being produced by the filter.form, other than adding the bootstrap |, which still does not help with spacing or alignment of labels. Again, super new and any help appreciated, direction to further documentation, reading, etc...

Upvotes: 1

Views: 1741

Answers (1)

minglyu
minglyu

Reputation: 3337

It's almost same of how you doing Form customization.

label will be showed as label for the field, also you can use a customized widget and pass placeholder, class to control how the form looks.

from django.forms.widgets import Input

django_filters.CharFilter(label='name_starts', method=filter_name_starts, 
    widget = Input(attrs={'placeholder':'filter by first letter...', 'class': 'form-control'}))

Internally, Filter class hold a default form Field as a class attribute, paramters defined on the Filter related to form are passed to form Field to render the HTML.

Then consult to Manually render django form, then you can customize the form looks in field level

EDIT

ChoiceFilter is kind of special here, if you would like to change the empty_label of the category, you need add a new line.

    CHOICES = (
        ('', '----'), # replace the value '----' with your values, served just like placeholder in CharField
        ('highToLow', 'Highest-to-Lowest'),
        ('lowToHigh', 'Lowest-to-Highest'),
    )

UPDATED

if you use class Meta: you can not override widgets in the definition time, in this case. you can do some adjustments after the filter initialized.note, this also works for other ChoiceFilter

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # change the widget choices after initialization
        self.form.fields['category'].widget.choices = [("", "please select a value"),] + list(self.form.fields["category"].choices)[1:]
        

Upvotes: 1

Related Questions