5
+from datetime import datetime
6
+
7
+from django.conf import settings
8
+from django.core.files.storage import default_storage
9
+
10
+from django.http import JsonResponse
11
+
12
+from django.views import generic
13
+from django.views.decorators.csrf import csrf_exempt
14
+
15
+from . import utils, image_processing
16
+
17
+
18
+def get_upload_filename(upload_name):
19
+    # Generate date based path to put uploaded file.
20
+    date_path = datetime.now().strftime('%Y/%m/%d')
21
+
22
+    # Complete upload path (upload_path + date_path).
23
+    upload_path = os.path.join(settings.SIMDITOR_UPLOAD_PATH, date_path)
24
+
25
+    if getattr(settings, 'SIMDITOR_UPLOAD_SLUGIFY_FILENAME', True):
26
+        upload_name = utils.slugify_filename(upload_name)
27
+
28
+    return default_storage.get_available_name(os.path.join(upload_path, upload_name))
29
+
30
+
31
+def upload_handler(request):
32
+    files = request.FILES
33
+
34
+    upload_config = settings.SIMDITOR_CONFIGS.get(
35
+        'upload', {'fileKey': 'upload'})
36
+    filekey = upload_config.get('fileKey', 'upload')
37
+
38
+    uploaded_file = files.get(filekey)
39
+
40
+    if not uploaded_file:
41
+        retdata = {'file_path': '', 'success': False,
42
+                   'msg': '图片上传失败,无法获取到图片对象!'}
43
+        return JsonResponse(retdata)
44
+
45
+    image_size = upload_config.get('image_size')
46
+    if image_size and uploaded_file.size > image_size:
47
+        retdata = {'file_path': '', 'success': False,
48
+                   'msg': '上传失败,已超出图片最大限制!'}
49
+        return JsonResponse(retdata)
50
+
51
+    backend = image_processing.get_backend()
52
+
53
+    if not getattr(settings, 'SIMDITOR_ALLOW_NONIMAGE_FILES', True):
54
+        try:
55
+            backend.image_verify(uploaded_file)
56
+        except utils.NotAnImageException:
57
+            retdata = {'file_path': '', 'success': False,
58
+                       'msg': '图片格式错误!'}
59
+            return JsonResponse(retdata)
60
+
61
+    filename = get_upload_filename(uploaded_file.name)
62
+    saved_path = default_storage.save(filename, uploaded_file)
63
+
64
+    url = utils.get_media_url(saved_path)
65
+
66
+    is_api = settings.SIMDITOR_CONFIGS.get('is_api', False)
67
+    url = request.META.get('HTTP_ORIGIN') + url if is_api else url
68
+
69
+    retdata = {'file_path': url, 'success': True, 'msg': '上传成功!'}
70
+
71
+    return JsonResponse(retdata)
72
+
73
+
74
+class ImageUploadView(generic.View):
75
+    """ImageUploadView."""
76
+
77
+    http_method_names = ['post']
78
+
79
+    def post(self, request, **kwargs):
80
+        """Post."""
81
+        return upload_handler(request)
82
+
83
+
84
+UPLOAD = csrf_exempt(ImageUploadView.as_view())

+ 170 - 0
simditor/widgets.py

