From 60c3c8ed8e0477be7a1c51de510243014a742c62 Mon Sep 17 00:00:00 2001 From: Oliver Marks Date: Mon, 27 Feb 2017 19:07:13 +0000 Subject: [PATCH 1/3] markdownx example --- config/settings/common.py | 1 + config/urls.py | 1 + mhackspace/blog/admin.py | 5 +++++ requirements/base.txt | 1 + 4 files changed, 8 insertions(+) diff --git a/config/settings/common.py b/config/settings/common.py index 7c1d361..c660fe9 100644 --- a/config/settings/common.py +++ b/config/settings/common.py @@ -38,6 +38,7 @@ THIRD_PARTY_APPS = ( 'allauth.socialaccount', # registration 'stdimage', 'rest_framework', + 'markdownx', ) # Apps specific for this project go here. diff --git a/config/urls.py b/config/urls.py index 2649b41..01c0cf5 100644 --- a/config/urls.py +++ b/config/urls.py @@ -33,6 +33,7 @@ urlpatterns = [ url(r'^api/v1/', include(router.urls, namespace='v1')), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), + url(r'^markdownx/', include('markdownx.urls')), url(r'^blog/$', blog, name='contact'), url(r'^blog/rss/$', BlogFeed()), url(r'^blog/(?P[0-9A-Za-z_\-]+)/$', blog, name='blog-item'), diff --git a/mhackspace/blog/admin.py b/mhackspace/blog/admin.py index 9b5d7b9..cbab459 100644 --- a/mhackspace/blog/admin.py +++ b/mhackspace/blog/admin.py @@ -1,5 +1,7 @@ from django.contrib import admin +from django.db import models from django.contrib.admin import ModelAdmin +from markdownx.widgets import AdminMarkdownxWidget from mhackspace.blog.models import Post, Category @@ -12,6 +14,9 @@ class PostAdmin(ModelAdmin): readonly_fields = ('published_date',) filter_horizontal = ('categories',) prepopulated_fields = {"slug": ("title",)} + formfield_overrides = { + models.TextField: {'widget': AdminMarkdownxWidget}, + } @admin.register(Category) class CategoryAdmin(ModelAdmin): diff --git a/requirements/base.txt b/requirements/base.txt index c2784ec..5d5c461 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -62,3 +62,4 @@ git+https://github.com/olymk2/scaffold.git djangorestframework==3.5.4 django-filter==1.0.1 +django-markdownx From 615514259d9950be1da7b740cd2c49f3e6b0f521 Mon Sep 17 00:00:00 2001 From: Oliver Marks Date: Mon, 27 Feb 2017 19:15:27 +0000 Subject: [PATCH 2/3] implemented for blog as a test --- config/settings/common.py | 2 +- config/urls.py | 2 +- mhackspace/blog/admin.py | 4 ---- mhackspace/blog/models.py | 3 ++- requirements/base.txt | 2 +- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/config/settings/common.py b/config/settings/common.py index c660fe9..6488eae 100644 --- a/config/settings/common.py +++ b/config/settings/common.py @@ -38,7 +38,7 @@ THIRD_PARTY_APPS = ( 'allauth.socialaccount', # registration 'stdimage', 'rest_framework', - 'markdownx', + 'draceditor', ) # Apps specific for this project go here. diff --git a/config/urls.py b/config/urls.py index 01c0cf5..e242ef0 100644 --- a/config/urls.py +++ b/config/urls.py @@ -33,7 +33,7 @@ urlpatterns = [ url(r'^api/v1/', include(router.urls, namespace='v1')), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), - url(r'^markdownx/', include('markdownx.urls')), + url(r'^draceditor/', include('draceditor.urls')), url(r'^blog/$', blog, name='contact'), url(r'^blog/rss/$', BlogFeed()), url(r'^blog/(?P[0-9A-Za-z_\-]+)/$', blog, name='blog-item'), diff --git a/mhackspace/blog/admin.py b/mhackspace/blog/admin.py index cbab459..1e955f7 100644 --- a/mhackspace/blog/admin.py +++ b/mhackspace/blog/admin.py @@ -1,7 +1,6 @@ from django.contrib import admin from django.db import models from django.contrib.admin import ModelAdmin -from markdownx.widgets import AdminMarkdownxWidget from mhackspace.blog.models import Post, Category @@ -14,9 +13,6 @@ class PostAdmin(ModelAdmin): readonly_fields = ('published_date',) filter_horizontal = ('categories',) prepopulated_fields = {"slug": ("title",)} - formfield_overrides = { - models.TextField: {'widget': AdminMarkdownxWidget}, - } @admin.register(Category) class CategoryAdmin(ModelAdmin): diff --git a/mhackspace/blog/models.py b/mhackspace/blog/models.py index b02b2a9..ee2e0fe 100644 --- a/mhackspace/blog/models.py +++ b/mhackspace/blog/models.py @@ -1,6 +1,7 @@ from django.db import models from django.utils import timezone from django.urls import reverse +from draceditor.models import DraceditorField from mhackspace.users.models import User from stdimage.models import StdImageField @@ -34,7 +35,7 @@ class Post(models.Model): "height": 220, "crop": True}}) - description = models.TextField() + description = DraceditorField() published_date = models.DateTimeField(default=timezone.now) updated_date = models.DateTimeField(default=timezone.now) active = models.BooleanField(default=True) diff --git a/requirements/base.txt b/requirements/base.txt index 5d5c461..b61eacc 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -62,4 +62,4 @@ git+https://github.com/olymk2/scaffold.git djangorestframework==3.5.4 django-filter==1.0.1 -django-markdownx +draceditor From 280601f3aa46abee6550832ec4b3d9065e719e05 Mon Sep 17 00:00:00 2001 From: Oliver Marks Date: Mon, 27 Feb 2017 19:33:38 +0000 Subject: [PATCH 3/3] enable image uploader --- config/settings/common.py | 4 +++ config/urls.py | 5 ++++ mhackspace/base/views.py | 57 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 mhackspace/base/views.py diff --git a/config/settings/common.py b/config/settings/common.py index 6488eae..decc12a 100644 --- a/config/settings/common.py +++ b/config/settings/common.py @@ -195,6 +195,10 @@ STATICFILES_FINDERS = ( # ------------------------------------------------------------------------------ # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root MEDIA_ROOT = str(APPS_DIR('media')) +import time +DRACEDITOR_UPLOAD_PATH = 'images/uploads/{}'.format(time.strftime("%Y/%m/%d/")) +DRACEDITOR_UPLOAD_URL = '/api/uploader/' # change to local uploader +MAX_IMAGE_UPLOAD_SIZE = 5242880 # 5MB # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url MEDIA_URL = '/media/' diff --git a/config/urls.py b/config/urls.py index e242ef0..5b04fce 100644 --- a/config/urls.py +++ b/config/urls.py @@ -15,6 +15,7 @@ from mhackspace.members.views import MemberListView from mhackspace.subscriptions import views as subscription from mhackspace.base.feeds import LatestEntriesFeed from mhackspace.blog.feeds import BlogFeed, BlogCategoryFeed +from mhackspace.base.views import markdown_uploader from mhackspace.blog.views import blog, PostViewSet, CategoryViewSet from mhackspace.feeds.views import FeedViewSet, ArticleViewSet @@ -34,6 +35,10 @@ urlpatterns = [ url(r'^api/v1/', include(router.urls, namespace='v1')), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), url(r'^draceditor/', include('draceditor.urls')), + url( + r'^api/uploader/$', + markdown_uploader, name='markdown_uploader_page' + ), url(r'^blog/$', blog, name='contact'), url(r'^blog/rss/$', BlogFeed()), url(r'^blog/(?P[0-9A-Za-z_\-]+)/$', blog, name='blog-item'), diff --git a/mhackspace/base/views.py b/mhackspace/base/views.py new file mode 100644 index 0000000..55ecc24 --- /dev/null +++ b/mhackspace/base/views.py @@ -0,0 +1,57 @@ +import os +import json +import uuid + +from django.conf import settings +from django.http import HttpResponse +from django.utils.translation import ugettext_lazy as _ +from django.contrib.auth.decorators import login_required +from django.core.files.storage import default_storage +from django.core.files.base import ContentFile + +from draceditor.utils import LazyEncoder + + +@login_required +def markdown_uploader(request): + """ + Makdown image upload for locale storage + and represent as json to markdown editor. + """ + if request.method == 'POST' and request.is_ajax(): + if 'markdown-image-upload' in request.FILES: + image = request.FILES['markdown-image-upload'] + image_types = [ + 'image/png', 'image/jpg', + 'image/jpeg', 'image/pjpeg', 'image/gif' + ] + if image.content_type not in image_types: + data = json.dumps({ + 'status': 405, + 'error': _('Bad image format.') + }, cls=LazyEncoder) + return HttpResponse( + data, content_type='application/json', status=405) + + if image._size > settings.MAX_IMAGE_UPLOAD_SIZE: + to_MB = settings.MAX_IMAGE_UPLOAD_SIZE / (1024 * 1024) + data = json.dumps({ + 'status': 405, + 'error': _('Maximum image file is %(size) MB.') % {'size': to_MB} + }, cls=LazyEncoder) + return HttpResponse( + data, content_type='application/json', status=405) + + img_uuid = "{0}-{1}".format(uuid.uuid4().hex[:10], image.name.replace(' ', '-')) + tmp_file = os.path.join(settings.DRACEDITOR_UPLOAD_PATH, img_uuid) + def_path = default_storage.save(tmp_file, ContentFile(image.read())) + img_url = os.path.join(settings.MEDIA_URL, def_path) + + data = json.dumps({ + 'status': 200, + 'link': img_url, + 'name': image.name + }) + return HttpResponse(data, content_type='application/json') + return HttpResponse(_('Invalid request!')) + return HttpResponse(_('Invalid request!'))