djangodjango-templatespygments

Django - create code blocks in html templates


I would like to create a web page that will display data I have in a table inside a code block just the way it is here, even with a copy function. I can already display the data on the page, I just like to have it formatted in a pretty box, maybe even with syntax highlights, I looked at Pygments but I can't get it to work.

Below is a sample code block that I would like to re-create in my Django app. Please don't pay attention to the actual code, this is only a sample. I would appreciate if you could please let me know in detail how to implement this.

# Python Program to find the area of triangle

a = 5
b = 6
c = 7

# Uncomment below to take inputs from the user
# a = float(input('Enter first side: '))
# b = float(input('Enter second side: '))
# c = float(input('Enter third side: '))

# calculate the semi-perimeter
s = (a + b + c) / 2

# calculate the area
area = (s*(s-a)*(s-b)*(s-c)) ** 0.5
print('The area of the triangle is %0.2f' %area)

Solution

  • Honestly, your question is more related to CSS and Javascript than Python / Django.

    This took me a while...Based on what you said, I will assume you know the basics of Django.

    models.py

    from django.db import models
    
    class Codeblock(models.Model):
        text = models.TextField()
        ...
    

    views.py

    from .models import Codeblock
    
    def codes(request):
        codeblocks = Codeblock.objects.all()
        return render(request, 'list_codes.html', {'codeblocks': codeblocks})
    

    To format code blocks you can use HTML pre and code tags (Bootstrap 5 examples):

    <pre><code>{{codeblocks.text}}</code></pre>
    

    The tricky part was trying to find a way to hightlight the syntax. After a few dead ends I have found highlight.js that worked very well. It has documentation on basic usage and various themes for you to play with, you can test them using this CDN library, it is also possible to write your own theme.

    There was one last problem related on how to copy the text. Although it is easy to copy text to clipboard, its not an easy task (at least for me) to have a styled button placed in the right place. To not extend myself, after a while I found this highlightjs-copy project, that not only copy the text to clipboard but has a perfect button in the right place.

    With that being said, at last, here is an example:

    list_codes.html

    <!DOCTYPE html>
    <html>
        <head>
            <!-- bootstrap -->
            <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
            
            <!-- highlight.js -->
            <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/base16/ashes.min.css" integrity="sha512-KX15mI6Sw0VzQyAOf4MAPS9BZ0tWXyZrGPHKSkqDmy40Jl+79f8ltpj6FvLJ+3obnH56ww0ukclsd6xGAxb5mA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
            <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
            <script>hljs.highlightAll();</script>
            
            <!-- highlightjs-copy -->
            <script src="https://unpkg.com/highlightjs-copy/dist/highlightjs-copy.min.js"></script>
            <link
            rel="stylesheet"
            href="https://unpkg.com/highlightjs-copy/dist/highlightjs-copy.min.css"
            />
            <script>hljs.addPlugin(new CopyButtonPlugin());</script>
    
        </head>
    <body style="background-color: hsl(0,0%,22.5%);">
        {% for codeblock in codeblocks %}
            <div class="container">
                <!-- Need to be in one line or will not render correctly -->
                <pre><code class="language-python">{{codeblock.text}}</code></pre>
            </div>
        {% endfor %}
    </body>
    </html>