视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
深入了解Python中Django后台自定义表单控件
2020-11-27 14:15:09 责编:小采
文档
本篇文章主要介绍了Python中Django 后台自定义表单控件,其实 django 已经为我们提供了一些可用的表单控件,比如:多选框、单选按钮等,有兴趣的开业了解一下。

在 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 editp = $('<p>', {
 position: 'absolute',
 width: textarea.width(),
 height: textarea.height(),
 'class': textarea.attr('class')
 }).insertBefore(textarea);
 textarea.css('display', 'none');
 var editor = ace.edit(editp[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{}>
{}</textarea>', flatatt(final_attrs), force_text(value))]
 current_ace_render = ACE_RENDER %(self.mode, self.theme)
 output.append(current_ace_render)
 return mark_safe('
'.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 目录下。

效果图

附录:

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)

下载本文
显示全文
专题