@@ -0,0 +1,170 @@
1
+"""simditor widgets."""
2
+from __future__ import absolute_import
3
+
4
+from django import forms
5
+from django.conf import settings
6
+from django.core.exceptions import ImproperlyConfigured
7
+from django.core.serializers.json import DjangoJSONEncoder
8
+
9
+from django.template.loader import render_to_string
10
+from django.utils.encoding import force_text
11
+from django.utils.safestring import mark_safe
12
+from django.utils.html import conditional_escape
13
+from django.utils.functional import Promise
14
+
15
+try:
16
+    # Django >=2.1
17
+    from django.forms.widgets import get_default_renderer
18
+    IS_NEW_WIDGET = True
19
+except ImportError:
20
+    IS_NEW_WIDGET = False
21
+
22
+try:
23
+    # Django >=1.7
24
+    from django.forms.utils import flatatt
25
+except ImportError:
26
+    # Django <1.7
27
+    from django.forms.util import flatatt        # pylint disable=E0611, E0401
28
+
29
+
30
+class LazyEncoder(DjangoJSONEncoder):
31
+    """LazyEncoder."""
32
+
33
+    # pylint disable=E0202
34
+    def default(self, obj):
35
+        if isinstance(obj, Promise):
36
+            return force_text(obj)
37
+        return super(LazyEncoder, self).default(obj)
38
+
39
+
40
+JSON_ENCODE = LazyEncoder().encode
41
+
42
+
43
+FULL_TOOLBAR = [
44
+    'title', 'bold', 'italic', 'underline', 'strikethrough', 'fontScale',
45
+    'color', '|', 'ol', 'ul', 'blockquote', 'code', 'table', '|', 'link',
46
+    'image', 'hr', '|', 'indent', 'outdent', 'alignment', 'checklist',
47
+    'markdown', 'fullscreen'
48
+]
49
+
50
+DEFAULT_TOOLBAR = [
51
+    'title', 'bold', 'italic', 'underline', 'strikethrough', 'fontScale',
52
+    'color', '|', 'ol', 'ul', 'blockquote', 'table', '|', 'link',
53
+    'image', 'hr', '|', 'indent', 'outdent', 'alignment'
54
+]
55
+
56
+DEFAULT_CONFIG = {
57
+    'toolbar': DEFAULT_TOOLBAR,
58
+    'cleanPaste': True,
59
+    'tabIndent': True,
60
+    'pasteImage': True,
61
+    'upload': {
62
+        'url': '/',
63
+        'fileKey': 'file'
64
+    }
65
+}
66
+
67
+
68
+class SimditorWidget(forms.Textarea):
69
+    """
70
+    Widget providing Simditor for Rich Text Editing.abs
71
+    Supports direct image uploads and embed.
72
+    """
73
+    class Media:
74
+        """Media."""
75
+
76
+        css_list = [
77
+            'simditor/styles/simditor.min.css'
78
+        ]
79
+
80
+        if 'emoji' in settings.SIMDITOR_TOOLBAR:
81
+            css_list.append('simditor/styles/simditor-emoji.css')
82
+
83
+        if 'fullscreen' in settings.SIMDITOR_TOOLBAR:
84
+            css_list.append('simditor/styles/simditor-fullscreen.min.css')
85
+
86
+        if 'checklist' in settings.SIMDITOR_TOOLBAR:
87
+            css_list.append('simditor/styles/simditor-checklist.min.css')
88
+
89
+        if 'markdown' in settings.SIMDITOR_TOOLBAR:
90
+            css_list.append('simditor/styles/simditor-markdown.min.css')
91
+
92
+        css = {'all': tuple(settings.STATIC_URL + url for url in css_list)}
93
+
94
+        jquery_list = ['simditor/scripts/jquery.min.js',
95
+                       'simditor/scripts/module.min.js',
96
+                       'simditor/scripts/hotkeys.min.js',
97
+                       'simditor/scripts/uploader.min.js',
98
+                       'simditor/scripts/simditor.min.js']
99
+
100
+        if 'fullscreen' in settings.SIMDITOR_TOOLBAR:
101
+            jquery_list.append('simditor/scripts/simditor-fullscreen.min.js')
102
+
103
+        if 'checklist' in settings.SIMDITOR_TOOLBAR:
104
+            jquery_list.append('simditor/scripts/simditor-checklist.min.js')
105
+
106
+        if 'markdown' in settings.SIMDITOR_TOOLBAR:
107
+            jquery_list.append('simditor/scripts/marked.min.js')
108
+            jquery_list.append('simditor/scripts/to-markdown.min.js')
109
+            jquery_list.append('simditor/scripts/simditor-markdown.min.js')
110
+
111
+        if 'image' in settings.SIMDITOR_TOOLBAR:
112
+            jquery_list.append('simditor/scripts/simditor-dropzone.min.js')
113
+
114
+        if 'emoji' in settings.SIMDITOR_TOOLBAR:
115
+            jquery_list.append('simditor/scripts/simditor-emoji.js')
116
+
117
+        js = tuple(settings.STATIC_URL + url for url in jquery_list)
118
+
119
+        try:
120
+
121
+            js += (settings.STATIC_URL + 'simditor/simditor-init.js',)
122
+        except AttributeError:
123
+            raise ImproperlyConfigured("django-simditor requires \
124
+                     SIMDITOR_MEDIA_PREFIX setting. This setting specifies a \
125
+                    URL prefix to the ckeditor JS and CSS media (not \
126
+                    uploaded media). Make sure to use a trailing slash: \
127
+                    SIMDITOR_MEDIA_PREFIX = '/media/simditor/'")
128
+
129
+    def __init__(self, *args, **kwargs):
130
+        super(SimditorWidget, self).__init__(*args, **kwargs)
131
+        # Setup config from defaults.
132
+        self.config = DEFAULT_CONFIG.copy()
133
+
134
+        # Try to get valid config from settings.
135
+        configs = getattr(settings, 'SIMDITOR_CONFIGS', None)
136
+        if configs:
137
+            if isinstance(configs, dict):
138
+                self.config.update(configs)
139
+            else:
140
+                raise ImproperlyConfigured(
141
+                    'SIMDITOR_CONFIGS setting must be a dictionary type.')
142
+
143
+    def build_attrs(self, base_attrs, extra_attrs=None, **kwargs):
144
+        """
145
+        Helper function for building an attribute dictionary.
146
+        This is combination of the same method from Django<=1.10 and Django1.11
147
+        """
148
+        attrs = dict(base_attrs, **kwargs)
149
+        if extra_attrs:
150
+            attrs.update(extra_attrs)
151
+        return attrs
152
+
153
+    def render(self, name, value, attrs=None, renderer=None):
154
+        if value is None:
155
+            value = ''
156
+        final_attrs = self.build_attrs(self.attrs, attrs, name=name)
157
+
158
+        params = ('simditor/widget.html', {
159
+            'final_attrs': flatatt(final_attrs),
160
+            'value': conditional_escape(force_text(value)),
161
+            'id': final_attrs['id'],
162
+            'config': JSON_ENCODE(self.config)
163
+        })
164
+
165
+        if renderer is None and IS_NEW_WIDGET:
166
+            renderer = get_default_renderer()
167
+
168
+        data = renderer.render(*params) if IS_NEW_WIDGET else render_to_string(*params)
169
+
170
+        return mark_safe(data)

kodosale - Gogs: Go Git Service

Nenhuma Descrição

huangqimin: ecae93df3f :bug: Fix Bug: error.message was deprecated in Python 2.6 and removed in Python 3 5 anos atrás
account d1f2463a76 :art: Support AdministratorInfo and relation 5 anos atrás
api 7c0a098a63 add order/list and /pack sorted 5 anos atrás
commands 9e28f52376 :tada: Initial 5 anos atrás
data 9e28f52376 :tada: Initial 5 anos atrás
docs 9e28f52376 :tada: Initial 5 anos atrás
goods 8cb1966a10 art: Support PackGoodsInfo inventory and has_sale_num related 5 anos atrás
kodosale 1c30c8567d :art: Update requirement.txt 5 anos atrás
kol 9e28f52376 :tada: Initial 5 anos atrás
pay ecae93df3f :bug: Fix Bug: error.message was deprecated in Python 2.6 and removed in Python 3 5 anos atrás
simditor 3e81499401 fix simditor upload bug 5 anos atrás
utils d1f2463a76 :art: Support AdministratorInfo and relation 5 anos atrás
.editorconfig 9e28f52376 :tada: Initial 5 anos atrás
.gitignore 9e28f52376 :tada: Initial 5 anos atrás
.isort.cfg 9e28f52376 :tada: Initial 5 anos atrás
README.md 9e28f52376 :tada: Initial 5 anos atrás
check.sh 9e28f52376 :tada: Initial 5 anos atrás
isort.sh 9e28f52376 :tada: Initial 5 anos atrás
manage.py 9e28f52376 :tada: Initial 5 anos atrás
pep8.sh 9e28f52376 :tada: Initial 5 anos atrás
requirements.txt d1f2463a76 :art: Support AdministratorInfo and relation 5 anos atrás
requirements_deploy.txt 9e28f52376 :tada: Initial 5 anos atrás
requirements_dev.txt 9e28f52376 :tada: Initial 5 anos atrás
requirements_dj.txt 1c30c8567d :art: Update requirement.txt 5 anos atrás
requirements_pywe.txt 1c30c8567d :art: Update requirement.txt 5 anos atrás
requirements_redis.txt 9e28f52376 :tada: Initial 5 anos atrás
sysctl.sh 9e28f52376 :tada: Initial 5 anos atrás
kodosale - Gogs: Go Git Service

Nenhuma Descrição

FFIB: a4e8c93600 fix simditor image url bug 5 anos atrás
account 0b87187840 add user_id 5 anos atrás
api 2a2b2994c6 add title, expired_at 5 anos atrás
commands 9e28f52376 :tada: Initial 5 anos atrás
data 9e28f52376 :tada: Initial 5 anos atrás
docs 9e28f52376 :tada: Initial 5 anos atrás
goods f9f759921d Merge branch 'master' of http://git.xfoto.com.cn/Kodo/kodosale 5 anos atrás
kodosale a4e8c93600 fix simditor image url bug 5 anos atrás
kol 9e28f52376 :tada: Initial 5 anos atrás
pay d1b83c39d0 update 5 anos atrás
simditor 3e81499401 fix simditor upload bug 5 anos atrás
utils a329bd00d4 :art: Format Codes 5 anos atrás
.editorconfig 9e28f52376 :tada: Initial 5 anos atrás
.gitignore 9e28f52376 :tada: Initial 5 anos atrás
.isort.cfg 9e28f52376 :tada: Initial 5 anos atrás
README.md 9e28f52376 :tada: Initial 5 anos atrás
check.sh 9e28f52376 :tada: Initial 5 anos atrás
isort.sh 9e28f52376 :tada: Initial 5 anos atrás
manage.py 9e28f52376 :tada: Initial 5 anos atrás
pep8.sh 9e28f52376 :tada: Initial 5 anos atrás
requirements.txt 9e28f52376 :tada: Initial 5 anos atrás
requirements_deploy.txt 9e28f52376 :tada: Initial 5 anos atrás
requirements_dev.txt 9e28f52376 :tada: Initial 5 anos atrás
requirements_dj.txt 194fbcf74d add simditor 5 anos atrás
requirements_pywe.txt 2f87042dda :art: Update requirements_pywe.txt 5 anos atrás
requirements_redis.txt 9e28f52376 :tada: Initial 5 anos atrás
sysctl.sh 9e28f52376 :tada: Initial 5 anos atrás