toto290
toto290

Reputation: 49

Change layout of django-filter form

I am currently working on my first bigger django project and I am facing issues regarding the layout of my data filters made with django-filters. The default layout of the django-filter form is a vertical list (see image), but I need to make it horizontal, consisting of two rows (labels/fields). enter image description here

What is the (best practice) way to edit the layout? Is there a way I can access every Label/Field-Item of the form from within the template, so I can use Bootstrap5 Grid?

One restriction is, that my template will be used by differents models/filters, so I need to configure the layout dynamically.

Every hint is very much appreciated :) Thank you!

My template (relevant section)

<form method="get" class="form">
       <button type="submit" class ="btn btn-primary">Filtern</button>
       {% crispy filter.form %}
</form>

my django-filter filter class

class EquipmentFilter(FilterSet):
    class Meta:
        model = Equipment
        fields = {'name': ['icontains'], 'description': ['icontains']}

my model

class Equipment(models.Model):
    """Device that can execute a measurement"""
    name = models.CharField("Name", max_length=50)
    description = models.CharField("Description", max_length=100)
    configuration = models.JSONField("Configuration", default=dict)
    equipment_category = models.ForeignKey("EquipmentCategory", on_delete=models.CASCADE, verbose_name="Equipment Category")

Upvotes: 3

Views: 2405

Answers (2)

dani herrera
dani herrera

Reputation: 51715

I use class based views, my solution is to override get_context_data and massage the form there:


class EquipmentListView(
       SingleTableMixin,
       FilterView):

    model = Equipment
    table_class = EquipmentTable
    template_name = 'equipment/tables2/list.html'
    filterset_class = EquipmentFilter

    # override get_context_data
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        filter = context['filter']
        form = filter.form             # <- here!
        form.helper = FormHelper()
        form.helper.add_input(
            Submit('submit', 'Filter', css_class='btn-primary')
        )
        return context

Upvotes: 0

Cyrille Pontvieux
Cyrille Pontvieux

Reputation: 2471

filter.form is a normal Django form, so you can layout it the way you want.

I see that you use crispy forms. But you can style it anyway you want, boostrap-way included.

Here is an example from the official documentation

You can use the .as_p method to get them in <p><label><input></label></p> format or you can generate them by hand:

<form method="get" class="form">
  <button type="submit" class ="btn btn-primary">Filtern</button>
  {{ filter.form.non_field_errors }}
  <div class="boostrap-class">
    {{ filter.form.name.errors }}
    <label for="{{ filter.form.name.id_for_label }}" class="another-boostrap-class">Name</label>
    {{ filter.form.name }}
  </div>
  <div class="boostrap-class">
    {{ filter.form.description.errors }}
    <label for="{{ filter.form.description.id_for_label }}" class="another-boostrap-class">Description</label>
    {{ filter.form.description }}
  </div>
</form>

You can also specify a custom Form class in your filterset meta (EquipmentFilter.Meta) and use techniques presented in this other SO question

Upvotes: 4

Related Questions