Архитектура MTV, установка, структура проекта, settings, wsgi/asgi
Django — это высокоуровневый Python веб-фреймворк, который следует философии "batteries included" (всё включено). Он предоставляет все необходимые инструменты для быстрой разработки безопасных и масштабируемых веб-приложений.
💡 Правило: Django следует принципу DRY (Don't Repeat Yourself) — не повторяйся. Каждая бизнес-логика должна иметь одно, однозначное представление в коде.
Django использует паттерн MTV (Model-Template-View), который является вариацией классического MVC (Model-View-Controller):
┌─────────────────────────────────────────────────────────────┐
│ Client Request │
└────────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ URL Dispatcher (urls.py) — маршрутизация запросов │
└────────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ View (views.py) — бизнес-логика, обработка запроса │
│ • Получает данные через Model │
│ • Выбирает Template для отображения │
│ • Возвращает HttpResponse │
└────────────────────────────┬────────────────────────────────┘
│
┌──────────────┴──────────────┐
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ Model (models.py) │ │ Template (.html) │
│ • ORM для БД │ │ • HTML + DTL │
│ • Валидация данных │ │ • Наследование │
│ • Бизнес-правила │ │ • Теги и фильтры │
└──────────────────────┘ └──────────────────────┘
| MVC | MTV | Ответственность |
|---|---|---|
| Model | Model | Данные, бизнес-логика, ORM |
| View | Template | Представление, HTML |
| Controller | View | Обработка запроса, выбор данных |
⚠️ Важно: Django View — это не View из MVC. Django View играет роль Controller.
# Установка Django
pip install django
# Создание проекта
django-admin startproject myproject
# Структура проекта
myproject/
├── manage.py # Утилита командной строки
└── myproject/
├── __init__.py # Пустой файл, делает директорию Python-пакетом
├── settings.py # Настройки проекта
├── urls.py # URL-конфигурация (root URLconf)
├── wsgi.py # WSGI-конфигурация для deployment
└── asgi.py # ASGI-конфигурация для async поддержки# Внутри директории проекта
python manage.py startapp blog
# Структура приложения
blog/
├── __init__.py
├── admin.py # Конфигурация Django Admin
├── apps.py # Конфигурация приложения
├── models.py # Модели данных (ORM)
├── tests.py # Тесты
├── views.py # Представления (обработка запросов)
├── migrations/ # Миграции базы данных
│ └── __init__.py
└── templates/ # Шаблоны (опционально, можно в корне проекта)
└── blog/
└── post_list.htmlДобавьте приложение в settings.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Ваши приложения
'blog', # Простое подключение
# Или для namespace:
# 'blog.apps.BlogConfig',
]# Базовая конфигурация
DEBUG = True # Режим отладки (не включать в production!)
ALLOWED_HOSTS = ['localhost', '127.0.0.1'] # Разрешённые хосты
# База данных
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myproject',
'USER': 'postgres',
'PASSWORD': 'secret',
'HOST': 'localhost',
'PORT': '5432',
}
}
# Middleware (порядок важен!)
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', # Должен быть первым
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# URL-конфигурация
ROOT_URLCONF = 'myproject.urls'
# Шаблоны
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'], # Глобальные шаблоны
'APP_DIRS': True, # Искать templates в приложениях
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# Статические файлы
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles' # Для collectstatic
# Медиа-файлы (загружаемые пользователями)
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
# Интернационализация
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Безопасность (в production!)
SECRET_KEY = 'django-insecure-...' # Хранить в переменной окружения!
SESSION_COOKIE_SECURE = True # HTTPS только
CSRF_COOKIE_SECURE = TrueДля production рекомендуется разделять настройки:
myproject/
├── settings/
│ ├── __init__.py
│ ├── base.py # Общие настройки
│ ├── dev.py # Development (DEBUG=True, консольный email)
│ ├── prod.py # Production (DEBUG=False, Sentry, Redis)
│ └── test.py # Тесты (in-memory БД)
# settings/base.py
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-key')
DEBUG = False
# settings/dev.py
from .base import *
DEBUG = True
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# settings/prod.py
from .base import *
DEBUG = False
ALLOWED_HOSTS = ['example.com']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME'),
# ...
}
}
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': os.environ.get('REDIS_URL'),
}
}Синхронный стандарт для Python-веб-приложений:
# myproject/wsgi.py
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_wsgi_application()Использование:
# Запуск через Gunicorn
gunicorn myproject.wsgi:application --workers 4 --bind 0.0.0.0:8000
# Запуск через uWSGI
uwsgi --http :8000 --module myproject.wsgi:applicationАсинхронный стандарт, поддерживающий:
async def)# myproject/asgi.py
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = get_asgi_application()Использование:
# Запуск через Uvicorn
uvicorn myproject.asgi:application --host 0.0.0.0 --port 8000
# Запуск через Daphne (для Django Channels)
daphne myproject.asgi:applicationmanage.py — утилита командной строки для взаимодействия с Django:
# Запуск сервера разработки
python manage.py runserver
python manage.py runserver 8080 # Другой порт
# Работа с базой данных
python manage.py makemigrations # Создание миграций
python manage.py migrate # Применение миграций
python manage.py showmigrations # Показать статус миграций
# Администрирование
python manage.py createsuperuser # Создать админа
python manage.py shell # Django shell
python manage.py dbshell # Shell базы данных
# Тестирование
python manage.py test # Запуск тестов
python manage.py test blog.tests # Тесты конкретного приложения
# Статические файлы
python manage.py collectstatic # Сборка статики для production
# Прочее
python manage.py check # Проверка конфигурации
python manage.py startapp app # Создать приложение
python manage.py startproject prj # Создать проектСоздадим базовую структуру для блога:
# 1. Создание проекта
django-admin startproject blog_project
cd blog_project
# 2. Создание приложения
python manage.py startapp posts
# 3. Создание модели
# posts/models.py
from django.db import models
from django.utils.text import slugify
class Post(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True, blank=True)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_published = models.BooleanField(default=False)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
def __str__(self):
return self.title
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['-created_at']),
models.Index(fields=['is_published', '-created_at']),
]# posts/views.py
from django.shortcuts import render, get_object_or_404
from .models import Post
def post_list(request):
posts = Post.objects.filter(is_published=True)
return render(request, 'posts/post_list.html', {'posts': posts})
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug, is_published=True)
return render(request, 'posts/post_detail.html', {'post': post})# posts/urls.py
from django.urls import path
from . import views
app_name = 'posts'
urlpatterns = [
path('', views.post_list, name='list'),
path('<slug:slug>/', views.post_detail, name='detail'),
]# blog_project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('posts/', include('posts.urls', namespace='posts')),
]# settings.py (фрагмент)
INSTALLED_APPS = [
# ...
'posts',
]# Применение миграций
python manage.py makemigrations
python manage.py migrate
# Создание суперпользователя
python manage.py createsuperuser
# Запуск сервера
python manage.py runserversettings.py и ключевые параметрыmanage.py для основных операцийAUTH_USER_MODELВопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.