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使用ctypes模块调用windowsapi获取系统版本示例
Apr 17 Python
Python中getattr函数和hasattr函数作用详解
Jun 14 Python
Python之Scrapy爬虫框架安装及使用详解
Nov 16 Python
Python解决N阶台阶走法问题的方法分析
Dec 28 Python
取numpy数组的某几行某几列方法
Apr 03 Python
python实现向微信用户发送每日一句 python实现微信聊天机器人
Mar 27 Python
python脚本之一键移动自定格式文件方法实例
Sep 02 Python
python实现七段数码管和倒计时效果
Nov 23 Python
Python定时任务APScheduler原理及实例解析
May 30 Python
python如何写出表白程序
Jun 01 Python
PyTorch安装与基本使用详解
Aug 31 Python
python爬虫scrapy框架的梨视频案例解析
Feb 20 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
ajax php 实现写入数据库
2009/09/02 PHP
PHP数据对象PDO操作技巧小结
2016/09/27 PHP
php设计模式之原型模式分析【星际争霸游戏案例】
2020/03/23 PHP
extjs 学习笔记(三) 最基本的grid
2009/10/15 Javascript
js怎么终止程序return不行换jfslk
2013/05/30 Javascript
js实现正方形颜色从下往上升的效果
2014/08/04 Javascript
原生javascript实现Tab选项卡切换功能
2015/01/12 Javascript
javascript清空table表格的方法
2015/05/14 Javascript
jquery利用拖拽方式在图片上添加热链接
2015/11/24 Javascript
基于JavaScript操作DOM常用的API小结
2015/12/01 Javascript
js获取iframe中的window对象的实现方法
2016/05/20 Javascript
Node.js中防止错误导致的进程阻塞的方法
2016/08/11 Javascript
实例解析jQuery工具函数
2016/12/01 Javascript
创建简单的node服务器实例(分享)
2017/06/23 Javascript
微信小程序时间标签和时间范围的联动效果
2019/02/15 Javascript
详解jQuery中的getAll()和cleanData()
2019/04/15 jQuery
VUE 实现复制内容到剪贴板的两种方法
2019/04/24 Javascript
js常用正则表达式集锦
2019/05/17 Javascript
基于layPage插件实现两种分页方式浅析
2019/07/27 Javascript
Javascript中Math.max和Math.max.apply的区别和用法详解
2020/08/24 Javascript
JS中队列和双端队列实现及应用详解
2020/09/29 Javascript
github配置使用指南
2014/11/18 Python
基于Python实现对PDF文件的OCR识别
2016/08/05 Python
Django Highcharts制作图表
2016/08/27 Python
用yum安装MySQLdb模块的步骤方法
2016/12/15 Python
从CentOS安装完成到生成词云python的实例
2017/12/01 Python
用python实现将数组元素按从小到大的顺序排列方法
2018/07/02 Python
如何利用python给图片添加半透明水印
2019/09/06 Python
Python+OpenCV 实现图片无损旋转90°且无黑边
2019/12/12 Python
CSS3制作气泡对话框的实例教程
2016/05/10 HTML / CSS
艺术家策划的室内设计:Curious Egg
2019/03/06 全球购物
King Apparel官网:英国街头服饰品牌
2019/09/05 全球购物
中式餐厅创业计划书范文
2014/01/23 职场文书
物理分数没达标检讨书
2014/09/13 职场文书
毕业生银行实习自我鉴定
2014/10/14 职场文书
python疲劳驾驶困倦低头检测功能的实现
2022/04/04 Python