Django: setting up project/app to use Jinja syntax in Markdown posts

I'm migrating my website from Eleventy to Django. I had Eleventy set up with some custom Nunjucks filters/shortcodes or whatever they're called so I could use Nunjucks for including responsive web images as well as custom HTML media player code for video files, instead of having to write out HTML in the Markdown file every time. I'm trying to replicate that simplification in Django via Jinja (as it's basically the same thing, by Nunjucks' own admission), but I'm having a time wrapping my head around the learning curve for the different things I need to tackle in order to do this. From what I think I understand so far, I have a few obstacles:

  1. Figuring out how to get my Django project/app to process Jinja syntax in Markdown files and convert it to HTML. I found what looks like a good context explainer here (https://stackoverflow.com/a/32254521/21423257), but it's more of a general heads-up and doesn't explain what you need to actually do to your project/app to make this work. I'm using the Markdown plugin, I assume that will be adequate but if not, I'm open to using one of the other Markdown plugins if they're better suited for this task.

  2. Posting multiple images and/or video files in a Markdown post. My Markdown posts usually follow this format:

Here is some text.

{Here is some Jinja code to display an image or video file}

Here is some more text.

{Here is some more Jinja code to display an image or video file}

From what I've seen on here, it seems like if you're going to post multiple images/files in a markdown post, it's best to make a separate model to handle images, and then you put those image/file URLs into the post. However, the examples I see usually put those images in some kind of gallery where they call the URLs with a for loop, and they assume you'll have other users posting images to the site, so they make forms to upload images, and that's not how I'll use or handle the files (see the example above). I'm the sole user, so I will add posts/images/media through the admin page only. Is making a model for media files the best approach for my use case?

  1. I use responsive web design as well as image optimization for my images (small/medium/large versions for desktop and mobile viewing, plus a couple different file formats for compatibility), and it seems like Pillow is good to use for that. I haven't looked into this much yet because I'm just trying to get the images to show up in the first place, but I'll mention it here in case adding this changes the code I use or how I have Django handle the media files.

With all that in mind, what do I need to add or modify in my project/app to make all this work? Here's all the relevant info in the files:

settings.py

STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, 'static'),)
STATIC_ROOT = BASE_DIR / 'staticfiles'

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

models.py

from django.db import models
from django.utils import timezone
from django.template.defaultfilters import slugify
from django.urls import reverse


class Tag(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class Article(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    slug = models.SlugField(null=False, unique=True)
    date = models.DateTimeField(default=timezone.now)
    tags = models.ManyToManyField("Tag", related_name="articles")
    image = models.FileField(blank=True)
    # Add line for video?

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("article_detail", kwargs={"slug": self.slug})

# Taken from https://soshace.com/2020/08/18/upload-multiple-images-to-a-django-model-without-plugins/       
class ArticleFile(models.Model):
    article = models.ForeignKey(Article, default=None, on_delete=models.CASCADE)
    images = models.FileField(upload_to = 'images')
    # Add line for video? models.FileField(upload_to = 'videos')
    
    def __str__(self):
        return self.article.title
# End image model

urls.py (project)

[...snip, but at the end of the file I have:]

if settings.DEBUG:  # new
    urlpatterns + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

views.py

from django.shortcuts import render
from django.views import generic
from .models import Tag, Article
from django.http import JsonResponse

class ArticleListView(generic.ListView):
    model = Article
    paginate_by = 6
    template_name = "index.html"

class ArticleDetailView(generic.DetailView):
    model = Article
    template_name = "article.html"

markdown.py (in my templatetags folder)

from django import template
from django.template.defaultfilters import stringfilter

import markdown as md

register = template.Library()


@register.filter()
@stringfilter
def markdown(value):
    return md.markdown(value)

jinja2.py (in my application folder)

from jinja2 import Environment 
from django.urls import reverse  
from django.templatetags.static import static


def environment(**options):  
    env = Environment(**options)  
    env.globals.update({  
        "static": static,  
        "url": reverse  
    })  
    return env

I think that's all the relevant info, but if you need more info or context, let me know and I'll edit the post. I also wasn't sure if this is too much for one post, so if I need to break it up, let me know.

Вернуться на верх