Home > Software engineering >  Django forms - display HTML <pre> code snippets within rendered {{ form.text }}
Django forms - display HTML <pre> code snippets within rendered {{ form.text }}

Time:01-24

I have a blog set up with Django that I use to post some of my notes and personal how-tos. I have an articles model that takes data from a form rendered in the template. The application displays my articles posted dynamically in the template. My goal is to include code snippets as a <pre> tag within the form data that I post, while writing as little HTML as possible.

models.py

from django.db import models
from django.contrib.auth import get_user_model
from django.db import models
from django.urls import reverse

class Article(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(
            get_user_model(),
            on_delete=models.CASCADE,
        )

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('article_detail', args=[str(self.id)])


views.py

from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import ListView, DetailView
from django.views.generic.edit import UpdateView, DeleteView, CreateView
from django.urls import reverse_lazy
from .models import Article 

class ArticleListView(LoginRequiredMixin, ListView):
    model = Article
    template_name = 'article_list.html'

class ArticleCreateView(LoginRequiredMixin, CreateView):
    model = Article 
    template_name = 'article_new.html'
    fields = ('title', 'body',)
    
    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

templates/article_new.html

{% extends 'base.html' %}
{% block title %}New article{% endblock title %}

{% block content %}
<h1>New article</h1>
<form action='' method='post'>
    {% csrf_token %}
    {{ form.as_p }}
    <button class='btn btn-success ml-2' type='submit'>Save</button>
</form>
{% endblock content %}

templates/article_list.html

{% extends 'base.html' %}
{% block title %}Articles{% endblock title %}

{% block content %}
<br/>

    <div class='row'>
        <div class='col-8'>
            {% for article in object_list %}
                <div class='card' style='background: #292b2c'>
                    <div class='card-header' style='background: #292b2c;'>
                        <span class='font-weight-bold'>{{ article.title }}</span> &middot;
                        <span class='text-muted'>by {{ article.author }} | {{ article.date }}</span>
                    </div>
                    <div class='card-body' style='background: #1a1a1a;'>
                        <p>{{ article.body|linebreaks }}</p>
                        <a href="{% url 'article_edit' article.pk %}">edit<a> | <a href="{% url 'article_delete' article.pk %}">Delete</a>
                    </div>
                    <div class='card-footer' style='background: #292b2c'>
                        {% for comment in article.comments.all %}
                            <p class='font-weight-bold'>
                            <span class='font-weight-bold'>{{ comment.author }} &middot;</span>
                            {{ comment }}
                            </p>
                        {% endfor %}
                    </div>
                </div>
                <br />
            {% endfor %}

Is there a way that I can display code snippets as a <pre> tag within the form I posted for tutorial purposes?

I tried wrapping the {{ articles.body }} in <pre> tags within the actual template but that will just turn all text into <pre>. I have successfully kept the whitespace from my original entry by using {{ articles.body|linebreaks }}

I don't necessarily want to use RichTextField() because I want to keep it simple but I will if I have to.

CodePudding user response:

If you want to keep it simple and short, you could add the safe templatetag to your body. This will allow you to render HTML from your input: https://docs.djangoproject.com/en/4.1/ref/templates/builtins/#safe

...
<div class='card-body' style='background: #1a1a1a;'>
    <p>{{ article.body|safe|linebreaks }}</p>
    ...
</div>
...

And then, when you're writing the blog, you can wrap the code inside a <pre> tag:

Hello this is my tutorial
This is a piece of code:
<pre>my_function()</pre>
Hope you enjoyed it!

And that will be rendered.

  • Related