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展示动态规则法用以解决重叠子问题的示例
Apr 02 Python
Python实现读取txt文件并转换为excel的方法示例
May 17 Python
python_opencv用线段画封闭矩形的实例
Dec 05 Python
如何不用安装python就能在.NET里调用Python库
Jul 12 Python
python 字典有序并写入json文件过程解析
Sep 30 Python
关于Pytorch的MLP模块实现方式
Jan 07 Python
pytorch实现CNN卷积神经网络
Feb 19 Python
Python HTMLTestRunner可视化报告实现过程解析
Apr 10 Python
使用python编写一个语音朗读闹钟功能的示例代码
Jul 14 Python
python中pickle模块浅析
Dec 29 Python
Python Pandas数据分析之iloc和loc的用法详解
Nov 11 Python
PYTHON InceptionV3模型的复现详解
May 06 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
不用数据库的多用户文件自由上传投票系统(1)
2006/10/09 PHP
php中利用post传递字符串重定向的实现代码
2011/04/21 PHP
windows7下安装php的imagick和imagemagick扩展教程
2014/07/04 PHP
php数据库的增删改查 php与javascript之间的交互
2017/08/31 PHP
一个多次搜索+多次传值的解决方案
2007/01/20 Javascript
超棒的javascript页面顶部卷动广告效果
2007/12/01 Javascript
Jquery进度条插件 Progress Bar小问题解决
2011/07/12 Javascript
jquery制作图片时钟特效
2020/03/30 Javascript
JavaScript模拟鼠标右键菜单效果
2020/12/08 Javascript
Jquery实现的简单轮播效果【附实例】
2016/04/19 Javascript
文本框只能输入数字的js代码(含小数点)
2016/07/10 Javascript
详解JavaScript常量定义
2017/01/03 Javascript
深入理解Vue transition源码分析
2017/07/30 Javascript
JS中的多态实例详解
2017/10/15 Javascript
微信小程序swiper组件用法实例分析【附源码下载】
2017/12/07 Javascript
浅谈vue 单文件探索
2018/09/05 Javascript
python循环监控远程端口的方法
2015/03/14 Python
python 3.0 模拟用户登录功能并实现三次错误锁定
2017/11/01 Python
Python入门之三角函数全解【收藏】
2017/11/08 Python
Python2实现的图片文本识别功能详解
2018/07/11 Python
利用Python校准本地时间的方法教程
2019/10/31 Python
用python画一只可爱的皮卡丘实例
2019/11/21 Python
pytorch:实现简单的GAN示例(MNIST数据集)
2020/01/10 Python
CSS3实现全景图特效示例代码
2018/03/26 HTML / CSS
英国领先的品牌珠宝和配件供应商:Acotis Jewellery
2018/03/07 全球购物
英国家电购物网站:Sonic Direct
2019/03/26 全球购物
Theflamel意大利:女士奢华服装、鞋子和配件
2020/01/11 全球购物
澳大利亚床上用品、浴巾和家居用品购物网站:Bambury
2020/04/16 全球购物
业务经理的岗位职责
2013/11/16 职场文书
最新创业融资计划书
2014/01/19 职场文书
护士辞职信模板
2014/01/20 职场文书
优秀辅导员事迹材料
2014/02/16 职场文书
环保建议书作文
2014/03/12 职场文书
新员工试用期自我评价
2015/03/10 职场文书
SQL Server 数据库实验课第五周——常用查询条件
2021/04/05 SQL Server
SQL Server使用CROSS APPLY与OUTER APPLY实现连接查询
2022/05/25 SQL Server