jasper的技术小窝

关注DevOps、运维监控、Python、Golang、开源、大数据、web开发、互联网

django后台自定义表单控件(包装ace插件)

作者:jasper | 分类:django | 标签:       | 阅读 2153 次 | 发布:2014-09-12 9:04 p.m.

众所周知,django框架最优秀就是其自动生成的后台管理,我们可以在admin.py中添加ModelAdmin,这样就能方便地在后台进行增删改查的操作,然而,对应model生成的表单,并不友好,我们希望能像自己前端开发一样做出各种类型的标签,这就得对其后台的表单进行自定义。

其实django已经为我们提供一些可用的表单控件,比如多选框,单选按钮等,下面就以单选按钮为例,说说它的用法:

from django import forms
class MyAdminForm(forms.ModelForm):
    xxx= forms.ChoiceField(choices=[.......],widget=forms.RadioSelect())

class MyAdmin(object):
    form = MyAdminForm
    # ....省略若干代码

先定义一个自定义的AdminForm,在里面为字段添加控件,widget就是指定控件的类型,本例为单选按钮(RadioSelect),choices指定可选列表,再在Admin中的form指定为自定义表单即可。

在django中已经提供了很多widget(控件),具体可参见文档https://docs.djangoproject.com/en/1.7/ref/forms/widgets/,然而这些还远远满足不了我们的需求,比如日期控件datapicker什么的,这就需要我们去自定义widget,下面就以一个比较复杂一点的ace插件(一个代码编辑的插件)为例,说说怎么自定义widget:

from django import forms
from django.utils.html import format_html
from django.forms.util import flatatt
from django.utils.encoding import force_text
from django.utils.safestring import mark_safe

ACE_RENDER = '''
<script type="text/javascript" src="/static/js/ace/ace.js">   #引入插件的js文件
<script>
 $(function () {

        var editDiv = $('<div>', {
            position: 'absolute',
            width: textarea.width(),
            height: textarea.height(),
            'class': textarea.attr('class')
        }).insertBefore(textarea);

        textarea.css('display', 'none');

        var editor = ace.edit(editDiv[0]);
        editor.getSession().setValue(textarea.val());
        editor.getSession().setMode("ace/mode/%s");
        editor.setTheme("ace/theme/%s");

        textarea.closest('form').submit(function () {
            textarea.val(editor.getSession().getValue());
        })
    });

'''

class AceWidget(forms.Textarea):     #继承自textarea
    def __init__(self, mode="", theme="",  attrs=None):  #为了能在调用的时候自定义代码类型和样式
        super(AceWidget, self).__init__(attrs)
        self.mode = mode
        self.theme = theme

    def render(self, name, value, attrs=None):  #关键方法
        if value is None: value = ''
        final_attrs = self.build_attrs(attrs, name=name)
        output = [format_html('\r\n{1}', flatatt(final_attrs),force_text(value))]
        current_ace_render = ACE_RENDER %(self.mode, self.theme)
        output.append(current_ace_render)
        return mark_safe('\n'.join(output))

其实主要就是自定义的widget要继承自django的widget,然后重写render方法,在这个方法中,你要对新的控件进行包装。 同上方单选按钮一样,需要将widget引入:

class MyAdminForm(forms.ModelForm):
    content = forms.CharField(widget=AceWidget(mode="python", theme="eclipse"))  #自定义语言和样式

class MyAdmin(admin.ModelAdmin):
    form = MyAdminForm

这是一个比较复杂的例子,其他的可以触类旁通,这样就能做出自己想要的表单控件了。


转载请注明出处:http://www.opscoder.info/custom_form.html

【上一篇】 浅谈本博客搭建过程
【下一篇】 django中的权限管理
其他分类: