Search code examples
pythondjangodjango-crispy-forms

Is it possible to add a feature to attach code-blocks to a post form?


I've been trying to find something about this for a while, but I don't know if its my wording but I can't seem to find anything about it.

Anyways... I'm working on a project for school, and basically it's a website that does many things, and one of those things is like a mini-stackoverflow thing but just for my school's community. So I have designed a form for the post using crispy forms however I can't seem to find any information on how to add the feature to write in code blocks to a form (just like we do here on Stack Overflow).

This is what the form looks like on code:

Template:

<form method="POST" enctype="multipart/form-data">
                    {% csrf_token %}
                    <fieldset class="form-group">
                        <legend class="border-bottom mb-4">Nueva Publicación</legend>
                        {{ form|crispy }}
                    </fieldset>
                    <div>
                    <div class="form-group">
                        <button class="btn btn-outline-info" type="submit">Crear Publicación</button>
                    </div>
                </form>

Models

class Post(models.Model):
titulo  = models.CharField(max_length=150)
contenido = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
imagen = models.ImageField(default='default.jpg', upload_to='blog_images')

def __str__(self):
    return self.titulo

def get_absolute_url(self):
    return reverse("post-detail", kwargs={"pk": self.pk})

Visually:

form_post

If you guys need anything else in order to help, please tell me and I will provide ASAP.


Solution

  • You need a module that can translate Markdown-formatted text into HTML. It looks like django-markdownx can do this for you.

    Just follow the Installation and Getting Started directions, which I have summarized below.

    First, install MarkdownX:

    pip install django-markdownx
    

    In settings.py, add it to your list of installed apps:

    INSTALLED_APPS = (
        # [...]
        'markdownx',
    )
    

    In urls.py, add MarkdownX URLs:

    urlpatterns = [
        # [...]
        path('markdownx/', include('markdownx.urls')),
    ]
    

    Make sure you have a STATIC_ROOT setting in settings.py. This line will create a static directory in the root folder of your project:

    STATIC_ROOT = BASE_DIR / 'static'
    

    Add MarkdownX static assets to STATIC_ROOT:

    python3 manage.py collectstatic
    

    Change Post.contenido to use MarkdownxField:

    from markdownx.models import MarkdownxField
    from markdownx.utils import markdownify
    
    class Post(models.Model):
        # title = ...
        contenido = MarkdownxField() # not models.TextField()
        # date_posted, author, etc.
    
        def formatted(self):
            "Returns formatted HTML for post content."
            return markdownify(self.contenido)
    

    In your template, add {{ form.media }} after your </form> tag.

    Now, your post content should appear with Markdown formatting whenever you use {{ post.formatted|safe }} in a template, like this:

    {% extends "base.html" %}
    
    {% block content %}
    <h2>{{ object.title }}</h2>
    {{ object.formatted|safe }}
    {% endblock %}
    

    I tested this with Django 4.0.2, django-markdownx 3.0.1, and markdown 3.3.6.