【问题标题】:crispy form field type attribute ignored脆皮表单字段类型属性被忽略
【发布时间】:2021-02-16 19:54:21
【问题描述】:

我正在尝试在我的 django 应用程序中使用清晰的表单,但我似乎无法在字段上设置类型属性。

#forms.py
class ReminderForm(ModelForm):

    def __init__(self,*args,**kwargs):
        super().__init__(*args,**kwargs)
        self.helper=FormHelper()
        self.helper.layout = Layout(
            Fieldset('Reminder',
                Row(
                    Div(Field('message'),css_class="col"),
                    ),
                Row(
                    Div(Field('messagetype'),css_class="col-md-6"),
                    Div(Field('account'),css_class="col-md-6"),
                    ),
                Row(
                    Div(Field('reminddate',type="date"),css_class="col-md-6"),
                    Div(Field('duedate', type="date"),css_class="col-md-6"),
                    ),
                
            )  
        )

    class Meta:
        model=Reminder
        exclude=['sentdate','confirmdate','completedate']

我的模态表单

{% load cms_tags crispy_forms_tags %}

<div class="modal fade" id="{{formid}}" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">{{title}}</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <form >
        {% crispy form %}
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

为下面的输入渲染的 html 显示了 type="text" 的提醒日期和到期日样式

<div class="modal-body">
        <form>
 <fieldset> <legend>Reminder</legend> <div class="form-row "> <div class="col"> <div id="div_id_message" class="form-group"> <label for="id_message" class="">
                Message
            </label> <div class=""> <textarea name="message" cols="40" rows="10" class="textarea form-control" id="id_message"></textarea> </div> </div> </div>

</div>
<div class="form-row "> <div class="col-md-6"> <div id="div_id_messagetype" class="form-group"> <label for="id_messagetype" class="">
                Messagetype
            </label> <div class=""> <select name="messagetype" class="select form-control" id="id_messagetype"> <option value="">---------</option> <option value="email">Email</option> <option value="sms">Text Message</option> <option value="internal">Internal Website</option>

</select> </div> </div> </div>
<div class="col-md-6"> <div id="div_id_account" class="form-group"> <label for="id_account" class="">
                Account
            </label> <div class=""> <select name="account" class="select form-control" id="id_account"> <option value="" selected="">---------</option> <option value="4">jim.pm</option> <option value="2">joe.sp</option> <option value="3">sally.om</option> <option value="1">sparrow</option>

</select> </div> </div> </div>

</div>
<div class="form-row "> <div class="col-md-6"> <div id="div_id_reminddate" class="form-group"> <label for="id_reminddate" class=" requiredField">
                Reminddate<span class="asteriskField">*</span> </label> <div class=""> <input type="text" name="reminddate" class="datetimeinput form-control" required="" id="id_reminddate"> </div> </div> </div>
<div class="col-md-6"> <div id="div_id_duedate" class="form-group"> <label for="id_duedate" class=" requiredField">
                Duedate<span class="asteriskField">*</span> </label> <div class=""> <input type="text" name="duedate" class="datetimeinput form-control" required="" id="id_duedate"> </div> </div> </div>

</div> </fieldset> </form>

        
      </div>

rendred form

如何正确设置类型属性?其他属性(自定义属性)工作正常。

【问题讨论】:

    标签: django django-crispy-forms


    【解决方案1】:

    @Martin Beran 为我指明了正确的方向。由于我试图继续使用 {% crispy form %} 方法...我发现使用 Meta 类中的小部件覆盖提供了我需要的东西!

        class Meta:
            model=Reminder
            exclude=['sentdate','confirmdate','completedate']
            widgets = {
                'reminddate': forms.DateInput(attrs={'type':'date'}),
                'duedate': forms.DateInput(attrs={'type':'date'})
            }
    

    Form with bootstrap date control

    【讨论】:

    • 我也用过,但是有问题,可能是SplitDateTimeWidget,所以我做了模板过滤器
    【解决方案2】:

    哦,你想要 type=date,这是一个棘手的问题……你应该制作自己的小部件,但如果你像我一样懒惰,你可以使用模板过滤器来解决:

    from django import forms
    from django import template
    from django.utils.safestring import mark_safe
    
    register = template.Library()
    
    
    @register.filter
    def set_input_type(field, field_type=None):
      if field_type:
        pass
      elif isinstance(field.field.widget, forms.DateInput):
        field_type = 'date'
      elif isinstance(field.field.widget, forms.TimeInput):
        field_type = 'time'
      elif isinstance(field.field.widget, forms.SplitDateTimeWidget):
        for subfield in field.field.widget.widgets:
          if isinstance(subfield, forms.DateInput):
            subfield.input_type = 'date'
          elif isinstance(subfield, forms.TimeInput):
            subfield.input_type = 'time'
      elif isinstance(field.field.widget, forms.DateTimeInput):
        # field_type = 'datetime-local'  # can't work with passing/returning ISO format
        # field_type = 'datetime'  # is deprecated, doesn't work in many browsers
        # use widget=forms.SplitDateTimeWidget() instead
        pass
    
      if field_type:
        field.field.widget.input_type = field_type
    
      return field
    

    这样您就可以更改模板中的类型,例如

    {{ form.dt|set_input_type:'date' }}
    

    但是如果你只使用{% crispy form %},你必须走第一种(首选)方式并制作你自己的小部件:)

    还有一种方式是使用JS,比如$('#id_reminddate').attr('type', 'date');

    顺便说一句,他们可能使用 type=text,因为 type=date 在桌面浏览器中很难看,所以你可以使用一些 JS 库,比如 jqueryui 来做 callendars

    【讨论】:

    • 你能澄清一下吗?我没有看到小部件如何解决能够专门使用易碎的表单布局设置 html 标记属性的问题。最终目标是利用 bootstrap4 进行显示。
    • sry,我改变了答案,我之前没听懂你
    • 小部件答案为我指明了正确的方向,但我只需要覆盖现有的 Meta 小部件。查看完整答案
    猜你喜欢
    • 2019-04-24
    • 2017-11-14
    • 2014-11-13
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-01
    • 2017-07-22
    相关资源
    最近更新 更多