在 django 中我們可以在 admin.py
中添加 ModelAdmin
,這樣就能很方便地在后臺進行增刪改查的操作。然而,對應 Model
生成的表單,并不友好,我們希望能像前端開發一樣做出各種類型的控件,這就得對其后臺的表單進行自定義。
其實 django 已經為我們提供了一些可用的表單控件,比如:多選框、單選按鈕等,下面就以單選按鈕為例:
# forms.pyfrom django import formsfrom .models import MyModelclass MyForm(forms.ModelForm): xxx = forms.ChoiceField(choices=[...], widget=forms.RadioSelect()) class Meta: model = MyModel fields = ['id', 'xxx']# admin.pyfrom django.contrib import adminfrom .models import MyModelfrom .forms import MyFormclass MyAdmin(admin.ModelAdmin): form = MyForm # ...省略若干代碼admin.site.register(MyModel, MyAdmin)
先自定義一個 MyForm
,在里面為字段添加控件,widget
用來指定控件的類型,choices
指定可選列表,再在 MyAdmin
中的 form 指定為自定義表單即可。
在 django 中已經提供了很多 widget(控件),然而這些還遠遠滿足不了我們的需求,這就需要我們去自定義,下面就以一個 ACE 插件 (ACE 是一個獨立的 JavaScript 編寫的基于 Web 的代碼編輯器)為例,說說怎么自定義 widget:
#coding: utf-8from django import formsfrom django.utils.html import format_htmlfrom django.forms.utils import flatattfrom django.utils.encoding import force_textfrom django.utils.safestring import mark_safeACE_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))
新聞熱點
疑難解答