【问题标题】:Conditionally display a Fieldset with Crispy Forms有条件地显示带有 Crispy 表单的字段集
【发布时间】:2016-08-10 22:01:06
【问题描述】:

我想在使用 Crispy Forms 时做一些简单的事情;我只想在用户属于员工组时才显示字段集。这可以在这样的标准模板中轻松解决:

{% if user.is_staff %} show extra stuff {% endif %}

也许我错过了手册中的某些内容,但我不明白如何将“{% if user.is_staff %}”之类的模板标签注入到清晰的表单布局中。如果我可以使用虚构的“Djangotag”来解决我的问题,那将是我的用例的理想选择:

self.helper.layout = Layout(
   Fieldset(
       'Section One',
       'name',
       'description',
   ),
   Djangotag('{% if user.is_staff %}'),
   Fieldset(
       'Conditional Fieldset',
       'field1',
       'field2',
   ),
   Djangotag('{% endif %}'),      
   Fieldset(
       'More Details',
       'detail1',
       'detail2',
   ),
  )

有没有一种简单的方法可以用脆的形式做到这一点?


注意:我已经实现了self.user = kwargs.pop('user') 方法,它不是很优雅,我还在寻找更好的东西。

我还尝试为 if 语句创建简单的模板,并尝试了 HTML("{% include 'helpers/is_staff.html' %}"), 但渲染过程失败。

【问题讨论】:

    标签: python django django-forms django-crispy-forms


    【解决方案1】:

    您可以将请求上下文从视图传递给您的表单,然后在您的表单助手中使用它。像这样的:

    在创建表单的视图函数中:

    form = MyForm(request.POST, user=getattr(request, 'user', None))
    

    然后在表单的__init__ 方法中:

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        super(MyForm, self).__init__(args, kwargs)
    

    最后在你的表单布局代码中:

    if user and user.is_staff:
        self.helper.layout.append(Fieldset(
            'Conditional Fieldset',
            'field1',
            'field2',
        ),
    

    我刚刚将此字段集附加到布局的末尾。 documentation 为您提供了动态更新布局的其他选项。

    【讨论】:

    • 这正是我开始实施的方法。然后意识到我将不得不在附加字段和小部件等方面胡思乱想。Django 框架非常优雅地解决了这个用例,即使它有效,这个 hack 很快就会变得丑陋并且对我来说似乎无法接受。
    【解决方案2】:

    我没有找到更干净的方法,所以我按照我开始的方式完成了它。

    这里是视图...

    class ModelCreateView(LoginRequiredMixin, CreateView):
    ....
    def get_form_kwargs(self):
        # I am going to stuff the user object into the view so that 
        # I can use it in ModelForm to check the user and build the form
        # conditionally
        kwargs = super(ModelCreateView, self).get_form_kwargs()
        kwargs.update({'user': self.request.user})
        return kwargs
    

    在 ModelForm 中,最简单的假设是始终需要这些字段——所以我在元部分中声明了它们——然后有条件地删除这些字段,并有条件地附加表单...

    class YourCrispyForm(forms.ModelForm):
    ....
    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')
        super(YourCrispyForm, self).__init__(*args, **kwargs)
    
        # remove conditional fields
        if self.user and self.user.is_staff:
            pass
        else: 
            del self.fields['field_name'] 
            del self.fields['field_name'] 
            del self.fields['field_name']
    
        if self.user and self.user.is_staff:
            self.helper.layout.append(  
            Fieldset(
                'Conditional Sections',
                Row(
                    Div('field_name', css_class="col-md-2"), 
                    Div('field_name', css_class="col-md-2"),
                    ...
                ),
              )
            )
    

    我花了一段时间才意识到删除是要走的路。希望能对以后的人有所帮助。

    【讨论】:

      【解决方案3】:

      用 Python(TM) 实现

      清晰表单的核心思想是在 Python 中做更多的事情,而在模板中做更少的事情。 因此,我的脆皮表格通常是这样称呼的

        {% crispy form form.get_formhelper %}
      

      get_formhelper 函数中,我从头开始以附加方式构建Layout 对象,所有这些都以编程方式进行,只要需要动态适应,就像这样:

      import crispy_forms.helper as cfh
      import crispy_forms.layout as cfl
      
      def get_formhelper():
          helper = cfh.FormHelper()   
          layout = cfl.Layout()
          fieldset = cfl.Fieldset("Fieldset Title")
          fieldset.fields.append('myfield')
          ...
          layout.fields.append(fieldset)
          ...
          helper.layout = layout
          return helper
      

      这提供了最大的灵活性,并使布局逻辑与其他表单逻辑很好地分开。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-31
        • 2022-01-04
        • 2011-10-06
        • 2016-07-13
        • 1970-01-01
        • 1970-01-01
        • 2014-12-21
        • 1970-01-01
        相关资源
        最近更新 更多