2015-09-07 12:41:44 +00:00
# django-markdownx [](https://pypi.python.org/pypi/django-markdownx/)
2015-09-30 14:13:02 +00:00
[](https://travis-ci.org/adi-/django-markdownx)
[](https://pypi.python.org/pypi/django-markdownx/)
[](https://pypi.python.org/pypi/django-markdownx/)
[](https://pypi.python.org/pypi/django-markdownx/)
[](https://pypi.python.org/pypi/django-markdownx/)
2014-11-01 21:02:31 +00:00
2016-05-15 11:13:35 +00:00
Django Markdownx is a Markdown editor built for Django. It enables raw editing, live preview and image uploads (stored locally in `MEDIA` folder) with drag& drop functionality and auto tag insertion.
2015-09-07 08:31:11 +00:00

2016-05-15 11:36:20 +00:00
2016-05-15 11:38:54 +00:00
< sup > *(using Bootstrap for layout and styling)*< / sup >
2015-09-07 08:31:11 +00:00
2016-05-15 11:13:35 +00:00
Template is highly customizable, so you can easily use i.e. Bootstrap to layout editor pane and preview pane side by side. Using multiple editors on one page is supported.
*Side note: Just to keep it simple, all UI editing controls are unwelcome – this is Markdown editor not a web MS Word imitation.*
2015-09-07 08:32:28 +00:00
2016-05-15 11:13:35 +00:00
# Menu
2015-09-07 08:29:07 +00:00
* [Quick Start ](#quick-start )
* [Usage ](#usage )
* [Model ](#model )
* [Form ](#form )
* [Django Admin ](#django-admin )
* [Customization ](#customization )
* [Settings ](#settings )
2016-05-14 18:07:29 +00:00
* [Widget's custom template ](#widgets-custom-template )
2016-05-14 10:21:42 +00:00
* [Custom image insertion tag ](#custom-image-insertion-tag )
2016-05-14 18:07:29 +00:00
* [JS events ](#js-events )
2015-09-07 08:29:07 +00:00
* [Dependencies ](#dependencies )
* [Changelog ](#changelog )
* [License ](#license )
2016-05-14 18:07:29 +00:00
* [Package Requests ](#package-requests )
* [Notes ](#notes )
2015-09-07 08:29:07 +00:00
2015-09-06 07:41:45 +00:00
# Quick Start
2014-11-01 21:02:31 +00:00
2015-09-06 18:58:04 +00:00
1. Install `django-markdownx` package.
2014-11-01 21:02:31 +00:00
2016-05-15 11:13:35 +00:00
```bash
2015-09-06 07:41:45 +00:00
pip install django-markdownx
```
2014-11-01 21:02:31 +00:00
2015-09-06 18:58:04 +00:00
1. Add `markdownx` to your `INSTALLED_APPS` .
2014-11-01 21:02:31 +00:00
2015-09-06 07:41:45 +00:00
```python
#settings .py
INSTALLED_APPS = (
[...]
'markdownx',
2015-09-06 18:58:04 +00:00
)
2015-09-06 07:41:45 +00:00
```
2015-09-06 18:58:04 +00:00
1. Add url pattern to your `urls.py` .
2014-11-01 22:16:52 +00:00
2015-09-06 07:41:45 +00:00
```python
#urls .py
urlpatterns = [
[...]
url(r'^markdownx/', include('markdownx.urls')),
]
```
2015-09-06 18:58:04 +00:00
1. Collect included `markdownx.js` and `markdownx.css` (for django admin styling) to your `STATIC_ROOT` folder.
2015-09-06 07:41:45 +00:00
2016-05-15 11:13:35 +00:00
```bash
2015-09-06 07:41:45 +00:00
python manage.py collectstatic
```
2015-09-06 18:58:04 +00:00
1. ...and don't forget to include jQuery in your html file.
2015-09-06 07:41:45 +00:00
```html
< head >
[...]
< script src = "//code.jquery.com/jquery-2.1.1.min.js" > < / script >
< / head >
```
# Usage
2015-09-07 08:29:07 +00:00
## Model
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
```python
#models.py
from markdownx.models import MarkdownxField
class MyModel(models.Model):
2015-09-30 11:01:46 +00:00
2015-09-07 08:29:07 +00:00
myfield = MarkdownxField()
```
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
...and then, include a form's required media in the template using `{{ form.media }}` :
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
```html
< form method = "POST" action = "" > {% csrf_token %}
{{ form }}
< / form >
{{ form.media }}
```
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
## Form
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
```python
#forms.py
from markdownx.fields import MarkdownxFormField
class MyForm(forms.Form):
2015-09-30 11:01:46 +00:00
2015-09-07 08:29:07 +00:00
myfield = MarkdownxFormField()
```
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
...and then, include a form's required media in the template using `{{ form.media }}` :
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
```html
< form method = "POST" action = "" > {% csrf_token %}
{{ form }}
< / form >
{{ form.media }}
```
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
## Django Admin
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
When using included `MarkdowxModel` class in your models, just use `MarkdownxModelAdmin` as follows:
2015-09-06 21:13:50 +00:00
2015-09-07 08:29:07 +00:00
```python
#admin.py
from django.contrib import admin
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
from markdownx.admin import MarkdownxModelAdmin
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
from .models import MyModel
2015-09-06 07:41:45 +00:00
2015-09-07 08:29:07 +00:00
admin.site.register(MyModel, MarkdownxModelAdmin)
```
2015-09-06 07:41:45 +00:00
2016-02-13 13:14:35 +00:00
However, when you want to use `markdownx` with other classes – lets say `TextField` – than override default widget as follows:
2015-09-06 21:13:50 +00:00
2015-09-07 08:29:07 +00:00
```python
#admin.py
from django.db import models
from django.contrib import admin
2015-09-06 21:13:50 +00:00
2015-09-07 08:29:07 +00:00
from markdownx.widgets import AdminMarkdownxWidget
2015-09-06 21:13:50 +00:00
2015-09-07 08:29:07 +00:00
from .models import MyModel
2015-09-06 21:13:50 +00:00
2015-09-07 08:29:07 +00:00
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.TextField: {'widget': AdminMarkdownxWidget},
}
2015-09-06 21:13:50 +00:00
2015-09-07 08:29:07 +00:00
admin.site.register(MyModel, MyModelAdmin)
```
2015-09-06 21:13:50 +00:00
2015-09-06 07:41:45 +00:00
2014-12-10 22:19:57 +00:00
# Customization
## Settings
2014-11-01 21:02:31 +00:00
2015-09-06 18:58:04 +00:00
Place settings in your `settings.py` to override default values:
2014-11-02 19:44:46 +00:00
2014-11-01 22:09:46 +00:00
```python
2014-11-01 23:20:50 +00:00
#settings.py
2016-02-12 13:18:32 +00:00
# Markdownify
2016-05-15 11:13:35 +00:00
MARKDOWNX_MARKDOWNIFY_FUNCTION = 'markdownx.utils.markdownify' # Default function that compiles markdown using defined extensions. Using custom function can allow you to pre-process or post-process markdown text. See below for more info.
2016-02-12 13:18:32 +00:00
2016-05-15 11:13:35 +00:00
# Markdown extensions
MARKDOWNX_MARKDOWN_EXTENSIONS = [] # List of used markdown extensions. See below for more info.
MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS = {} # Configuration object for used markdown extensions
2016-02-12 13:18:32 +00:00
# Markdown urls
2016-05-15 11:13:35 +00:00
MARKDOWNX_URLS_PATH = '/markdownx/markdownify/' # URL that returns compiled markdown text.
MARKDOWNX_UPLOAD_URLS_PATH = '/markdownx/upload/' # URL that accepts file uploads, returns markdown notation of the image.
2016-02-12 13:18:32 +00:00
# Media path
2016-05-15 11:13:35 +00:00
MARKDOWNX_MEDIA_PATH = 'markdownx/' # Path, where images will be stored in MEDIA_ROOT folder
2016-02-12 13:18:32 +00:00
# Image
2016-05-15 11:13:35 +00:00
MARKDOWNX_UPLOAD_MAX_SIZE = 52428800 # 50MB - maximum file size
MARKDOWNX_UPLOAD_CONTENT_TYPES = ['image/jpeg', 'image/png'] # Acceptable file content types
MARKDOWNX_IMAGE_MAX_SIZE = {'size': (500, 500), 'quality': 90,} # Different options describing final image processing: size, compression etc. See below for more info.
2016-02-12 13:18:32 +00:00
# Editor
2016-02-13 13:14:35 +00:00
MARKDOWNX_EDITOR_RESIZABLE = True # Update editor's height to inner content height while typing
2014-11-01 22:09:46 +00:00
```
2014-11-01 21:02:31 +00:00
2016-05-15 11:13:35 +00:00
#### MARKDOWNX_MARKDOWNIFY_FUNCTION
Default function that compiles markdown looks like:
```python
# utils.py
import markdown
from .settings import MARKDOWNX_MARKDOWN_EXTENSIONS, MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS
def markdownify(content):
return markdown.markdown(content, extensions=MARKDOWNX_MARKDOWN_EXTENSIONS, extension_configs=MARKDOWNX_MARKDOWN_EXTENSION_CONFIGS)
```
2016-05-14 18:07:29 +00:00
#### MARKDOWNX_MARKDOWN_EXTENSIONS
2016-02-12 13:18:32 +00:00
2016-05-15 11:34:09 +00:00
```python
2016-05-15 11:34:58 +00:00
#settings.py
2016-05-15 11:34:09 +00:00
MARKDOWNX_MARKDOWN_EXTENSIONS = [
'markdown.extensions.extra',
'markdown.extensions.nl2br',
'markdown.extensions.smarty',
]
```
2016-02-12 12:47:16 +00:00
2016-05-14 18:07:29 +00:00
*Visit [https://pythonhosted.org/Markdown/extensions/index.html ](https://pythonhosted.org/Markdown/extensions/index.html ) to read more about markdown extensions*.
2016-02-12 12:47:16 +00:00
2016-05-14 18:07:29 +00:00
#### MARKDOWNX_IMAGE_MAX_SIZE
Dict properties:
* **size** – (width, height). When `0` used, i.e.: (500,0), property will figure out proper height by itself
* **quality** – default: `90` – image quality, from `0` (full compression) to `100` (no compression)
* **crop** – default: `False` – if `True` , use `size` to crop final image
* **upscale** – default: `False` – if image dimensions are smaller than those in `size` , upscale image to `size` dimensions
## Widget's custom template
2014-11-01 21:02:31 +00:00
2015-09-06 07:41:45 +00:00
Default widget's template looks like:
2014-11-01 21:02:31 +00:00
2014-11-01 22:09:46 +00:00
```html
2015-09-06 07:41:45 +00:00
< div class = "markdownx" >
2014-11-02 20:10:09 +00:00
{{ markdownx_editor }}
2015-09-06 07:41:45 +00:00
< div class = "markdownx-preview" > < / div >
2014-11-01 22:09:46 +00:00
< / div >
```
2015-09-06 07:41:45 +00:00
2016-02-13 13:14:35 +00:00
When you want to use Bootstrap 3 and side-by-side panes (as in preview image above), just place `markdownx/widget.html` file in your project's 'TEMPLATE_DIRS' folder with:
2014-11-01 21:02:31 +00:00
2014-11-01 22:09:46 +00:00
```html
2015-09-06 07:41:45 +00:00
< div class = "markdownx row" >
< div class = "col-md-6" >
2014-11-02 20:10:09 +00:00
{{ markdownx_editor }}
2014-11-01 22:09:46 +00:00
< / div >
2015-09-06 07:41:45 +00:00
< div class = "col-md-6" >
< div class = "markdownx-preview" > < / div >
2014-11-01 22:09:46 +00:00
< / div >
< / div >
```
2014-11-01 21:02:31 +00:00
2016-05-14 18:07:29 +00:00
## Custom image insertion tag
2016-05-15 11:13:35 +00:00
Markdown uses `![]()` syntax to insert uploaded image file. This generates very simple html `<image>` tag. When you want to have more control and use your own html tags just create custom `form_valid()` function in `ImageUploadView` class.
2016-05-14 18:07:29 +00:00
2016-05-15 11:13:35 +00:00
Default `ImageUploadView` class looks like:
2016-05-14 18:07:29 +00:00
```python
#views.py
from django.http import JsonResponse
from django.views.generic.edit import FormView
from .forms import ImageForm
class ImageUploadView(FormView):
template_name = "dummy.html"
form_class = ImageForm
success_url = '/'
def form_invalid(self, form):
response = super(ImageUploadView, self).form_invalid(form)
if self.request.is_ajax():
return JsonResponse(form.errors, status=400)
else:
return response
def form_valid(self, form):
image_path = form.save()
response = super(ImageUploadView, self).form_valid(form)
if self.request.is_ajax():
image_code = ''.format(image_path)
return JsonResponse({'image_code': image_code})
else:
return response
```
# JS events
2016-02-12 10:47:23 +00:00
Each markdownx jQuery object triggers two basic events:
* 'markdownx.init'
* 'markdownx.update' – also returns 'response' variable containing markdownified text
```js
$('.markdownx').on('markdownx.init', function() {
console.log("INIT");
});
$('.markdownx').on('markdownx.update', function(e, response) {
console.log("UPDATE" + response);
});
```
2014-11-01 23:08:20 +00:00
# Dependencies
2015-09-06 07:41:45 +00:00
* Markdown
* Pillow
2015-09-30 11:22:35 +00:00
* Django
2015-09-06 07:41:45 +00:00
* jQuery
2014-11-01 21:02:31 +00:00
2015-09-06 07:41:45 +00:00
# Changelog
2014-11-01 21:02:31 +00:00
2016-05-14 10:18:00 +00:00
###### v1.5
* Possibility to customize image insertion code
2016-05-05 06:51:53 +00:00
###### v1.4.3
* Markdown abstractable function fix
2016-02-13 13:14:35 +00:00
###### v1.4.2
* Maintenance release
2016-02-12 13:03:53 +00:00
###### v1.4.1
* Make rendering the markdown abstractable
2016-02-12 10:47:23 +00:00
###### v1.4
* Added JS (jQuery) events
* Custom upload url path
* Fix when subclassing MarkdownxWidget
2015-10-28 08:54:36 +00:00
###### v1.3
* Added Markdown extension configuration setting
2015-10-19 18:10:45 +00:00
###### v1.2.1
* Fix by Eduard Sukharev: Fix accessing file length in python3
2015-10-13 15:34:31 +00:00
###### v1.2
* Added custom url path setting MARKDOWNX_URLS_PATH to compile markdown with custom view (i.e. for pre/post altering markdown text)
2015-10-09 08:44:28 +00:00
###### v1.1.3
* Setup tools fix
2015-10-06 07:55:15 +00:00
###### v1.1.2
* Critical fix for image upload
###### v1.1.1
* Package fix
2015-09-30 11:22:35 +00:00
###### v1.1
* Python 3.3+ support
* Very simple test added just to test python 3 support
2015-09-06 21:13:50 +00:00
###### v1.0.1
* Moved html logic from FormField to Widget to be able to override model objects other than included MarkdownxModel
* Fixed default value for `MARKDOWNX_EDITOR_RESIZABLE`
###### v1.0.0
2014-11-01 21:02:31 +00:00
2015-09-06 07:41:45 +00:00
* Warning: no backward compatibility
* Admin, Model and Form custom objects
* Django admin styles for compiled markdown
* Settings variables changed:
* MARKDOWNX_MAX_SIZE => MARKDOWNX_IMAGE_MAX_SIZE
* MARKDOWNX_MARKDOWN_KWARGS => MARKDOWNX_MARKDOWN_EXTENSIONS
* MARKDOWNX_MAX_UPLOADSIZE => MARKDOWNX_UPLOAD_MAX_SIZE
* MARKDOWNX_CONTENT_TYPES => MARKDOWNX_UPLOAD_CONTENT_TYPES
2014-11-01 21:02:31 +00:00
2015-09-06 07:41:45 +00:00
###### v0.4.2
2014-12-10 21:25:09 +00:00
* Path fix by argaen
2015-09-06 07:41:45 +00:00
###### v0.4.1
2014-12-03 19:32:27 +00:00
* Better editor height updates
* Refresh preview on image upload
* Small JS code fixes
2015-09-06 07:41:45 +00:00
###### v0.4.0
2014-11-14 11:29:37 +00:00
* editor auto height
2015-09-06 07:41:45 +00:00
###### v0.3.1
2014-11-14 10:11:36 +00:00
* JS event fix
2015-09-06 07:41:45 +00:00
###### v0.3.0
2014-11-13 09:40:51 +00:00
* version bump
2015-09-06 07:41:45 +00:00
###### v0.2.9
2014-11-12 15:04:21 +00:00
* Removed any inlcuded css
* Removed JS markdown compiler (full python support now with Markdown lib)
2015-09-06 07:41:45 +00:00
###### v0.2.0
2014-11-05 22:11:33 +00:00
* Allow to paste tabs using Tab button
2015-09-06 07:41:45 +00:00
###### v0.1.4
2014-11-03 10:04:22 +00:00
* package data fix
2015-09-06 07:41:45 +00:00
###### v0.1.3
2014-11-03 09:31:41 +00:00
* README.md fix on PyPi
2015-09-06 07:41:45 +00:00
###### v0.1.2
2014-11-03 09:14:41 +00:00
* critical setuptools fix
2015-09-06 07:41:45 +00:00
###### v0.1.1
2014-11-02 20:10:09 +00:00
* change context name `editor` to `markdownx_editor` for better consistency
2015-09-06 07:41:45 +00:00
###### v0.1.0
2014-11-01 21:02:31 +00:00
* init
2014-11-01 23:08:20 +00:00
2015-09-06 07:41:45 +00:00
# License
2016-05-15 11:13:35 +00:00
django-markdown is licensed under the open source BSD license. Read `LICENSE` file for details.
2015-09-06 07:41:45 +00:00
2016-05-14 18:07:29 +00:00
# Package requests
It would be nice if anyone could support this project by adding missing functionality:
* tests
2016-05-15 11:13:35 +00:00
* JS intelligent auto-scrolling when side-by-side panes used
2016-05-14 18:07:29 +00:00
2014-11-01 23:08:20 +00:00
# Notes
2015-09-06 21:13:50 +00:00
**django-markdownx** was inspired by great [django-images ](https://github.com/mirumee/django-images ) and [django-bootstrap-markdown ](http://thegoods.aj7may.com/django-bootstrap-markdown/ ) packages.