Using Markdown in Django

Hello, Habr!

In this article we will learn use Markdown with Django on a blog example. It is written for beginners, for basic familiarization. Its in the format .md can be downloaded in my developing Telegram channel.

Markdown is a simple markup language used to create rich text (such as HTML) using a text editor. By the way, I wrote this article using the syntax Markdown)

Creating and activating a virtual environment

python -m venv venv

source venv/bin/activate

Installing required packages

pip install Django==4.2

Version Django relevant at the moment 2024 of the year.

pip install markdown

Website and application creation

django-admin startproject markdown_blog

cd markdown_blog

python manage.py startapp posts

We create:

Creating a Post Model

Open the file posts/models.pyand write the following:

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


class Post(models.Model):
    title = models.CharField(max_length=250)
    slug = models.SlugField(max_length=250)
    author = models.ForeignKey(User,
    on_delete=models.CASCADE,
    related_name="blog_posts")
    body = models.TextField()

	def __str__(self):
		return self.title

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

We created a model Postwhich has the following fields:

  • title – Heading, up to 250 characters long

  • slug – Slug, up to 250 characters long

  • author – ForeignKey to the model User. When you delete a user, all of his posts are deleted.

  • body – Post text (we will work with this field)

Add the application to markdown_blog/settings.py:

INSTALLED_APPS = [
				  # other apps,
				  'posts.apps.PostsConfig',
]

Create and run migrations:

python manage.py makemigrations

python manage.py migrate

Registering a model in the admin panel

Open the file posts/admin.py and write the following:

from django.contrib import admin
from .models import Post

admin.site.register(Post)

We have registered the model Post in the admin panel.

Creating Views and Templates

Open the file posts/views.pyand write the following:

from django.shortcuts import render, get_object_or_404

from .models import Post


def post_list(request):
    posts = Post.objects.all()
    return render(request,
    'post_list.html',
    {'posts': posts})

def post_detail(request, id):
	post = get_object_or_404(Post,
	id=id)
	return render(request,
	'post_detail.html',
	{'post': post})
	

We created two simple views:

  • post_list – Receives a list of posts from the database and passes it to the template post_list.html.

  • post_detail – Retrieves a post from the database idand passes it to the template post_detail.html.

Create a directory posts/templates and inside create a new file post_list.html. Write the following in it:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>List of posts</title>
</head>

<body>
{% for post in posts %}
<h2>
	<a href="https://habr.com/ru/articles/810119/{{ post.get_absolute_url }}">{{ post.title }}</a>
</h2>
<div>
	{{ post.body|truncatewords_html:30 }}
</div>
{% endfor %}
</body>
</html>

Inside posts/templates create a file post_detail.html. Write the following in it:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Post: {{ post.title }}</title>
</head>

<body>
<a href="https://habr.com/ru/articles/810119/{% url"post_list" %}">List of posts</a>
<h2>
	{{ post.title }}
</h2>
<div>
	{{ post.body }}
</div>
</body>
</html>

Open the file markdown_blog/urls.pyand write the following:

from django.contrib import admin
from django.urls import path

from posts import views

urlpatterns = [
  path('admin/', admin.site.urls),
  path('', views.post_list, name="post_list"),
  path('<int:id>/', views.post_detail, name="post_detail"),
]

We created two URL for our ideas.

Adding Markdown syntax to your site

One way to add syntax Markdown to the site – this is creation specifically applied template filter.

Create a package posts/templatetagscreate files post_tags.py, and __init.py__. File post_tags.py will contain our library specifically applied template filters and tags. Write the following in it:

from django import template
from django.utils.safestring import mark_safe

import markdown

register = template.Library()


@register.filter(name="markdown")
def markdown_format(text):
    return mark_safe(markdown.markdown(text))

We use the web framework provided Django function
mark_safeto mark the result as safe for drawing in the template source code HTML. Default Django will not trust any source code HTML and will escape it before inserting it
to the result. The only exceptions are variables that
marked as safe to avoid shielding. This
behavior does not give Django output potentially dangerous source code
HTML and allows you to create exceptions to return safe source code HTML.

Edit the file templates/post_detail.html:

{% load post_tags %}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Post: {{ post.title }}</title>
</head>

<body>
<a href="https://habr.com/ru/articles/810119/{% url"post_list" %}">List of posts</a>
<h2>
	{{ post.title }}
</h2>
<div>
	{{ post.body|markdown }}
</div>
</body>
</html>

Edit the file templates/post_list.html:

{% load post_tags %}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>List of posts</title>
</head>

<body>
{% for post in posts %}
<h2>
	<a href="https://habr.com/ru/articles/810119/{{ post.get_absolute_url }}">{{ post.title }}</a>
</h2>
<div>
	{{ post.body|markdown|truncatewords_html:30 }}
</div>
{% endfor %}
</body>
</html>

Examination

Create a superuser:

python manage.py createsuperuser

Follow all instructions and start the development server:

python manage.py runserver

Go to the address 127.0.0.1:8000/admin, log in using the previously entered data. Through the admin panel, add several posts (using the syntax Markdown). Some texts are below:

**Модель** — это единственный и точный источник информации о ваших данных. Он содержит основные поля и поведение данных, которые вы храните. Обычно каждая модель сопоставляется с одной таблицей базы данных.

### Основы
- - -

- Каждая модель представляет собой класс Python, который является подклассом `django.db.models.Model`.
- Каждый атрибут модели представляет поле базы данных.
- При всем этом Django предоставляет вам автоматически генерируемый API доступа к базе данных; см. [Создание запросов](https://docs.djangoproject.com/en/5.0/topics/db/queries/).


- - -
## MTV

Django подчиняется шаблону архитектурного дизайна **MTV** (Model-Template-View)

Обязанности в шаблоне архитектурного дизайна MTV Django распределе-
ны следующим образом:

- **Model** (модель) – определяет логическую структуру данных и является обработчиком данных между базой данных и их представлением

- **Template** (шаблон) – это слой представления. В Django используется система текстовых шаблонов, в которой хранится все, что браузер прорисовывает на страницах.

- **View** (представление) – взаимодействует с базой данных через модель и передает данные в шаблон для их прорисовки и просмотра.


- - -

Go to address 127.0.0.1:8000. You should see a list of posts. Click on one of the links, you will see the entire contents of the page.

Bottom line

We have implemented one of the options for using the syntax Markdown V Django. The purpose of the article was not to implement ideal blog, but only the simplest implementation of such a task. In the future, you can embed an editor on the site for convenient writing of pages using Markdown. But that’s a completely different story), we’ll look at it later.

PS this is my first article. Bye everyone, Control + D!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *