Django База [2023]: Автоматическое формирование slug, обработка кириллицы в Django #9
В данном уроке мы научимся работать со slug в Django 4.1, а именно форматировать их автоматически, а также обрабатывать кириллицу в slugField.
Если вы хотите выразить благодарность автору сайта, статей и курса по Django, вы можете сделать это по ссылке ниже:
Что такое Slug?
slug - это тип поля в Django для создания человеко-понятных URL на латинице. С помощью slug мы можем автоматически конвертировать нашу запись, например с заголовком: Добро пожаловать на сайт. В url типа: dobro-pozhalovat-na-sajt.
Есть 2 способа конвертации заголовка в slug, но один работает лишь внутри административной модели, а другой работает всегда. Верно будет использовать оба варианта.
Настройка формирования slug в административной панели
Перейдем в файл admin.py в нашем приложении блог, и изменим код с этого:
from django.contrib import admin
from mptt.admin import DraggableMPTTAdmin
from .models import Category, Article
@admin.register(Category)
class CategoryAdmin(DraggableMPTTAdmin):
"""
Админ-панель модели категорий
"""
list_display = ('tree_actions', 'indented_title', 'id', 'title', 'slug')
list_display_links = ('title', 'slug')
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Article)
На следующий:
from django.contrib import admin
from mptt.admin import DraggableMPTTAdmin
from .models import Category, Article
@admin.register(Category)
class CategoryAdmin(DraggableMPTTAdmin):
"""
Админ-панель модели категорий
"""
list_display = ('tree_actions', 'indented_title', 'id', 'title', 'slug')
list_display_links = ('title', 'slug')
prepopulated_fields = {'slug': ('title',)}
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('title',)}
Пояснение:
- Мы добавили параметр
prepopulated_fields
, который позволяет с помощью JS обрабатывать заголовок в реальном времени, конвертирует даже кириллицу.
Смотрим результат в админ-панели:
Отлично, все работает. Теперь перейдем ко второму способу.
Добавление функции для сохранения уникального slug, обработка кириллицы с помощью python
Для обработки кириллицы в slug, нужно модернизировать функцию slugify()
, для этого установим пакет pytils с помощью терминала: pip install pytils
Результат установки:
(venv) PS C:\Users\Razilator\Desktop\Base\backend> pip install pytils
Collecting pytils
Using cached pytils-0.4.1-py3-none-any.whl
Installing collected packages: pytils
Successfully installed pytils-0.4.1
[notice] A new release of pip available: 22.3 -> 22.3.1
[notice] To update, run: python.exe -m pip install --upgrade pip
Отлично, теперь я создам папку services в папке modules, а внутри два файла init.py и utils.py.
init.py необходим для инициализации папки как пакета Python.
В файл utils.py мы будем добавлять различные полезные функции для нашего проекта, поэтому мы ее отделим от приложения блог. Лично для меня это удобно, декомпозиция это всегда хорошо.
Теперь напишем функцию:
from uuid import uuid4
from pytils.translit import slugify
def unique_slugify(instance, slug):
"""
Генератор уникальных SLUG для моделей, в случае существования такого SLUG.
"""
model = instance.__class__
unique_slug = slugify(slug)
while model.objects.filter(slug=unique_slug).exists():
unique_slug = f'{unique_slug}-{uuid4().hex[:8]}'
return unique_slug
Добавление services в INSTALLED_APPS
Далее необходимо добавить наш созданный модуль services в приложения конфигурации Django.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'modules.blog.apps.BlogConfig',
'modules.services',
]
Применение уникальных авто-слагов в модели Django
Отлично, функцию написали и модуль добавили в установленные приложения, теперь функцию unique_slugify()
необходимо применить в модели Article (Статей).
Для этого переходим в blog/models.py и добавим работу функции при сохранении экземпляра модели.
from django.db import models
from django.core.validators import FileExtensionValidator
from django.contrib.auth import get_user_model
from django.urls import reverse
from mptt.models import MPTTModel, TreeForeignKey
from modules.services.utils import unique_slugify
class Article(models.Model):
"""
Модель постов для сайта
"""
STATUS_OPTIONS = (
('published', 'Опубликовано'),
('draft', 'Черновик')
)
title = models.CharField(verbose_name='Заголовок', max_length=255)
slug = models.CharField(verbose_name='Альт.название', max_length=255, blank=True, unique=True)
# Другие поля...
# Другие функции...
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('articles_detail', kwargs={'slug': self.slug})
def save(self, *args, **kwargs):
"""
Сохранение полей модели при их отсутствии заполнения
"""
if not self.slug:
self.slug = unique_slugify(self, self.title)
super().save(*args, **kwargs)
Пояснение:
Мы импортировали функцию по генерации slug, а также добавили метод save для обработки полей экземпляра. В условии, если нет slug, то мы генерируем slug из заголовка, а если такой slug существует, то мы добавляем символы uuid4.
Давайте протестируем нашу функцию:
Отлично, у нас все получилось!