Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Архитектурный паттерн MTV (Model-Template-View)
МTV — это архитектурный паттерн, используемый в Django. Это вариант паттерна MVC, адаптированный специально для Django. Каждая буква отвечает за отдельный компонент системы.
M — Model (Модель)
Отвечает за:
- Представление данных и бизнес-логики
- Взаимодействие с базой данных
- Валидацию данных
- Бизнес-правила
Model — это класс, который наследуется от django.db.models.Model:
from django.db import models
class Article(models.Model):
"""Модель статьи"""
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
is_published = models.BooleanField(default=False)
class Meta:
ordering = ["-created_at"]
indexes = [
models.Index(fields=["is_published", "-created_at"]),
]
def __str__(self):
return self.title
def get_absolute_url(self):
"""URL статьи"""
return f"/articles/{self.id}/"
def is_recent(self):
"""Бизнес-логика: проверить, свежая ли статья"""
from django.utils import timezone
from datetime import timedelta
return self.created_at > timezone.now() - timedelta(days=7)
Ответственность Model:
- Определение структуры данных (поля, связи)
- ORM операции (save, delete, filter, get)
- Валидация на уровне БД (constraints, validators)
- Методы бизнес-логики
T — Template (Шаблон)
Отвечает за:
- Отображение данных пользователю
- HTML разметка
- Логика представления (conditionals, loops)
- Интеграция CSS и JavaScript
Template — это HTML файл с Django шаблонизатором:
<!-- templates/article_detail.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ article.title }}</title>
<link rel="stylesheet" href="{% static "style.css" %}">
</head>
<body>
<h1>{{ article.title }}</h1>
<p>Автор: <strong>{{ article.author.get_full_name }}</strong></p>
<p>Дата: {{ article.created_at|date:"Y-m-d" }}</p>
{% if article.is_recent %}
<span class="badge">Свежая статья!</span>
{% endif %}
<div class="content">
{{ article.content|safe }}
</div>
{% if user.is_authenticated %}
<a href="{% url "edit_article" article.id %}">Редактировать</a>
{% else %}
<p>Пожалуйста, <a href="{% url "login" %}">авторизуйтесь</a> для редактирования</p>
{% endif %}
<h3>Комментарии</h3>
{% for comment in article.comments.all %}
<div class="comment">
<p>{{ comment.author }}: {{ comment.text }}</p>
</div>
{% empty %}
<p>Нет комментариев</p>
{% endfor %}
</body>
</html>
Ответственность Template:
- HTML структура
- Отображение переменных из context
- Условная логика (if/else, for)
- Filters и template tags
- CSS классы и статические файлы
V — View (Представление)
Отвечает за:
- Обработка HTTP запросов
- Получение данных из Model
- Подготовка контекста для Template
- Бизнес-логика контроллера (не основной бизнес, а логика запроса)
- Возврат HTTP ответа
Function-based View (FBV):
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from .models import Article
def article_list(request):
"""Список всех статей"""
# Model: получение данных
articles = Article.objects.filter(is_published=True).order_by("-created_at")
# Фильтрация по поиску
search = request.GET.get("search")
if search:
articles = articles.filter(title__icontains=search)
# Пагинация
paginate_by = 10
page = request.GET.get("page", 1)
# ... логика пагинации
# Подготовка context для Template
context = {
"articles": articles,
"search": search,
}
# Template: рендеринг с данными
return render(request, "article_list.html", context)
def article_detail(request, article_id):
"""Детальный вид статьи"""
# Model
article = get_object_or_404(Article, id=article_id, is_published=True)
# Обновление счётчика просмотров
article.views += 1
article.save(update_fields=["views"])
# Context
context = {"article": article}
# Template
return render(request, "article_detail.html", context)
Class-based View (CBV):
from django.views import View
from django.views.generic import ListView, DetailView
class ArticleListView(ListView):
"""Список статей с готовой логикой"""
model = Article
template_name = "article_list.html"
context_object_name = "articles"
paginate_by = 10
def get_queryset(self):
"""Model: фильтрация данных"""
queryset = Article.objects.filter(is_published=True)
search = self.request.GET.get("search")
if search:
queryset = queryset.filter(title__icontains=search)
return queryset
def get_context_data(self, **kwargs):
"""Template: дополнительный контекст"""
context = super().get_context_data(**kwargs)
context["search"] = self.request.GET.get("search", "")
return context
class ArticleDetailView(DetailView):
"""Детальный вид статьи"""
model = Article
template_name = "article_detail.html"
context_object_name = "article"
def get_queryset(self):
return Article.objects.filter(is_published=True)
def get(self, request, *args, **kwargs):
"""Обновление просмотров перед рендерингом"""
response = super().get(request, *args, **kwargs)
self.object.views += 1
self.object.save(update_fields=["views"])
return response
Ответственность View:
- Обработка HTTP запроса
- Вызовы Model для получения данных
- Бизнес-логика для подготовки данных
- Подготовка контекста
- Возврат HTTP ответа
Архитектурная диаграмма MTV
HTTP Request
↓
[View (обработчик)]
↓
[Model (данные)] ← Запрос к БД
↓
[Template (HTML)] ← Render с context
↓
HTTP Response (HTML)
Сравнение MTV с MVC
| MTV (Django) | MVC | Роль |
|---|---|---|
| Model | Model | Данные и бизнес-логика |
| Template | View | Представление данных |
| View | Controller | Обработка запросов и логика |
Отличие: в MVC вью отвечает за представление, а в Django вью отвечает за логику обработки (как контроллер).
Практический пример полного цикла
# models.py
class Comment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="comments")
author = models.CharField(max_length=100)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
# views.py
def article_detail(request, article_id):
# View: получение статьи из Model
article = get_object_or_404(Article, id=article_id)
# View: получение комментариев из Model
comments = article.comments.all().order_by("-created_at")
# View: обработка POST запроса
if request.method == "POST":
author = request.POST.get("author")
text = request.POST.get("text")
# Model: создание комментария
Comment.objects.create(article=article, author=author, text=text)
# Redirect или re-render
# View: подготовка контекста
context = {"article": article, "comments": comments}
# Template: рендеринг
return render(request, "article_detail.html", context)
# template: article_detail.html
# Цикл по комментариям (Template логика)
{% for comment in comments %}
<div>{{ comment.author }}: {{ comment.text }}</div>
{% endfor %}
Выводы
- Model = Данные и бизнес-логика
- Template = HTML и представление
- View = Логика обработки запросов
- MTV помогает разделить ответственность
- Каждый компонент можно тестировать отдельно