Frequently Asked Questions

This page answers common questions about Martor. If you don’t find your answer here, check the Troubleshooting guide or create an issue on GitHub.

General Questions

What is Martor?

Martor is a Django application that provides a rich markdown editor for web applications. It integrates seamlessly with Django models, forms, and admin interface, offering features like live preview, syntax highlighting, image upload, user mentions, and emoji support.

Why choose Martor over other markdown editors?

Martor offers several advantages:

  • Deep Django integration - Works seamlessly with models, forms, and admin

  • Dual theme support - Bootstrap and Semantic-UI compatible

  • Security-focused - Built-in XSS protection and HTML sanitization

  • Feature-rich - Image upload, mentions, emoji, video embedding

  • Extensible - Custom markdown extensions and easy customization

  • Production-ready - Used in many production applications

Is Martor free to use?

Yes! Martor is released under the GNU General Public License v3.0 (GPL-3.0), making it free to use in both personal and commercial projects, provided you comply with the license terms.

Installation & Setup

What are the minimum requirements?

  • Python: 3.9+

  • Django: 3.2+

  • Markdown: 3.0+

  • Modern browser with JavaScript support

Can I use Martor with older Django versions?

Martor officially supports Django 3.2+. While it might work with older versions, we recommend upgrading Django for security and feature benefits.

Do I need to run migrations after installing Martor?

No! Martor doesn’t include any database models, so no migrations are required. Simply add 'martor' to INSTALLED_APPS and include the URLs.

Can I use Martor without collecting static files?

No, you must run python manage.py collectstatic to make Martor’s CSS, JavaScript, and other assets available to your application.

Configuration

What’s the difference between Bootstrap and Semantic UI themes?

Both themes provide the same functionality but with different styling:

  • Bootstrap theme: Uses Bootstrap CSS classes and styling

  • Semantic UI theme: Uses Semantic UI CSS classes and styling

Choose based on your existing frontend framework. The theme affects only appearance, not functionality.

Can I use both themes in the same project?

No, you can only use one theme at a time. The MARTOR_THEME setting applies globally to all Martor instances in your project.

How do I disable specific toolbar buttons?

Customize the MARTOR_TOOLBAR_BUTTONS setting:

# Remove buttons you don't want
MARTOR_TOOLBAR_BUTTONS = [
    'bold', 'italic', 'heading', 'link',
    # Removed: 'image-upload', 'emoji', 'direct-mention'
]

Usage Questions

Can I use multiple Martor fields in the same model?

Yes! You can use as many MartorField instances as needed:

class Product(models.Model):
    description = MartorField(verbose_name="Product Description")
    specifications = MartorField(verbose_name="Technical Specs")
    instructions = MartorField(verbose_name="Usage Instructions")

How do I convert existing TextField to MartorField?

Since MartorField inherits from TextField, no data migration is needed:

# Before
class Article(models.Model):
    content = models.TextField()

# After - existing data is preserved
class Article(models.Model):
    content = MartorField()

Can I use Martor with Django REST Framework?

Yes! MartorField works with DRF serializers:

from rest_framework import serializers

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ['title', 'content']  # MartorField works normally

How do I render markdown content in templates?

Use the safe_markdown template filter:

{% load martortags %}
{{ article.content|safe_markdown }}

Can I search within markdown content?

Yes, you can use Django’s standard text search on MartorField:

# Simple search
articles = Article.objects.filter(content__icontains='django')

# Full-text search (PostgreSQL)
from django.contrib.postgres.search import SearchVector
articles = Article.objects.annotate(
    search=SearchVector('title', 'content')
).filter(search='django tutorial')

Features & Functionality

How do I set up image upload?

You have two options:

  1. Use imgur.com (easiest):

# settings.py
MARTOR_IMGUR_CLIENT_ID = 'your-client-id'
MARTOR_IMGUR_API_KEY = 'your-api-key'
  1. Custom uploader (recommended for production):

See examples/custom-uploader for implementation details.

How do user mentions work?

Enable mentions in settings and implement a user search endpoint:

# settings.py
MARTOR_ENABLE_CONFIGS = {'mention': 'true'}
MARTOR_SEARCH_USERS_URL = '/my-user-search/'

Users can then type @[username] to mention others.

Can I disable the live preview?

Yes, set living to false:

# settings.py
MARTOR_ENABLE_CONFIGS = {'living': 'false'}

How do I add custom markdown extensions?

Add them to MARTOR_MARKDOWN_EXTENSIONS:

# settings.py
MARTOR_MARKDOWN_EXTENSIONS = [
    # ... default extensions
    'my_app.markdown_extensions.custom_extension',
]

What video platforms are supported for embedding?

Martor supports embedding from:

  • YouTube

  • Vimeo

  • Dailymotion

  • Yahoo Video

  • Veoh

  • Metacafe

Simply paste the video URL in the editor.

Performance & Scaling

Is Martor suitable for high-traffic websites?

Yes! Martor is used in production by many high-traffic sites. For optimal performance:

  • Cache rendered HTML using Django’s cache framework

  • Disable live preview for better performance

  • Use a CDN for static assets

  • Consider database indexing for content search

How do I optimize performance with large content?

  1. Disable real-time features:

MARTOR_ENABLE_CONFIGS = {
    'living': 'false',
    'spellcheck': 'false',
}
  1. Cache rendered content:

from django.core.cache import cache
from martor.utils import markdownify

