Jekson
Jekson

Reputation: 3272

How to add custom css class to django-filters field

I tried to make a way that worked with forms, but here the class did not apply

class TrainerFilter(django_filters.FilterSet):
    price_lt = django_filters.NumberFilter(field_name="prise", lookup_expr='lt')
    class Meta:
        model = Profile
        fields = ['direction', 'group', 'child', 'price_lt']
        widgets = {
            'direction': SelectMultiple(attrs={'class': 'custom-select'}),     
        }

Upvotes: 7

Views: 6260

Answers (6)

FlexW
FlexW

Reputation: 1

I found a pretty simple solution:

  1. Open your dev tools and look at the element generated by django-filters
  2. django-filters have assigned the element an id like 'id_field'
  3. so just use that id in your CSS to style that element.

Upvotes: 0

AgainstAO
AgainstAO

Reputation: 11

IMPORTANT: read the bottom paragraph as I discovered an issue doing it this way and have linked to a source that explains how to use this in tandem with widget tweaks to add custom css to the filters.

From the official documentation.

Djano_Filters Docmentation

Simply put, add a field into filters meta class named "form" that uses a forms.py class as its value, like so. This effectively extends your forms.py class.

Adding form field to a filter

Customize Field Types:
From there you can do customize the fields types like you normally for forms.py like so.

enter image description here

Actually styling the page using CSS
From here you got three options. My least favorite (leads to alot more code). Use widget tweaks to style it on the page. Use boot strap (or really any css files class). Or the most effective way use both boot strap and widget_tweaks while creating templates for your forms.

However, unless your doing really complicated filtering or querying stuff for 90% of use cases you could do something like the following in your forms.py class to make it pretty easy.

Note: I have since found this method unreliable read the bottom paragraph for a solution enter image description here

IMPORTANT: Django filters unreliably applies the CSS to these fields extending the forms class but it does allow you to still customize the help text, the widgets used, and etc. so I'm leaving it in the answer. It worked for me initially but after expanding the filter to do more complicated things I realized some fields where getting arbitrarily left out. Below is an article that details how to use Django-filters WITH a custom widget tweaks file that does this for you. Django-filters how to and widget tweaks with css styling

Upvotes: 0

Xin Liang
Xin Liang

Reputation: 21

class UsersFilter(django_filters.FilterSet):
class Meta:
    model = UsersModels
    fields = ['username', 'email', 'first_name', 'phone']
    filter_overrides = {
        models.CharField: {
            'filter_class': django_filters.CharFilter,
            'extra': lambda f: {
                'lookup_expr': 'icontains',
                'widget': forms.TextInput(attrs={'class': 'form-control'})
            },
        },
        models.EmailField: {
            'filter_class': django_filters.CharFilter,
            'extra': lambda f: {
                'lookup_expr': 'icontains',
                'widget': forms.EmailInput(attrs={'class': 'form-control'})
            },
        },

    }

like this

Upvotes: 2

Liam Hanninen
Liam Hanninen

Reputation: 1583

You were pretty close. This should work:

class TrainerFilter(django_filters.FilterSet):
    price_lt = django_filters.NumberFilter(field_name="prise", lookup_expr='lt')
    direction = django_filters.CharFilter(widgets = SelectMultiple(attrs={'class': 'custom-select'}))
    class Meta:
        model = Profile
        fields = ['group', 'child', 'price_lt']

Upvotes: 3

Mini_Me
Mini_Me

Reputation: 96

In case somebody stumbles upon this, one solution might be to add the class to the field's widget attrs, like so:

    class TrainerFilter(django_filters.FilterSet):

        ...

        def __init__(self, data=None, queryset=None, *, request=None, prefix=None):
            super(TrainerFilter, self).__init__(data=data, queryset=queryset, request=request, prefix=prefix)
            self.filters['direction'].field.widget.attrs.update({'class': 'custom-select'})

Upvotes: 4

Jekson
Jekson

Reputation: 3272

The easiest way I found is using django widget tweaks. And this module can be used with different kinds of forms, not just with filters. After installations add to template

{% load widget_tweaks %}

And now you can add class for your forms like this

{{ filter.form.direction.label_tag }}
{% render_field filter.form.direction class="custom-select" %}

insread

{{ filter.form.direction.label_tag }}
 {{ filter.form.direction }}

Upvotes: 1

Related Questions