Django Custom Template Tags
For Django applications, you can create a custom template tag to easily mount the Traven editor inside your forms, seamlessly integrating with Django's ModelForm workflows.
1. Create the Template Tag
Inside your Django app (e.g., blog), create a templatetags directory with an __init__.py and a traven_tags.py file:
# blog/templatetags/traven_tags.py
from django import template
from django.utils.html import escape
register = template.Library()
@register.inclusion_tag('traven/editor.html')
def traven_editor(name="body", content=""):
"""
Usage: {% traven_editor name="body" content=form.body.value|default:"" %}
"""
return {
'name': name,
'content': content
}
And create the small inclusion template traven/editor.html in your templates directory:
<!-- templates/traven/editor.html -->
<traven-editor name="{{ name }}">
{{ content|escape }}
</traven-editor>
2. Use in your Templates
Load the tags and use them alongside a standard ModelForm:
{% extends 'base.html' %}
{% load traven_tags %}
{% block content %}
<form method="POST" action="{% url 'post_create' %}">
{% csrf_token %}
<!-- Render non-markdown fields normally -->
{{ form.title.label_tag }}
{{ form.title }}
<!-- Render the Traven editor for the body field -->
<label for="id_body">Body Content:</label>
{% traven_editor name="body" content=form.body.value|default:"" %}
<button type="submit">Save Post</button>
</form>
{% endblock %}
{% block scripts %}
<!-- Load the Traven bundle once per page -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@freedomware/traven@0.2.10/dist/traven.js"></script>
{% endblock %}
3. Handle in the View
Because Traven synchronizes a hidden <textarea>, Django's standard form binding works out of the box. The markdown string cleanly arrives in cleaned_data when the form is submitted.
# blog/views.py
from django.shortcuts import render, redirect
from .forms import PostForm
def post_create(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
# form.cleaned_data['body'] contains the raw Markdown from Traven
post = form.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_form.html', {'form': form})