def get_cached_html(markdown_content, cache_key):
    html = cache.get(cache_key)
    if html is None:
        html = markdownify(markdown_content)
        cache.set(cache_key, html, 3600)  # 1 hour
    return html
  1. Use database indexing:

class Article(models.Model):
    content = MartorField(db_index=True)

Can I use Martor with multiple databases?

Yes, MartorField works with Django’s multiple database support just like any other field.

Security

Is Martor secure against XSS attacks?

Yes! Martor includes built-in security features:

  • HTML sanitization using the bleach library

  • Whitelist approach for allowed HTML tags and attributes

  • Safe rendering through the safe_markdown filter

The default configuration only allows safe HTML elements.

Can users inject malicious content?

Martor’s security features prevent most attacks:

  • Script tags are stripped by default

  • Only whitelisted HTML tags are allowed

  • URLs are validated against allowed schemes

  • The escape_html extension handles edge cases

However, always validate user input and consider your specific security requirements.

How do I further restrict allowed content?

Customize the security settings:

# settings.py
ALLOWED_HTML_TAGS = ['p', 'strong', 'em', 'a', 'ul', 'ol', 'li']
ALLOWED_HTML_ATTRIBUTES = ['href', 'title']
ALLOWED_URL_SCHEMES = ['http', 'https', 'mailto']

Customization

Can I customize the editor’s appearance?

Yes! You can:

  1. Override CSS:

.martor-field {
    border-radius: 10px;
    /* Your custom styles */
}
  1. Use custom theme files:

# settings.py
MARTOR_ALTERNATIVE_CSS_FILE_THEME = 'custom/my-theme.css'
MARTOR_ALTERNATIVE_JS_FILE_THEME = 'custom/my-theme.js'
  1. Override templates:

Create your own templates in templates/martor/bootstrap/ or templates/martor/semantic/.

How do I add custom toolbar buttons?

This requires custom JavaScript development. You can:

  1. Create a custom widget with additional buttons

  2. Extend Martor’s JavaScript files

  3. Add custom ACE editor commands

Can I use a different code editor instead of ACE?

Martor is built specifically around the ACE editor. Switching to a different editor would require significant modification of the codebase.

Can I integrate with my existing CSS framework?

Yes! While Martor officially supports Bootstrap and Semantic UI, you can:

  1. Use custom CSS to override styling

  2. Create custom theme files

  3. Override templates to match your HTML structure

Migration & Upgrading

How do I migrate from django-markdownx?

  1. Install Martor alongside django-markdownx

  2. Update models one by one:

# Before
from markdownx.models import MarkdownxField
content = MarkdownxField()

# After
from martor.models import MartorField
content = MartorField()
  1. Update templates:

<!-- Before -->
{{ content|markdownify }}

<!-- After -->
{% load martortags %}
{{ content|safe_markdown }}
  1. Test thoroughly before removing django-markdownx

How do I upgrade Martor versions?

  1. Check the changelog for breaking changes

  2. Update the package:

pip install -U martor
  1. Collect static files:

python manage.py collectstatic
  1. Test your application thoroughly

What happens to existing data when upgrading?

Your markdown content is preserved during upgrades. However:

  • Check for changes in markdown rendering

  • Test custom extensions compatibility

  • Verify security settings are still appropriate

Development & Debugging

How do I debug Martor issues?

  1. Enable Django debug mode:

DEBUG = True
  1. Check browser console for JavaScript errors

  2. Test individual endpoints (e.g., /martor/markdownify/)

  3. Check server logs for Python errors

Can I contribute to Martor development?

Absolutely! Martor welcomes contributions:

  1. Report bugs on GitHub Issues

  2. Submit pull requests for fixes or features

  3. Improve documentation

  4. Share your use cases and feedback

How do I create custom markdown extensions?

Create a Python module following Python-Markdown’s extension API:

from markdown.extensions import Extension
from markdown.preprocessors import Preprocessor

class MyExtension(Extension):
    def extendMarkdown(self, md):
        md.preprocessors.register(
            MyPreprocessor(md), 'my_preprocessor', 175
        )

def makeExtension(**kwargs):
    return MyExtension(**kwargs)

Getting Help

Where can I get help with Martor?

  1. Documentation: Start with this documentation

  2. GitHub Issues: Search existing issues or create new ones

  3. Django Community: Ask in Django forums or Slack channels

  4. Stack Overflow: Tag questions with django-martor

How do I report bugs?

When reporting bugs, include:

  • Django and Martor versions

  • Browser and version

  • Complete error messages

  • Minimal code to reproduce the issue

  • Steps to reproduce the problem

What information should I include in bug reports?

Essential information:

  • Environment: Python, Django, Martor versions

  • Browser: Name and version

  • Error messages: Complete tracebacks

  • Code: Minimal example that reproduces the issue

  • Configuration: Relevant settings

  • Steps: Exact steps to reproduce the problem

Template:

## Environment
- Django: 4.2.0
- Martor: 1.8.1
- Python: 3.9.0
- Browser: Chrome 91.0

## Problem Description
[Clear description of the issue]

## Steps to Reproduce
1. [First step]
2. [Second step]
3. [Result]

## Expected Behavior
[What should happen]

## Actual Behavior
[What actually happens]

## Code
[Minimal code example]

Still have questions?

If your question isn’t answered here:

  1. Check the Troubleshooting guide

  2. Search GitHub Issues

  3. Create a new issue with detailed information

Next Steps