赞
踩
1.安装依赖
django-simditor==0.0.15
2.配置
INSTALLED_APPS += ( 'simditor', ) SIMDITOR_TOOLBAR = [ 'title', 'bold', 'italic', 'underline', 'strikethrough', 'fontScale', 'color', '|', 'ol', 'ul', 'blockquote', 'table', '|', 'link', 'image', 'hr', '|', 'indent', 'outdent', 'alignment', # '|', 'markdown' ] SIMDITOR_UPLOAD_PATH = 'uploads/' SIMDITOR_IMAGE_BACKEND = 'pillow' # 图片上传的url SIMDITOR_CONFIGS = { 'toolbar': SIMDITOR_TOOLBAR, 'upload': { 'url': SITE_URL + '/simditor/upload/', 'fileKey': 'upload', 'image_size': 1024 * 1024 * 4 # max image size 4MB }, 'emoji': { 'imagePath': '/static/simditor/images/emoji/' } }
3.生成simditor编辑器form的代码
# -*- coding: utf-8 from __future__ import unicode_literals, absolute_import from django.conf.urls import include, url from simditor import utils, image_processing from .widgets import SimditorWidget import os from datetime import datetime from django.conf import settings from django.core.files.storage import default_storage from django.http import JsonResponse from django.views import generic from django.views.decorators.csrf import csrf_exempt # from . import utils, image_processing class SimditorEditor(): """Editors should inherit from this. See wiki.editors for examples.""" # The editor id can be used for conditional testing. If you write your # own editor class, you can use the same editor_id as some editor editor_id = 'simditor' def get_admin_widget(self): return SimditorWidget() def get_widget(self, instance=None): return SimditorWidget() def get_urls(self): return [url(r'^simditor/', include('simditor.urls'))] class AdminMedia: css = {'all': ( 'wiki/simditor/styles/simditor.css', 'wiki/simditor/styles/simditor-markdown.css', )} js = ( 'wiki/simditor/scripts/jquery.min.js', 'wiki/simditor/scripts/module.js', 'wiki/simditor/scripts/uploader.js', 'wiki/simditor/scripts/hotkeys.js', 'wiki/simditor/scripts/simditor.js', 'wiki/simditor/scripts/marked.js', 'wiki/simditor/scripts/to-markdown.js', 'wiki/simditor/scripts/simditor-markdown.js', ) class Media: css = {'all': ( 'wiki/simditor/styles/simditor.css', 'wiki/simditor/styles/simditor-markdown.css', )} js = ( 'wiki/simditor/scripts/jquery.min.js', 'wiki/simditor/scripts/module.js', 'wiki/simditor/scripts/uploader.js', 'wiki/simditor/scripts/hotkeys.js', 'wiki/simditor/scripts/simditor.js', 'wiki/simditor/scripts/marked.js', 'wiki/simditor/scripts/to-markdown.js', 'wiki/simditor/scripts/simditor-markdown.js', ) def get_upload_filename(upload_name): # Generate date based path to put uploaded file. date_path = datetime.now().strftime('%Y/%m/%d') # Complete upload path (upload_path + date_path). upload_path = os.path.join(settings.SIMDITOR_UPLOAD_PATH, date_path) if getattr(settings, 'SIMDITOR_UPLOAD_SLUGIFY_FILENAME', True): upload_name = utils.slugify_filename(upload_name) return default_storage.get_available_name(os.path.join(upload_path, upload_name)) def upload_handler(request): files = request.FILES upload_config = settings.SIMDITOR_CONFIGS.get( 'upload', {'fileKey': 'upload'}) filekey = upload_config.get('fileKey', 'upload') uploaded_file = files.get(filekey) if not uploaded_file: retdata = {'file_path': '', 'success': False, 'msg': '图片上传失败,无法获取到图片对象!'} return JsonResponse(retdata) image_size = upload_config.get('image_size') if image_size and uploaded_file.size > image_size: retdata = {'file_path': '', 'success': False, 'msg': '上传失败,已超出图片最大限制!'} return JsonResponse(retdata) backend = image_processing.get_backend() if not getattr(settings, 'SIMDITOR_ALLOW_NONIMAGE_FILES', True): try: backend.image_verify(uploaded_file) except utils.NotAnImageException: retdata = {'file_path': '', 'success': False, 'msg': '图片格式错误!'} return JsonResponse(retdata) filename = get_upload_filename(uploaded_file.name) saved_path = default_storage.save(filename, uploaded_file) url = utils.get_media_url(saved_path) is_api = settings.SIMDITOR_CONFIGS.get('is_api', False) url = request.META.get('HTTP_ORIGIN') + url if is_api else url retdata = {'file_path': url, 'success': True, 'msg': '上传成功!'} return JsonResponse(retdata) class ImageUploadView(generic.View): """ImageUploadView.""" http_method_names = ['post'] def post(self, request, **kwargs): """Post.""" return upload_handler(request) UPLOAD = csrf_exempt(ImageUploadView.as_view())
这里有一个坑,由于SimditorWidget()从依赖中引入不识别,我解决的办法:将这个内容所在的文件从依赖中拷贝出来,直接从这个文件引入
widgets.py
"""simditor widgets.""" from __future__ import absolute_import from django import forms from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.core.serializers.json import DjangoJSONEncoder from django.template.loader import render_to_string from django.utils.encoding import force_text from django.utils.safestring import mark_safe from django.utils.html import conditional_escape from django.utils.functional import Promise from conf.default import SITE_URL try: # Django >=2.1 from django.forms.widgets import get_default_renderer IS_NEW_WIDGET = True except ImportError: IS_NEW_WIDGET = False try: # Django >=1.7 from django.forms.utils import flatatt except ImportError: # Django <1.7 from django.forms.util import flatatt # pylint disable=E0611, E0401 class LazyEncoder(DjangoJSONEncoder): """LazyEncoder.""" # pylint disable=E0202 def default(self, obj): if isinstance(obj, Promise): return force_text(obj) return super(LazyEncoder, self).default(obj) JSON_ENCODE = LazyEncoder().encode FULL_TOOLBAR = [ 'title', 'bold', 'italic', 'underline', 'strikethrough', 'fontScale', 'color', '|', 'ol', 'ul', 'blockquote', 'code', 'table', '|', 'link', 'image', 'hr', '|', 'indent', 'outdent', 'alignment', 'checklist', 'markdown', 'fullscreen' ] DEFAULT_TOOLBAR = [ 'title', 'bold', 'italic', 'underline', 'strikethrough', 'fontScale', 'color', '|', 'ol', 'ul', 'blockquote', 'table', '|', 'link', 'image', 'hr', '|', 'indent', 'outdent', 'alignment', # '|', 'markdown' ] SIMDITOR_UPLOAD_PATH = 'uploads/' SIMDITOR_IMAGE_BACKEND = 'pillow' # 我的理解是前端的上传图片请求配置 DEFAULT_CONFIG = { 'toolbar': DEFAULT_TOOLBAR, 'cleanPaste': True, 'tabIndent': True, 'pasteImage': True, 'upload': { 'url': SITE_URL + '/simditor/upload/', 'fileKey': 'upload', 'image_size': 1024 * 1024 * 4 # max image size 4MB }, } class SimditorWidget(forms.Textarea): """ Widget providing Simditor for Rich Text Editing.abs Supports direct image uploads and embed. """ class Media: """Media.""" css_list = [ 'simditor/styles/simditor.css' ] if 'emoji' in settings.SIMDITOR_TOOLBAR: css_list.append('simditor/styles/simditor-emoji.css') if 'fullscreen' in settings.SIMDITOR_TOOLBAR: css_list.append('simditor/styles/simditor-fullscreen.min.css') if 'checklist' in settings.SIMDITOR_TOOLBAR: css_list.append('simditor/styles/simditor-checklist.min.css') if 'markdown' in settings.SIMDITOR_TOOLBAR: css_list.append('simditor/styles/simditor-markdown.min.css') css = {'all': tuple(settings.STATIC_URL + url for url in css_list)} jquery_list = ['simditor/scripts/jquery.min.js', 'simditor/scripts/module.min.js', 'simditor/scripts/hotkeys.min.js', 'simditor/scripts/uploader.min.js', # 'simditor/scripts/simditor.min.js', 'simditor/scripts/simditor.js', ] if 'fullscreen' in settings.SIMDITOR_TOOLBAR: jquery_list.append('simditor/scripts/simditor-fullscreen.min.js') if 'checklist' in settings.SIMDITOR_TOOLBAR: jquery_list.append('simditor/scripts/simditor-checklist.min.js') if 'markdown' in settings.SIMDITOR_TOOLBAR: jquery_list.append('simditor/scripts/marked.min.js') jquery_list.append('simditor/scripts/to-markdown.min.js') jquery_list.append('simditor/scripts/simditor-markdown.min.js') if 'image' in settings.SIMDITOR_TOOLBAR: jquery_list.append('simditor/scripts/simditor-dropzone.min.js') if 'emoji' in settings.SIMDITOR_TOOLBAR: jquery_list.append('simditor/scripts/simditor-emoji.js') js = tuple(settings.STATIC_URL + url for url in jquery_list) try: js += (settings.STATIC_URL + 'simditor/simditor-init.js',) except AttributeError: raise ImproperlyConfigured("django-simditor requires \ SIMDITOR_MEDIA_PREFIX setting. This setting specifies a \ URL prefix to the ckeditor JS and CSS media (not \ uploaded media). Make sure to use a trailing slash: \ SIMDITOR_MEDIA_PREFIX = '/media/simditor/'") def __init__(self, *args, **kwargs): super(SimditorWidget, self).__init__(*args, **kwargs) # Setup config from defaults. self.config = DEFAULT_CONFIG.copy() # Try to get valid config from settings. configs = getattr(settings, 'SIMDITOR_CONFIGS', None) if configs: if isinstance(configs, dict): self.config.update(configs) else: raise ImproperlyConfigured( 'SIMDITOR_CONFIGS setting must be a dictionary type.') def build_attrs(self, base_attrs, extra_attrs=None, **kwargs): """ Helper function for building an attribute dictionary. This is combination of the same method from Django<=1.10 and Django1.11 """ attrs = dict(base_attrs, **kwargs) if extra_attrs: attrs.update(extra_attrs) return attrs def render(self, name, value, attrs=None, renderer=None): if value is None: value = '' final_attrs = self.build_attrs(self.attrs, attrs, name=name) params = ('simditor/widget.html', { 'final_attrs': flatatt(final_attrs), 'value': conditional_escape(force_text(value)), 'id': final_attrs['id'], 'config': JSON_ENCODE(self.config) }) if renderer is None and IS_NEW_WIDGET: renderer = get_default_renderer() data = renderer.render(*params) if IS_NEW_WIDGET else render_to_string(*params) return mark_safe(data)
4.form表单部分代码
forms.py文件
class CreateForm(forms.Form, SpamProtectionMixin):
def __init__(self, request, urlpath_parent, *args, **kwargs):
super(CreateForm, self).__init__(*args, **kwargs)
# 富文本字段
richtext = forms.CharField(
label=_('Contents'),
required=False,
widget=SimditorEditor().get_widget())
article.py文件
class Create(FormView, ArticleMixin):
form_class = forms.CreateForm
template_name = "wiki/create.html"
最后一个问题就是上传图片会出的问题:上传需要url路由,不然上传不识别路由报错,导致上传失败
from django.views.decorators.csrf import csrf_exempt
from .simditor import ImageUploadView # 从simditor.py导入的
urlpatterns += [
url(r'^simditor/upload', csrf_exempt(ImageUploadView.as_view())),
]
这样就可以识别了
效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。