【问题标题】:How to format django-filters using crispy forms?如何使用清晰的表单格式化 django-filters?
【发布时间】:2021-01-13 12:12:53
【问题描述】:

是否可以使用 django-crispy-forms 格式化 django_filters 过滤器表单?我一直在尝试这样做,但django_filters.FilterSet 似乎不接受脆表单格式(来自 DeviceFilter 类)。它也没有给出错误。似乎唯一能够给出格式的是{{ filter.form|crispy }},但我希望能够在python中使用FormHelper()

filters.py

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column
import django_filters

class DeviceFilter(django_filters.FilterSet):

    device_type = django_filters.ModelChoiceFilter(lookup_expr='exact', field_name='device_type__pk',
                                                   queryset=None)
    device_group = django_filters.ModelChoiceFilter(lookup_expr='exact, field_name='device_group__pk',
                                                   queryset=None)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.filters['device_type'].queryset = DeviceType.objects.filter(owner=self.request.user)
        self.filters['device_group'].queryset = DeviceGroup.objects.filter(owner=self.request.user)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Row(
                Column('device_type', css_class='form-group col-md-6 mb-0'),
                Column('device_group', css_class='form-group col-md-4 mb-0'),
                css_class='form-row'
            ),
            Submit('submit', 'filter')
        )

    class Meta:
        model = Device
        fields = {}

模板

<!-- filter -->
{% if filter %}
    <form method="get">
        {{ filter.form|crispy  }}
    </form>

{% endif %}

更新

我分享我的最终解决方案。这会呈现:

class DeviceForm(forms.ModelForm):

    class Meta:
        model = Device
        fields = [
            'device_id',
            'device_type',
            'device_group',
        ]


    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Row(
                Column('device_created', css_class='form-group col-12'),
                css_class='form-row'
            ),
            Row(
                Column('device_id', css_class='form-group col-12'),
                css_class='form-row'
            ),
            Row(
                Column('device_type', css_class='form-group col-6 mb-0'),
                Column('device_group', css_class='form-group col-6 mb-0'),
                css_class='form-row'
            ),
        )

class DeviceFilter(django_filters.FilterSet):

    device_created = django_filters.DateTimeFromToRangeFilter(label='', widget=MyRangeWidget(
        {
            'class': 'datetimepicker form-control',
            'placeholder': 'From'
        }, {
            'class': 'datetimepicker form-control',
            'placeholder': 'To'
        }
    ))


    device_id = django_filters.CharFilter(label='', lookup_expr='icontains', widget=TextInput(attrs={
        'placeholder': 'Enter Device Id'
    }))

    device_group = django_filters.ModelChoiceFilter(label='', lookup_expr='exact',
                                                    field_name='device_group__pk',
                                                    queryset=None, empty_label=('Select Group'))

    device_type = django_filters.ModelChoiceFilter(label='', lookup_expr='exact',
                                                   field_name='device_type__pk',
                                                   queryset=None, empty_label=('Select Type'))


    class Meta:
        form = DeviceForm

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.filters['device_type'].queryset = DeviceType.objects.filter(owner=self.request.user)
        self.filters['device_group'].queryset = DeviceGroup.objects.filter(owner=self.request.user)

【问题讨论】:

    标签: django django-filter django-crispy-forms


    【解决方案1】:

    尝试将助手设置为表单

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Your code
        self.form.helper = FormHelper()
        # Your code
    

    或者尝试在元类中设置表单

    class DeviceFilter(django_filters.FilterSet):
        # Your code
        class Meta:
            form = YourCustomFormClass
    

    【讨论】:

    • 是否可以将表单类传递给 FilterSet 以用作基本表单?
    • 是的,请阅读文档中的this
    【解决方案2】:

    这个 Github gist 有一个非常好的解决方案。关键部分是定义一个基类(作者称他们为FilteredSingleTableView),您的表视图将从该基类继承。基类有一个formhelper_class 类属性,子类可以使用它来指向定义布局的 Crispy Form 的 FormHelper 子类

    这是他们的那部分代码。我不会重新发布其余的,因为链接更容易关注

    from django_filters.views import FilterView
    from django_tables2 import SingleTableMixin
    
    
    class FilteredSingleTableView(SingleTableMixin, FilterView):
        """Base class for table filtering with crispy forms
    
        Subclasses should override the formhelper_class
        """
    
        formhelper_class = None
    
        def get_filterset(self, filterset_class):
            """Where the magic happens
    
            Add the helper class to the pre-existing form from django-filters
            """
    
            kwargs = self.get_filterset_kwargs(filterset_class)
            filterset = filterset_class(**kwargs)
            filterset.form.helper = self.formhelper_class()
            return filterset
    

    【讨论】:

      猜你喜欢
      • 2014-07-16
      • 2015-04-14
      • 2014-07-19
      • 2020-02-17
      • 2011-07-24
      • 2012-10-07
      • 2012-08-18
      • 2012-04-20
      • 1970-01-01
      相关资源
      最近更新 更多