ChoiceFilter not working as expected with | crispy
opened this issue · comments
Hi all
I'm trying to combine django-filter with crispy-tailwind. The expected behavior is that the ChoiceFilter adds the selected attribute so that the filtered value would be pre-selected. The records are filtered correctly.
This works fine with:
<form method="get">
{{ filter.form.as_p }}
</form>
But doesn't work with:
<form method="get">
{{ filter.form | crispy }}
</form>
With | crispy
the ChoiceLists look beautiful, but the filtered value is not selected:
Any thoughts?
Below you'll find a few lines of code. I think I've extracted the relevant pieces. Full code is available in my objector github repository.
models.py
from django.db import models
from django.utils.translation import gettext_lazy as _
from rules.contrib.models import RulesModel
from inventory.models import Object
class Task(RulesModel):
class Statuses(models.IntegerChoices):
OVERDUE = 10, _("Overdue")
DUE = 20, _("Due")
PENDING = 30, _("Pending")
INACTIVE = 40, _("Inactive")
name = models.CharField(_("name"), max_length=200)
description = models.TextField(_("description"), blank=True)
object = models.ForeignKey(
Object,
verbose_name=_("object"),
related_name="task_object",
on_delete=models.CASCADE,
)
filters.py
from .models import Task
import django_filters
class TaskFilter(django_filters.FilterSet):
class Meta:
model = Task
fields = ["status", "object"]
views.py
from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Task
from .filters import TaskFilter
class TaskListView(LoginRequiredMixin, ListView):
model = Task
paginate_by = 10
def get_queryset(self):
# all groups for user
groups = self.request.user.groups.values_list("pk", flat=True)
groups_as_list = list(groups)
queryset = Task.objects.filter(object__owner=self.request.user)
filterset = TaskFilter(self.request.GET, queryset=queryset)
return filterset.qs
def get_context_data(self, **kwargs):
context = super(TaskListView, self).get_context_data(**kwargs)
filterset = TaskFilter(self.request.GET, queryset=self.queryset)
context["filter"] = filterset
return context
Is the selected
attribute being set on the choice? (I would expect so but have a dig into the rendered HTML)
This might be django-crispy-forms/crispy-tailwind#119 🤔
I'm calling the following URL: http://localhost:8000/task/?status=30
With {{ filter.form }}
the template generates the following output:
<select name="status" id="id_status">
<option value="" >---------</option>
<option value="10" >Overdue</option>
<option value="20" >Due</option>
<option value="30" selected>Pending</option>
<option value="40" >Inactive</option>
</select>
With {{ filter.form | crispy }}
the template generates the following output, which is missing the selected value:
<select class="bg-white ..." name="status" >
<option value="" >---------</option>
<option value="10" >Overdue</option>
<option value="20" >Due</option>
<option value="30" >Pending</option>
<option value="40" >Inactive</option>
</select>
I wanted to debug my template to figure out which values are passed to crispy, but I didn't manage. :-)
The issue might be in these files: select.html and especially select_option.html. I've compared it to the crispy-bootstrap5 repository, but there seems to be nothing similar available.
On the other hand I'm not sure if the issue is with crispy-tailwind, as there are other dropdown fields on other forms which work as expected. But these fields are on a plain form, not a filter. Thus I've raised the issue with django-filter and not crispy-tailwind.
The form is right, since the as_p()
rendering is correct. So it's a missing element in the template pack I'd think.
I think I've fixed it.
{% load crispy_forms_filters %}
{% load l10n %}
<option value="{{ value|stringformat:'s' }}" {{ field.field.widget.attrs|flatatt }}{% if field.value|stringformat:'s' == value|stringformat:'s' %} selected{% endif %}>{{ label }}</option>
With adding |stringformat:'s' to the value comparison it works for form fields and the django-filter fields. Would this solution be good enough for a pull request?
I think yes. Do open it on crispy-tailwind. I will let @smithdc1 know there's incoming. 😃
Actually there are two other pull requests on the Select feature.. so my pull request could be obsolete:
Especially the first one would make mine and the second one obsolete.
Who will guide us out on the way forward and when are crispy-tailwind releases usually made public? :-)
@gldecurtins On the last I'd likely suggest installing from GitHub as the crispy-tailwind package is still beta, and there may not be a release imminent.
Here's a link for installing from GitHub: https://pip.pypa.io/en/stable/topics/vcs-support/
I'll close this as I don't think it's a Django-filter issue.