Разработка веб-приложения на Django: полный цикл с практическими примерами
Базовое создание приложения на Django (MVT)
Наиболее эффективное решение: использование стандартного подхода MVT (Model-View-Template)
Django предоставляет встроенную архитектуру, которая делит приложение на модели (работа с базой данных), представления (логика обработки запроса) и шаблоны (отображение). Этот подход подходит для большинства типовых проектов благодаря минимальной настройке и высокой скорости разработки.
- Установка Django:
pip install djangoHtml css js python (интеграция python с html, css, javascript)
- Создание проекта:
django-admin startproject mysiteсоздание сайтов python django (создание веб-сайтов на django с использованием python)
– появится папка с файлами settings.py, urls.py и др. - Создание приложения:
python manage.py startapp myappPython web django (web-фреймворк django)
– внутри проекта появляется папка myapp с файлами models.py, views.py, admin.py и др. - Определение модели в models.py:
from django.db import models class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() pub_date = models.DateTimeField(auto_now_add=True) def __str__(self): return self.titlePython web flask (web-фреймворк flask)
- Регистрация модели в админке (admin.py):
from django.contrib import admin from .models import Article @admin.register(Article) class ArticleAdmin(admin.ModelAdmin): list_display = ('title', 'pub_date')Python web server (web-сервер на python)
- Выполнение миграций:
python manage.py makemigrations python manage.py migratePython 3 веб приложение (веб-приложение на python 3)
- Создание представления в views.py (функциональное представление):
from django.shortcuts import render from .models import Article def article_list(request): articles = Article.objects.all() return render(request, 'myapp/article_list.html', {'articles': articles})Python веб сервисы (веб-сервисы на python)
- Настройка маршрута в urls.py приложения:
from django.urls import path from . import views urlpatterns = [ path('', views.article_list, name='article_list'), ]примеры python веб (примеры веб-разработки на python)
- Подключение маршрутов приложения в корневом urls.py:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('articles/', include('myapp.urls')), ]создание сайта на python (создание сайта на python)
- Создание шаблона myapp/templates/myapp/article_list.html:
Статьи Список статей
{% for article in articles %}{{ article.title }}
{{ article.content|truncatewords:30 }}
{% empty %}Нет статей.
{% endfor %}Django python создание приложения (создание веб-приложения на django)
- Запуск сервера разработки:
python manage.py runserverбиблиотека django python (библиотека django для веб-разработки на python)
– приложение доступно по адресу http://127.0.0.1:8000/articles/.
Цели и случаи использования:
- Быстрая разработка прототипов и MVP.
- Проекты с классической клиент-серверной архитектурой, где весь вывод формируется на стороне сервера.
- Сайты с админ-панелью для управления контентом.
Как создать веб-приложение с использованием Class-Based Views (CBV) вместо функций?
Class-Based Views упрощают реализацию повторяющихся паттернов (список, детальная страница, создание, обновление) и предоставляют готовые классы-миксины. Пример для списка статей:
from django.views.generic import ListView
from .models import Article
class ArticleListView(ListView):
model = Article
template_name = 'myapp/article_list.html'
context_object_name = 'articles'Python django практика (практика django на python)
В urls.py подключаем:
path('', views.ArticleListView.as_view(), name='article_list')Python index html (работа с index.html в python)
Цель: сокращение объёма кода для стандартных операций, удобство наследования.
Как организовать REST API на Django с помощью Django REST Framework?
Для создания JSON API добавляем DRF. Установка:
pip install djangorestframework. Добавляем 'rest_framework' в INSTALLED_APPS. Создаём сериализаторы:
# myapp/serializers.py
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'
Представление (ViewSet):
from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
Маршруты через DefaultRouter:
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
urlpatterns = router.urls
Теперь API доступен по /articles/ (GET, POST, PUT, DELETE, etc).
Цель: обеспечить взаимодействие с мобильными приложениями, SPA, внешними интеграциями.
Как обрабатывать длительные задачи асинхронно с Celery и Redis?
Для задач типа отправки писем или генерации отчётов используем Celery. Установка:
pip install celery[redis]. Создаём файл celery.py в проекте:
# mysite/celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
app = Celery('mysite')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
В __init__.py импортируем:
from .celery import app as celery_app.
Определяем задачу в myapp/tasks.py:
from celery import shared_task
from django.core.mail import send_mail
@shared_task
def send_article_notification(article_id):
# логика отправки
print(f'Notification sent for article {article_id}')
Запуск Celery worker:
celery -A mysite worker --loglevel=info.
В представлении вызываем задачу отложенно:
from .tasks import send_article_notification
# при создании статьи
send_article_notification.delay(article.id)
Цель: повысить отзывчивость веб-сервера, обрабатывая тяжёлые операции в фоне.
Как изолировать среду разработки с помощью Docker и Docker Compose?
Создаём Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "mysite.wsgi:application", "--bind", "0.0.0.0:8000"]
Файл docker-compose.yml:
version: '3'
services:
web:
build: .
ports:
- "8000:8000"
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_DB: mydb
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
Запуск:
docker-compose up. Django настраивается для PostgreSQL через переменные окружения.
Цель: одинаковые окружения на всех машинах, упрощение деплоя и тестирования.
Типичные проблемы и их решения
Как избежать ошибки "RuntimeError: Model class apps.myapp.models.Article doesn't declare an explicit app_label"?
Причина: модель определена вне приложения или неправильно подключено приложение в INSTALLED_APPS. Решение: убедиться, что приложение добавлено в settings.py как 'myapp'.
Как исправить ошибку "django.db.utils.IntegrityError: NOT NULL constraint failed" при миграциях?
Причина: добавление поля с null=False на существующую таблицу без значения по умолчанию. Решение: указать default или null=True, затем выполнить миграции.
Почему статические файлы (CSS, JS) не отображаются в production?
Причина: Django по умолчанию не обслуживает статику вне режима DEBUG. Решение: настроить STATIC_ROOT и запустить collectstatic, а также настроить веб-сервер (Nginx) на раздачу статики.
Как решить проблему "DisallowedHost at /" при развёртывании?
Причина: HOST заголовок не совпадает с ALLOWED_HOSTS. Решение: добавить домен или IP в список ALLOWED_HOSTS в settings.py.
Расширенные примеры кода и команд
1. Использование Generic Class-Based Views с дополнительными контекстными данными
Пример добавления дополнительных данных в шаблон через переопределение get_context_data:
from django.views.generic import ListView
from .models import Article, Category
class ArticleListView(ListView):
model = Article
template_name = 'myapp/article_list.html'
context_object_name = 'articles'
paginate_by = 10
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['categories'] = Category.objects.all()
context['current_category'] = self.request.GET.get('category', 'all')
return context
В шаблоне можно использовать {{ categories }} и {{ current_category }}. Результат – список статей с пагинацией и боковой панелью категорий.
2. Форма с валидацией и сохранением данных (ModelForm)
# myapp/forms.py
from django import forms
from .models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'content']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}),
}
Представление для создания статьи:
from django.shortcuts import render, redirect
from .forms import ArticleForm
def create_article(request):
if request.method == 'POST':
form = ArticleForm(request.POST)
if form.is_valid():
article = form.save()
return redirect('article_detail', pk=article.pk)
else:
form = ArticleForm()
return render(request, 'myapp/article_form.html', {'form': form})
Шаблон article_form.html:
Результат: после отправки формы создаётся запись в базе и происходит перенаправление.
3. Кастомная команда управления (management command)
Создаём задачу импорта статей из CSV. Структура: myapp/management/commands/import_articles.py:
import csv
from django.core.management.base import BaseCommand
from myapp.models import Article
class Command(BaseCommand):
help = 'Импортирует статьи из CSV файла'
def add_arguments(self, parser):
parser.add_argument('file_path', type=str)
def handle(self, *args, **options):
file_path = options['file_path']
with open(file_path, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
Article.objects.create(
title=row['title'],
content=row['content']
)
self.stdout.write(self.style.SUCCESS('Импорт завершён'))
Запуск команды:
python manage.py import_articles data/articles.csv
Результат: в консоли увидим сообщение об успешном импорте.
4. Асинхронная отправка письма с вложением через Celery
# myapp/tasks.py
from celery import shared_task
from django.core.mail import EmailMessage
from django.contrib.auth.models import User
@shared_task
def send_file_mail(user_id, file_path):
user = User.objects.get(id=user_id)
email = EmailMessage(
subject='Ваш отчёт',
body='Во вложении находится сгенерированный документ.',
from_email='noreply@example.com',
to=[user.email],
)
with open(file_path, 'rb') as f:
email.attach('report.pdf', f.read(), 'application/pdf')
email.send()
return f'Email sent to {user.email}'
Вызов из представления:
send_file_mail.delay(request.user.id, '/tmp/report.pdf')
Worker выведет лог об отправке.
5. Работа с загрузкой файлов (изображения)
Модель:
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
image = models.ImageField(upload_to='articles/', blank=True, null=True)
Настройка в settings.py:
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
В корневом urls.py для разработки:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Форма с файлом:
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ['title', 'content', 'image']
В шаблоне enctype="multipart/form-data":
Результат: загруженные изображения будут доступны через /media/articles/имя_файла.
6. Кастомизация панели администратора с использованием ModelAdmin
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'pub_date', 'is_published')
list_filter = ('pub_date', 'is_published')
search_fields = ('title', 'content')
date_hierarchy = 'pub_date'
ordering = ('-pub_date',)
actions = ['make_published']
def make_published(self, request, queryset):
queryset.update(is_published=True)
make_published.short_description = 'Опубликовать выбранные статьи'
Результат: в админке появится кнопка массовой публикации и удобные фильтры.