Python中Django 后台自定义表单控件


Posted in Python onMarch 28, 2017

在 django 中我们可以在 admin.py 中添加 ModelAdmin,这样就能很方便地在后台进行增删改查的操作。然而,对应 Model 生成的表单,并不友好,我们希望能像前端开发一样做出各种类型的控件,这就得对其后台的表单进行自定义。

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

# forms.py
from django import forms
from .models import MyModel

class MyForm(forms.ModelForm):
  xxx = forms.ChoiceField(choices=[...], widget=forms.RadioSelect())

  class Meta:
    model = MyModel
    fields = ['id', 'xxx']


# admin.py
from django.contrib import admin
from .models import MyModel
from .forms import MyForm

class MyAdmin(admin.ModelAdmin):
  form = MyForm
  # ...省略若干代码

admin.site.register(MyModel, MyAdmin)

先自定义一个 MyForm,在里面为字段添加控件,widget 用来指定控件的类型,choices 指定可选列表,再在 MyAdmin 中的 form 指定为自定义表单即可。

在 django 中已经提供了很多 widget(控件),然而这些还远远满足不了我们的需求,这就需要我们去自定义,下面就以一个 ACE 插件 (ACE 是一个独立的 JavaScript 编写的基于 Web 的代码编辑器)为例,说说怎么自定义 widget:

#coding: utf-8
from django import forms
from django.utils.html import format_html
from django.forms.utils import flatatt
from django.utils.encoding import force_text
from django.utils.safestring import mark_safe


ACE_RENDER = '''
<script src="/static/js/jquery-1.11.2.min.js"></script>
<script src="/static/js/ace/ace.js"></script>
<script>
  $(function () {
    var textarea = $('textarea');
    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());
    });
  });
</script>
'''

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

  def render(self, name, value, attrs=None):
    '''
    关键方法
    :param name:
    :param value:
    :param attrs:
    :return:
    '''
    if value is None:
      value = ''
    final_attrs = self.build_attrs(attrs, name=name)
    output = [format_html('<textarea{}>\r\n{}</textarea>', 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 方法,在这个方法中,对新的控件进行包装。

forms.py 中将自定义的控件 AceWidget 引入:

#coding: utf-8
from django import forms
from .models import Code
from widgets import AceWidget


class CodeForm(forms.ModelForm):
  code = forms.CharField(label='源码', widget=AceWidget(attrs={'cols': '100', 'rows': '20'}, mode="python", theme="monokai"))

  class Meta:
    model = Code
    fields = ['title', 'code']

需要注意的是:在这里使用的 mode="python", theme="monokai" 对应的文件 mode-python.js theme-monokai.js 一定要在 /static/js/ace 目录下。

效果图

Python中Django 后台自定义表单控件

附录:

models.py:

#coding:utf-8
from django.db import models


class Code(models.Model):
  title = models.CharField('标题', max_length=50, unique=True)
  code = models.TextField('源码')

  class Meta:
    db_table = 'code'
    verbose_name = verbose_name_plural = '代码'

  def __unicode__(self):
    return self.title

admin.py:

from django.contrib import admin
from .models import Code
from .forms import CodeForm


class CodeAdmin(admin.ModelAdmin):
  form = CodeForm
  list_display = ['id', 'title']

admin.site.register(Code, CodeAdmin)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python写入中英文字符串到文件的方法
May 06 Python
在Python的struct模块中进行数据格式转换的方法
Jun 17 Python
Python中functools模块的常用函数解析
Jun 30 Python
python僵尸进程产生的原因
Jul 21 Python
详解Python中的动态属性和特性
Apr 07 Python
python实现文件助手中查看微信撤回消息
Apr 29 Python
Python获取命令实时输出-原样彩色输出并返回输出结果的示例
Jul 11 Python
用python实现英文字母和相应序数转换的方法
Sep 18 Python
Python基于read(size)方法读取超大文件
Mar 12 Python
Django实现从数据库中获取到的数据转换为dict
Mar 27 Python
关于Keras Dense层整理
May 21 Python
使用PyCharm官方中文语言包汉化PyCharm
Nov 18 Python
windows上安装Anaconda和python的教程详解
Mar 28 #Python
利用python爬取软考试题之ip自动代理
Mar 28 #Python
详解python调度框架APScheduler使用
Mar 28 #Python
Python中is与==判断的区别
Mar 28 #Python
Python利用Beautiful Soup模块创建对象详解
Mar 27 #Python
Python利用Beautiful Soup模块修改内容方法示例
Mar 27 #Python
python递归查询菜单并转换成json实例
Mar 27 #Python
You might like
PHP 中魔术常量的实例详解
2017/10/26 PHP
nodejs教程 安装express及配置app.js文件的详细步骤
2013/05/11 NodeJs
ie中js创建checkbox默认选中问题探讨
2013/10/21 Javascript
nodejs中使用monk访问mongodb
2014/07/06 NodeJs
json属性名为什么要双引号(个人猜测)
2014/07/31 Javascript
JavaScript中的普通函数与构造函数比较
2015/04/07 Javascript
javascript中DOM复选框选择用法实例
2015/05/14 Javascript
利用jQuery设计一个简单的web音乐播放器的实例分享
2016/03/08 Javascript
JavaScript学习笔记之ES6数组方法
2016/03/25 Javascript
sublime text配置node.js调试(图文教程)
2017/11/23 Javascript
Vue微信项目按需授权登录策略实践思路详解
2018/05/07 Javascript
详解基于DllPlugin和DllReferencePlugin的webpack构建优化
2018/06/28 Javascript
浅析JavaScript异步代码优化
2019/03/18 Javascript
浅谈vue加载优化策略
2019/03/19 Javascript
sortable+element 实现表格行拖拽的方法示例
2019/06/07 Javascript
vue中touch和click共存的解决方式
2020/07/28 Javascript
python多进程提取处理大量文本的关键词方法
2018/06/05 Python
对pandas中Series的map函数详解
2018/07/25 Python
python3爬虫获取html内容及各属性值的方法
2018/12/17 Python
python查找重复图片并删除(图片去重)
2019/07/16 Python
浅析使用Python搭建http服务器
2019/10/27 Python
Python实现随机取一个矩阵数组的某几行
2019/11/26 Python
TensorFlow——Checkpoint为模型添加检查点的实例
2020/01/21 Python
django在保存图像的同时压缩图像示例代码详解
2020/02/11 Python
python numpy实现多次循环读取文件 等间隔过滤数据示例
2020/03/14 Python
jupyter notebook实现显示行号
2020/04/13 Python
python生成xml时规定dtd实例方法
2020/09/21 Python
Perfumetrader荷兰:香水、化妆品和护肤品在线商店
2017/09/15 全球购物
优秀演讲稿范文
2013/12/29 职场文书
学生会竞选演讲稿
2014/04/24 职场文书
寒假安全保证书
2015/02/28 职场文书
超市员工辞职信范文
2015/05/12 职场文书
投诉书格式范本
2015/07/02 职场文书
2015年工会工作总结范文
2015/07/23 职场文书
2019思想汇报范文
2019/05/21 职场文书
Python+Appium新手教程
2021/04/17 Python