Django分多次渲染(输出)同一个form

Django中在模板上通过{{form}}即自动可生成表单内容,提供了非常便捷和强大的功能。这种功能虽然强大,但却不能满足很多的需求,比如一个表单的内容非常多,在页面上希望通过Tab将信息"分门别类"的隔开,Django内置的功能就无能为力了。

好在Django是开源产品,可以通过修改其代码,为其增加自定义输出字段的能力,即可很方便的达到目的。主要修改form的.as_table,as_ul,as_p等方法,为其增加一个待渲染字段列表即可。为了确保Django后续平滑升级,一般我们不会直接修改Django代码,借助Python的多重继承机制,可以非常轻松的为Django打上这个补丁。需要具备这种能力的form只需要先集成自定义的这个混入类(Mixin),然后再按照原有的方式继承form即可。

如:

UserForm(PartialRenderFormMixin,forms.ModelForm):
    class Meta:
        model = User
    def render_baseinfo(self):
        return self.as_table(('username','first_name','last_name'))
    def render_extinfo(self):
        return self.as_table(('email',))

PartialRenderFormMixin代码:

class PartialRenderFormMixin():
    def _html_output(self,render_fields, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row):
        "Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
        top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
        output, hidden_fields = [], []

        for name, field in self.fields.items():
            if render_fields and  not name in render_fields:
                continue
            html_class_attr = ''
            bf = self[name]
            bf_errors = self.error_class([conditional_escape(error) for error in bf.errors]) # Escape and cache in local variable.
            if bf.is_hidden:
                if bf_errors:
                    top_errors.extend([u'(Hidden field %s) %s' % (name, force_unicode(e)) for e in bf_errors])
                hidden_fields.append(unicode(bf))
            else:
                # Create a 'class="..."' atribute if the row should have any
                # CSS classes applied.
                css_classes = bf.css_classes()
                if css_classes:
                    html_class_attr = ' class="%s"' % css_classes

                if errors_on_separate_row and bf_errors:
                    output.append(error_row % force_unicode(bf_errors))

                if bf.label:
                    label = conditional_escape(force_unicode(bf.label))
                    # Only add the suffix if the label does not end in
                    # punctuation.
                    if self.label_suffix:
                        if label[-1] not in ':?.!':
                            label += self.label_suffix
                    label = bf.label_tag(label) or ''
                else:
                    label = ''

                if field.help_text:
                    help_text = help_text_html % force_unicode(field.help_text)
                else:
                    help_text = u''

                output.append(normal_row % {
                    'errors': force_unicode(bf_errors),
                    'label': force_unicode(label),
                    'field': unicode(bf),
                    'help_text': help_text,
                    'html_class_attr': html_class_attr
                })

        if top_errors:
            output.insert(0, error_row % force_unicode(top_errors))

        if hidden_fields: # Insert any hidden fields in the last row.
            str_hidden = u''.join(hidden_fields)
            if output:
                last_row = output[-1]
                # Chop off the trailing row_ender (e.g. '</td></tr>') and
                # insert the hidden fields.
                if not last_row.endswith(row_ender):
                    # This can happen in the as_p() case (and possibly others
                    # that users write): if there are only top errors, we may
                    # not be able to conscript the last row for our purposes,
                    # so insert a new, empty row.
                    last_row = (normal_row % {'errors': '', 'label': '',
                                              'field': '', 'help_text':'',
                                              'html_class_attr': html_class_attr})
                    output.append(last_row)
                output[-1] = last_row[:-len(row_ender)] + str_hidden + row_ender
            else:
                # If there aren't any rows in the output, just append the
                # hidden fields.
                output.append(str_hidden)
        return mark_safe(u'\n'.join(output))

    def as_table(self,render_fields=None):
        "Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
        return self._html_output(
            render_fields,
            normal_row = u'<tr%(html_class_attr)s><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>',
            error_row = u'<tr><td colspan="2">%s</td></tr>',
            row_ender = u'</td></tr>',
            help_text_html = u'<br /><span class="helptext">%s</span>',
            errors_on_separate_row = False)
    def as_bootstrip(self,render_fields =None):
        output = []
        for name, field in self.fields.items():
            if render_fields and  not name in render_fields:
                continue
            f = BoundField(self,field,name)
            output.append( as_bootstrap(f))
        return mark_safe(u''.join(output))

    def as_ul(self,render_fields=None):
        "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
        return self._html_output(
            render_fields,
            normal_row = u'<li%(html_class_attr)s>%(errors)s%(label)s %(field)s%(help_text)s</li>',
            error_row = u'<li>%s</li>',
            row_ender = '</li>',
            help_text_html = u' <span class="helptext">%s</span>',
            errors_on_separate_row = False)

    def as_p(self,render_fields=None):
        "Returns this form rendered as HTML <p>s."
        return self._html_output(
            render_fields,
            normal_row = u'<p%(html_class_attr)s>%(label)s %(field)s%(help_text)s</p>',
            error_row = u'%s',
            row_ender = '</p>',
            help_text_html = u' <span class="helptext">%s</span>',
            errors_on_separate_row = True)

下面的方法是配合bootstrap_tookit使用的,可以方便的与bootstrapt集成:

    def as_bootstrip(self,render_fields =None):
        output = []
        for name, field in self.fields.items():
            if render_fields and  not name in render_fields:
                continue
            f = BoundField(self,field,name)
            output.append( as_bootstrap(f))
        return mark_safe(u''.join(output))

 

 

转载于:https://www.cnblogs.com/Ankh/archive/2012/10/12/2721354.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值