Начало работы, создание модели статей
Новый проект
В последних двух модулях мы построим второй большой проект — сайт статей с древовидными категориями, профилями, добавлением статей пользователями, древовидными комментариями на AJAX, тегами, лайками, RSS и кешированием. Многое будет знакомо по блогу, но мы пойдём дальше и сделаем акцент на представлениях-классах и миксинах.
Создание
mkdir articles && cd articles
python -m venv venv
source venv/bin/activate
pip install django pillow
django-admin startproject backend .
mkdir modules
python manage.py startapp blog modules/blog
Приложения будем хранить в папке modules/ — так проще ориентироваться, когда их много. В modules/blog/apps.py поправьте имя:
class BlogConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "modules.blog"
verbose_name = "Статьи"
Создайте пустой modules/__init__.py.
Настройки
backend/settings.py:
INSTALLED_APPS = [
...
"modules.blog.apps.BlogConfig",
]
TEMPLATES[0]["DIRS"] = [BASE_DIR / "templates"]
LANGUAGE_CODE = "ru"
TIME_ZONE = "Europe/Moscow"
STATIC_URL = "static/"
STATICFILES_DIRS = [BASE_DIR / "templates" / "src"]
STATIC_ROOT = BASE_DIR / "static"
MEDIA_URL = "media/"
MEDIA_ROOT = BASE_DIR / "media"
backend/urls.py:
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("modules.blog.urls")),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Модель статьи
modules/blog/models.py:
from django.contrib.auth import get_user_model
from django.db import models
from django.urls import reverse
User = get_user_model()
class Article(models.Model):
class ArticleManager(models.Manager):
def all(self):
return self.get_queryset().filter(status="published")
STATUS_OPTIONS = (
("published", "Опубликовано"),
("draft", "Черновик"),
)
title = models.CharField(verbose_name="Заголовок", max_length=255)
slug = models.SlugField(verbose_name="URL", max_length=255, blank=True)
short_description = models.TextField(verbose_name="Краткое описание", max_length=500)
full_description = models.TextField(verbose_name="Полное описание")
thumbnail = models.ImageField(
verbose_name="Превью поста",
blank=True,
upload_to="images/thumbnails/%Y/%m/%d/",
)
status = models.CharField(choices=STATUS_OPTIONS, default="published", verbose_name="Статус", max_length=10)
time_create = models.DateTimeField(auto_now_add=True, verbose_name="Время добавления")
time_update = models.DateTimeField(auto_now=True, verbose_name="Время обновления")
author = models.ForeignKey(
to=User,
verbose_name="Автор",
on_delete=models.SET_DEFAULT,
related_name="author_posts",
default=1,
)
updater = models.ForeignKey(
to=User,
verbose_name="Обновил",
on_delete=models.SET_NULL,
null=True,
related_name="updater_posts",
blank=True,
)
fixed = models.BooleanField(verbose_name="Закреплено", default=False)
objects = models.Manager()
custom = ArticleManager()
class Meta:
db_table = "app_articles"
ordering = ["-fixed", "-time_create"]
indexes = [models.Index(fields=["-fixed", "-time_create", "status"])]
verbose_name = "Статья"
verbose_name_plural = "Статьи"
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("articles_detail", kwargs={"slug": self.slug})
Что здесь нового по сравнению с блогом:
get_user_model()— получаем модель пользователя, какой бы она ни была (стандартной или своей).on_delete=models.SET_DEFAULT, default=1— при удалении автора статьи «переходят» администратору с id=1, а не удаляются.updater— кто последним редактировал статью (SET_NULL, поле может быть пустым).fixed— закреплённые статьи показываются первыми (сортировка-fixed).- Менеджер объявлен прямо внутри модели; метод
all()переопределён, чтобыArticle.custom.all()возвращал только опубликованные. db_table = "app_articles"— своё имя таблицы.
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
Админка
from django.contrib import admin
from .models import Article
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = ["title", "author", "status", "fixed", "time_create"]
list_filter = ["status", "fixed"]
search_fields = ["title", "short_description"]
prepopulated_fields = {"slug": ("title",)}
Итог
- Новый проект
backendс приложениями в папкеmodules/. Article: заголовок, слаг, описания, превью, статус, даты, автор и редактор, закрепление.get_user_model()для ссылки на пользователя,SET_DEFAULTдля сохранения статей при удалении автора.- Собственный менеджер для опубликованных статей.
Практика решено 0 из 5
Расставьте шаги старта нового проекта «Сайт статей».
-
Описать модель
Articleи выполнить миграции -
python manage.py startapp blog(в папкеmodules) -
django-admin startproject backend . - Подключить приложение и настроить язык, часовой пояс, статику и медиа
- Создать venv и установить Django
- Зарегистрировать модель в админке
Опишите модель Article с полями: title (CharField 255), slug (SlugField 255, blank=True),
short_description (TextField 500), full_description (TextField), thumbnail (ImageField, upload_to="images/thumbnails/", blank=True),
status (CharField 10 с вариантами STATUS_OPTIONS, по умолчанию "published").
class Article(models.Model):
STATUS_OPTIONS = (
("published", "Опубликовано"),
("draft", "Черновик"),
)
title = models.CharField(verbose_name="Заголовок", max_length=255)
slug = models.SlugField(verbose_name="URL", max_length=255, blank=True)
short_description = models.TextField(verbose_name="Краткое описание", max_length=500)
full_description = models.TextField(verbose_name="Полное описание")
thumbnail = models.ImageField(verbose_name="Превью", upload_to="images/thumbnails/", blank=True)
status = models.CharField(choices=STATUS_OPTIONS, default="published", verbose_name="Статус", max_length=10)
Добавьте в модель Article поля дат: time_create (заполняется при создании) и time_update (при каждом сохранении),
а также автора: author — ForeignKey на User с on_delete=models.SET_DEFAULT, default=1 и related_name="author_posts".
class Article(models.Model):
title = models.CharField(max_length=255)
time_create = models.DateTimeField(auto_now_add=True, verbose_name="Время добавления")
time_update = models.DateTimeField(auto_now=True, verbose_name="Время обновления")
author = models.ForeignKey(
to=User,
verbose_name="Автор",
on_delete=models.SET_DEFAULT,
related_name="author_posts",
default=1,
)
Что произойдёт со статьями при удалении автора, если on_delete=models.SET_DEFAULT, default=1?
Какие настройки нужно добавить для работы с загружаемыми картинками (превью статей)?
Войдите, чтобы отмечать пройденные уроки.