Привет, Habr!
В этой статье мы научимся использовать Markdown вместе с Django на примере блога. Она написана для новичков, для базового ознакомления. Её в формате .md можно скачать в моём развивающемся Telegram канале.
Markdown — это простой язык разметки, используемый для создания форматированного текста (например, HTML) с помощью текстового редактора. Кстати, эту статью я писал, использую синтаксис Markdown)
Создание и активация виртуального окружения
python -m venv venv source venv/bin/activate
Установка необходимых пакетов
pip install Django==4.2
Версия Django является LTS (версия с долгосрочной поддержкой) на момент 2024 года.
pip install markdown
Создание сайта и приложения
django-admin startproject markdown_blog cd markdown_blog python manage.py startapp posts
Мы создаем:
проект markdown_blog
приложение posts
Создание модели поста
Откройте файл posts/models.py, и напишите следующее:
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])
Мы создали модель Post, в которой есть такие поля:
title- Заголовок, длиной до 250 символовslug- Слаг, длиной до 250 символовauthor- ForeignKey к модели User. При удалении пользователя удаляются все его посты.body- Текст поста (с этим полем мы и поработаем)
Добавьте приложение в markdown_blog/settings.py:
INSTALLED_APPS = [ # other apps, 'posts.apps.PostsConfig', ]
Создайте и выполните миграции:
python manage.py makemigrations python manage.py migrate
Регистрация модели в админ панели
Откройте файл posts/admin.py , и напишите следующее:
from django.contrib import admin from .models import Post admin.site.register(Post)
Мы зарегистрировали модель Post в админ панели.
Создание представлений и шаблонов
Откройте файл posts/views.py, и напишите следующее:
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})
Мы создали два простых представления:
post_list- Получает из базы данных список постов, и передаёт его в шаблон post_list.html.post_detail- Получает из базы данных пост по id, и передает его в шаблон post_detail.html.
Создайте директорию posts/templates и внутри создайте новый файл post_list.html. В него напишите следующее:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>List of posts</title> </head> <body> {% for post in posts %} <h2> <a href="{{ post.get_absolute_url }}">{{ post.title }}</a> </h2> <div> {{ post.body|truncatewords_html:30 }} </div> {% endfor %} </body> </html>
Внутри posts/templates создайте файл post_detail.html. В него напишите следующее:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Post: {{ post.title }}</title> </head> <body> <a href='{% url "post_list" %}'>List of posts</a> <h2> {{ post.title }} </h2> <div> {{ post.body }} </div> </body> </html>
Откройте файл markdown_blog/urls.py, и напишите следующее:
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'), ]
Мы создали два URL для наших представлений.
Добавление синтаксиса Markdown на сайт
Один из способов добавления синтаксиса Markdown на сайт - это создание конкретно-прикладного шаблонного фильтра.
Создайте пакет posts/templatetags, создайте файлы post_tags.py, и __init.py__. Файл post_tags.py будет содержать нашу библиотеку конкретно-прикладных шаблонных фильтров и тегов. В него напишите следующее:
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))
Мы используем предоставляемую веб-фреймворком Django функцию
mark_safe, чтобы помечать результат как безопасный для прорисовки в шаблоне исходный код HTML. По умолчанию Django не будет доверять никакому исходному коду HTML и будет экранировать его перед его вставкой
в результат. Единственными исключениями являются переменные, которые
помечены как безопасные, чтобы тем самым избежать экранирования. Такое
поведение не дает Django выводить потенциально опасный исходный код
HTML и позволяет создавать исключения, дабы возвращать безопасный исходный код HTML.
Отредактируйте файл 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='{% url "post_list" %}'>List of posts</a> <h2> {{ post.title }} </h2> <div> {{ post.body|markdown }} </div> </body> </html>
Отредактируйте файл 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="{{ post.get_absolute_url }}">{{ post.title }}</a> </h2> <div> {{ post.body|markdown|truncatewords_html:30 }} </div> {% endfor %} </body> </html>
Проверка
Создайте суперпользователя:
python manage.py createsuperuser
Выполните все инструкции, и запустите сервер разработки:
python manage.py runserver
Пройдите по адресу 127.0.0.1:8000/admin, войдите, используя ранее введённые данные. Через админ панель добавьте несколько постов (используя синтаксис Markdown). Некоторые тексты есть ниже:
**Модель** — это единственный и точный источник информации о ваших данных. Он содержит основные поля и поведение данных, которые вы храните. Обычно каждая модель сопоставляется с одной таблицей базы данных. ### Основы - - - - Каждая модель представляет собой класс 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** (представление) – взаимодействует с базой данных через модель и передает данные в шаблон для их прорисовки и просмотра. - - -
Перейдите по адресу 127.0.0.1:8000. Вы должны увидеть список постов. Нажмите на одну из ссылок, вы увидите всё содержимое страницы.
Итог
Мы реализовали один из вариантов использования синтаксиса Markdown в Django. Целью статьи не была реализация идеального блога, а лишь простейшая реализация такой задачи. В дальнейшем можно встроить на сайт редактор для удобного написания страниц с использованием Markdown. Но это уже совсем другая история), в дальнейшем рассмотрим.
P.S. это моя первая статья. Всем пока, Control + D!