Первый урок по Django: установка фреймворка и создание проекта

Первый урок по Django: установка фреймворка и создание проекта

Django — это мощный веб-фреймворк, написанный на языке Python. Он предоставляет разработчикам инструменты для быстрого создания безопасных и масштабируемых веб-приложений. В этой статье читатель познакомится с процессом установки Django и создания первого проекта.

Что такое Django и почему его стоит изучать?

Django — это высокоуровневый веб-фреймворк, который поощряет быструю разработку и чистый, прагматичный дизайн. Разработанный опытными программистами, Django заботится о многих аспектах веб-разработки, позволяя сосредоточиться на написании приложения без необходимости «изобретать велосипед».

  • Быстрая разработка: Django предоставляет множество готовых компонентов для ускорения процесса разработки.
  • Безопасность: Фреймворк включает в себя множество встроенных средств защиты от распространенных уязвимостей.
  • Масштабируемость: Django способен обрабатывать трафик высокой нагрузки и может быть легко масштабирован.
  • Универсальность: Подходит для разработки различных типов веб-приложений — от блогов до высоконагруженных веб-сайтов.

Подготовка к установке Django

Прежде чем приступить к установке Django, необходимо убедиться, что на компьютере установлен Python. Django совместим с Python 3.6 и выше.

Проверка наличия Python

Для проверки наличия Python и его версии следует открыть терминал (командную строку) и ввести следующую команду:

python --version

Если Python установлен, будет выведена его версия. Если команда не распознана, необходимо установить Python с официального сайта python.org.

Создание виртуального окружения

Рекомендуется использовать виртуальное окружение для изоляции проекта и его зависимостей. Для создания виртуального окружения выполняются следующие шаги:

  1. Открыть терминал и перейти в директорию, где будет располагаться проект.
  2. Выполнить команду для создания виртуального окружения:
    python -m venv myenv
  3. Активировать виртуальное окружение:
    • На Windows: myenv\Scripts\activate
    • На macOS и Linux: source myenv/bin/activate

Установка Django

После активации виртуального окружения можно приступить к установке Django. Процесс установки прост и выполняется с помощью pip — менеджера пакетов Python.

Установка последней версии Django

Для установки последней стабильной версии Django необходимо выполнить следующую команду:

pip install django

После завершения установки можно проверить версию установленного Django:

python -m django --version

Установка конкретной версии Django

Если требуется установить определенную версию Django, можно указать ее номер при установке:

pip install django==3.2.4

Это установит Django версии 3.2.4. Важно помнить, что разные версии могут иметь различия в функциональности и синтаксисе.

Создание первого проекта Django

После успешной установки Django можно приступить к созданию первого проекта. Django предоставляет удобную утилиту командной строки для автоматического создания базовой структуры проекта.

Использование django-admin для создания проекта

Для создания нового проекта выполняется следующая команда:

django-admin startproject myproject

Эта команда создаст новую директорию с именем «myproject», содержащую базовую структуру проекта Django.

Структура проекта Django

После выполнения команды будет создана следующая структура файлов и директорий:

myproject/ manage.py myproject/ __init__.py settings.py urls.py asgi.py wsgi.py

Каждый файл имеет свое назначение:

  • manage.py: Утилита командной строки для взаимодействия с проектом.
  • __init__.py: Пустой файл, указывающий Python, что эта директория является пакетом.
  • settings.py: Файл настроек проекта.
  • urls.py: Файл конфигурации URL-адресов проекта.
  • asgi.py: Точка входа для ASGI-совместимых веб-серверов.
  • wsgi.py: Точка входа для WSGI-совместимых веб-серверов.

Настройка базы данных

Django по умолчанию использует SQLite в качестве базы данных. Это упрощает начало работы, так как не требует дополнительной настройки. Однако для продакшн-проектов рекомендуется использовать более мощные СУБД, такие как PostgreSQL или MySQL.

Настройка базы данных в settings.py

Файл settings.py содержит настройки базы данных. По умолчанию он выглядит примерно так:

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }

Эта конфигурация указывает Django использовать SQLite и создать файл базы данных db.sqlite3 в корневой директории проекта.

Применение миграций

После настройки базы данных необходимо применить миграции. Миграции — это способ Django обновлять схему базы данных в соответствии с изменениями в моделях. Для применения миграций выполняются следующие команды:

python manage.py migrate

Эта команда создаст необходимые таблицы в базе данных для встроенных приложений Django, таких как система аутентификации и сессий.

Создание первого приложения

Проект Django состоит из одного или нескольких приложений. Приложение — это модульная часть проекта, выполняющая определенную функцию. Для создания нового приложения используется команда startapp.

Использование manage.py для создания приложения

Чтобы создать новое приложение, необходимо выполнить следующую команду:

python manage.py startapp myapp

Эта команда создаст новую директорию «myapp» со следующей структурой:

myapp/ __init__.py admin.py apps.py migrations/ __init__.py models.py tests.py views.py

Регистрация приложения в проекте

После создания приложения его необходимо зарегистрировать в проекте. Для этого следует открыть файл settings.py и добавить имя приложения в список INSTALLED_APPS:

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myapp', # Добавленная строка ]

Создание первого представления

Представление (view) в Django — это функция или класс, который обрабатывает HTTP-запрос и возвращает HTTP-ответ. Давайте создадим простое представление, которое будет выводить приветствие.

Написание функции представления

Откройте файл views.py в директории вашего приложения и добавьте следующий код:

from django.http import HttpResponse def hello_world(request): return HttpResponse("Привет, мир!") 

Эта функция создает простой HTTP-ответ с текстом «Привет, мир!».

Настройка URL-маршрутизации

Чтобы связать созданное представление с URL, необходимо настроить маршрутизацию. Для этого создайте файл urls.py в директории вашего приложения и добавьте следующий код:

from django.urls import path from . import views urlpatterns = [ path('hello/', views.hello_world, name='hello_world'), ] 

Затем откройте файл urls.py в директории проекта и добавьте ссылку на URL-конфигурацию приложения:

from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('myapp.urls')), ] 

Запуск сервера разработки

Django поставляется с легким веб-сервером для разработки, который позволяет быстро тестировать приложение без необходимости настройки полноценного веб-сервера.

Команда для запуска сервера

Для запуска сервера разработки выполните следующую команду:

python manage.py runserver

По умолчанию сервер запустится на локальном хосте (127.0.0.1) и порту 8000.

Проверка работы приложения

После запуска сервера откройте веб-браузер и перейдите по адресу http://127.0.0.1:8000/hello/. Вы должны увидеть сообщение «Привет, мир!».

Основы работы с шаблонами Django

Шаблоны в Django позволяют отделить представление данных от логики приложения. Это делает код более чистым и легким для поддержки.

Создание первого шаблона

Создайте директорию templates в вашем приложении, а в ней файл hello.html со следующим содержимым:

<!DOCTYPE html> <html> <head> <title>Приветствие</title> </head> <body> <h1>{{ message }}</h1> </body> </html>

Использование шаблона в представлении

Измените функцию hello_world в файле views.py, чтобы использовать шаблон:

from django.shortcuts import render def hello_world(request): context = {'message': 'Привет, мир!'} return render(request, 'hello.html', context) 

Работа с моделями данных

Модели в Django представляют структуру базы данных и позволяют работать с данными на уровне Python-объектов.

Читайте также  Влияние взлома сайта на его полную деиндексацию

Создание простой модели

Откройте файл models.py в вашем приложении и добавьте следующий код:

from django.db import models class Task(models.Model): title = models.CharField(max_length=200) description = models.TextField(blank=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title 

Создание и применение миграций

После создания модели необходимо создать и применить миграции:

python manage.py makemigrations python manage.py migrate

Работа с административной панелью Django

Django предоставляет мощную административную панель, которая позволяет управлять данными приложения без написания дополнительного кода.

Регистрация модели в админ-панели

Откройте файл admin.py в вашем приложении и добавьте следующий код:

from django.contrib import admin from .models import Task admin.site.register(Task) 

Создание суперпользователя

Для доступа к административной панели необходимо создать суперпользователя:

python manage.py createsuperuser

Следуйте инструкциям на экране, чтобы задать имя пользователя, email и пароль.

Обработка форм в Django

Формы играют важную роль в веб-приложениях, позволяя пользователям взаимодействовать с сервером.

Создание формы для модели

Создайте файл forms.py в директории вашего приложения и добавьте следующий код:

from django import forms from .models import Task class TaskForm(forms.ModelForm): class Meta: model = Task fields = ['title', 'description'] 

Использование формы в представлении

Измените файл views.py, чтобы использовать созданную форму:

from django.shortcuts import render, redirect from .forms import TaskForm from .models import Task def task_list(request): tasks = Task.objects.all() return render(request, 'task_list.html', {'tasks': tasks}) def task_create(request): if request.method == 'POST': form = TaskForm(request.POST) if form.is_valid(): form.save() return redirect('task_list') else: form = TaskForm() return render(request, 'task_form.html', {'form': form}) 

Создание шаблонов для отображения и создания задач

Теперь создадим шаблоны для отображения списка задач и формы создания новой задачи.

Шаблон списка задач

Создайте файл task_list.html в директории templates:

<!DOCTYPE html> <html> <head> <title>Список задач</title> </head> <body> <h1>Список задач</h1> <ul> {% for task in tasks %} <li>{{ task.title }} - {{ task.created_at }}</li> {% empty %} <li>Нет задач</li> {% endfor %} </ul> <a href="{% url 'task_create' %}">Создать новую задачу</a> </body> </html>

Шаблон формы создания задачи

Создайте файл task_form.html в директории templates:

<!DOCTYPE html> <html> <head> <title>Создание задачи</title> </head> <body> <h1>Создание новой задачи</h1> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">Сохранить</button> </form> <a href="{% url 'task_list' %}">Вернуться к списку задач</a> </body> </html>

Настройка URL-маршрутов для новых представлений

Обновите файл urls.py в вашем приложении, чтобы добавить новые URL-маршруты:

from django.urls import path from . import views urlpatterns = [ path('', views.task_list, name='task_list'), path('create/', views.task_create, name='task_create'), ] 

Добавление статических файлов

Статические файлы, такие как CSS и JavaScript, позволяют улучшить внешний вид и функциональность веб-приложения.

Настройка статических файлов

В файле settings.py убедитесь, что у вас есть следующие настройки:

STATIC_URL = '/static/' STATICFILES_DIRS = [ BASE_DIR / "static", ] 

Создание CSS файла

Создайте директорию static в корне вашего проекта, а в ней файл style.css:

body { font-family: Arial, sans-serif; line-height: 1.6; margin: 0; padding: 20px; } h1 { color: #333; } ul { list-style-type: none; padding: 0; } li { background: #f4f4f4; margin-bottom: 10px; padding: 10px; border-radius: 5px; } a { color: #333; text-decoration: none; } a:hover { color: #666; } form { background: #f4f4f4; padding: 20px; border-radius: 5px; } button { background: #333; color: #fff; padding: 10px 15px; border: none; border-radius: 5px; cursor: pointer; } button:hover { background: #444; } 

Подключение CSS к шаблонам

Обновите шаблоны task_list.html и task_form.html, добавив следующую строку в секцию <head>:

<link rel="stylesheet" href="{% static 'style.css' %}">

Также добавьте в начало файла:

{% load static %}

Добавление пагинации

При увеличении количества задач может потребоваться пагинация для улучшения производительности и удобства использования.

Обновление представления для поддержки пагинации

Измените функцию task_list в views.py:

from django.core.paginator import Paginator def task_list(request): tasks = Task.objects.all().order_by('-created_at') paginator = Paginator(tasks, 10) # 10 задач на страницу page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) return render(request, 'task_list.html', {'page_obj': page_obj}) 

Обновление шаблона для отображения пагинации

Измените task_list.html, чтобы использовать пагинацию:

<ul> {% for task in page_obj %} <li>{{ task.title }} - {{ task.created_at }}</li> {% empty %} <li>Нет задач</li> {% endfor %} </ul> <div class="pagination"> <span class="step-links"> {% if page_obj.has_previous %} <a href="?page=1">« первая</a> <a href="?page={{ page_obj.previous_page_number }}">предыдущая</a> {% endif %} <span class="current"> Страница {{ page_obj.number }} из {{ page_obj.paginator.num_pages }}. </span> {% if page_obj.has_next %} <a href="?page={{ page_obj.next_page_number }}">следующая</a> <a href="?page={{ page_obj.paginator.num_pages }}">последняя »</a> {% endif %} </span> </div>

Добавление функциональности поиска

Поиск поможет пользователям быстро находить нужные задачи.

Обновление представления для поддержки поиска

Измените функцию task_list в views.py:

from django.db.models import Q def task_list(request): query = request.GET.get('q') if query: tasks = Task.objects.filter(Q(title__icontains=query) | Q(description__icontains=query)) else: tasks = Task.objects.all() tasks = tasks.order_by('-created_at') paginator = Paginator(tasks, 10) page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) return render(request, 'task_list.html', {'page_obj': page_obj, 'query': query}) 

Добавление формы поиска в шаблон

Добавьте следующий код в начало task_list.html:

<form method="get" action="{% url 'task_list' %}"> <input type="text" name="q" value="{{ query|default:'' }}" placeholder="Поиск задач"> <button type="submit">Поиск</button> </form>

Добавление аутентификации пользователей

Аутентификация позволит ограничить доступ к созданию и редактированию задач только для зарегистрированных пользователей.

Создание представлений для регистрации и входа

Добавьте следующие функции в views.py:

from django.contrib.auth.forms import UserCreationForm, AuthenticationForm from django.contrib.auth import login, logout from django.contrib.auth.decorators import login_required def register(request): if request.method == 'POST': form = UserCreationForm(request.POST) if form.is_valid(): user = form.save() login(request, user) return redirect('task_list') else: form = UserCreationForm() return render(request, 'register.html', {'form': form}) def user_login(request): if request.method == 'POST': form = AuthenticationForm(data=request.POST) if form.is_valid(): user = form.get_user() login(request, user) return redirect('task_list') else: form = AuthenticationForm() return render(request, 'login.html', {'form': form}) def user_logout(request): logout(request) return redirect('task_list') @login_required def task_create(request): # Существующий код функции task_create 

Создание шаблонов для регистрации и входа

Создайте файлы register.html и login.html в директории templates:

<!-- register.html --> <h2>Регистрация</h2> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">Зарегистрироваться</button> </form> <!-- login.html --> <h2>Вход</h2> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">Войти</button> </form>

Обновление URL-маршрутов

Добавьте новые URL-маршруты в urls.py:

from django.urls import path from . import views urlpatterns = [ path('', views.task_list, name='task_list'), path('create/', views.task_create, name='task_create'), path('register/', views.register, name='register'), path('login/', views.user_login, name='login'), path('logout/', views.user_logout, name='logout'), ] 

Добавление возможности редактирования и удаления задач

Для полноценного управления задачами добавим функциональность редактирования и удаления.

Читайте также  Сравнительный анализ CSR, SSR и SSG: выбор оптимальной стратегии рендеринга

Создание представлений для редактирования и удаления

Добавьте следующие функции в views.py:

from django.shortcuts import get_object_or_404 @login_required def task_edit(request, pk): task = get_object_or_404(Task, pk=pk) if request.method == 'POST': form = TaskForm(request.POST, instance=task) if form.is_valid(): form.save() return redirect('task_list') else: form = TaskForm(instance=task) return render(request, 'task_form.html', {'form': form}) @login_required def task_delete(request, pk): task = get_object_or_404(Task, pk=pk) if request.method == 'POST': task.delete() return redirect('task_list') return render(request, 'task_confirm_delete.html', {'task': task}) 

Создание шаблона для подтверждения удаления

Создайте файл task_confirm_delete.html в директории templates:

<h2>Подтверждение удаления</h2> <p>Вы уверены, что хотите удалить задачу "{{ task.title }}"?</p> <form method="post"> {% csrf_token %} <button type="submit">Да, удалить</button> </form> <a href="{% url 'task_list' %}">Отмена</a>

Обновление URL-маршрутов

Добавьте новые URL-маршруты в urls.py:

path('edit/<int:pk>/', views.task_edit, name='task_edit'), path('delete/<int:pk>/', views.task_delete, name='task_delete'),

Обновление шаблона списка задач

Измените task_list.html, чтобы добавить ссылки на редактирование и удаление:

<ul> {% for task in page_obj %} <li> {{ task.title }} - {{ task.created_at }} <a href="{% url 'task_edit' task.pk %}">Редактировать</a> <a href="{% url 'task_delete' task.pk %}">Удалить</a> </li> {% empty %} <li>Нет задач</li> {% endfor %} </ul>

Добавление категорий для задач

Категории помогут организовать задачи и улучшить навигацию.

Создание модели категории

Добавьте следующий код в models.py:

class Category(models.Model): name = models.CharField(max_length=100) def __str__(self): return self.name class Task(models.Model): # Существующие поля category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True) 

Обновление формы задачи

Измените TaskForm в forms.py, чтобы включить поле категории:

class TaskForm(forms.ModelForm): class Meta: model = Task fields = ['title', 'description', 'category']

Создание представления для списка категорий

Добавьте следующую функцию в views.py:

def category_list(request): categories = Category.objects.all() return render(request, 'category_list.html', {'categories': categories}) 

Создание шаблона для списка категорий

Создайте файл category_list.html в директории templates:

<h2>Категории</h2> <ul> {% for category in categories %} <li> <a href="{% url 'task_list' %}?category={{ category.pk }}">{{ category.name }}</a> </li> {% empty %} <li>Нет категорий</li> {% endfor %} </ul>

Обновление представления списка задач

Измените функцию task_list в views.py, чтобы учитывать фильтрацию по категориям:

def task_list(request): query = request.GET.get('q') category_id = request.GET.get('category') tasks = Task.objects.all() if query: tasks = tasks.filter(Q(title__icontains=query) | Q(description__icontains=query)) if category_id: tasks = tasks.filter(category_id=category_id) tasks = tasks.order_by('-created_at') paginator = Paginator(tasks, 10) page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) categories = Category.objects.all() return render(request, 'task_list.html', { 'page_obj': page_obj, 'query': query, 'categories': categories, 'selected_category': category_id }) 

Обновление шаблона списка задач

Добавьте список категорий в task_list.html:

<h3>Категории</h3> <ul> <li><a href="{% url 'task_list' %}">Все задачи</a></li> {% for category in categories %} <li> <a href="{% url 'task_list' %}?category={{ category.pk }}" {% if selected_category == category.pk|stringformat:"s" %}class="selected"{% endif %}> {{ category.name }} </a> </li> {% endfor %} </ul>

Добавление приоритетов для задач

Приоритеты помогут пользователям выделять наиболее важные задачи.

Обновление модели задачи

Добавьте поле приоритета в модель Task в models.py:

class Task(models.Model): PRIORITY_CHOICES = ( (1, 'Низкий'), (2, 'Средний'), (3, 'Высокий'), ) # Существующие поля priority = models.IntegerField(choices=PRIORITY_CHOICES, default=2) 

Обновление формы задачи

Добавьте поле приоритета в TaskForm в forms.py:

class TaskForm(forms.ModelForm): class Meta: model = Task fields = ['title', 'description', 'category', 'priority']

Обновление представления списка задач

Измените функцию task_list в views.py, чтобы учитывать сортировку по приоритету:

def task_list(request): # Существующий код sort = request.GET.get('sort', '-created_at') if sort == 'priority': tasks = tasks.order_by('-priority', '-created_at') else: tasks = tasks.order_by(sort) # Остальной код 

Обновление шаблона списка задач

Добавьте возможность сортировки по приоритету в task_list.html:

<p> Сортировать по: <a href="{% url 'task_list' %}?sort=-created_at">Дате создания</a> | <a href="{% url 'task_list' %}?sort=priority">Приоритету</a> </p> <ul> {% for task in page_obj %} <li> {{ task.title }} - {{ task.get_priority_display }} приоритет <!-- Остальной код --> </li> {% empty %} <li>Нет задач</li> {% endfor %} </ul>

Добавление дат выполнения для задач

Даты выполнения помогут пользователям отслеживать сроки выполнения задач.

Обновление модели задачи

Добавьте поле даты выполнения в модель Task в models.py:

from django.utils import timezone class Task(models.Model): # Существующие поля due_date = models.DateField(null=True, blank=True) def is_overdue(self): return self.due_date and self.due_date < timezone.now().date()

Обновление формы задачи

Добавьте поле даты выполнения в TaskForm в forms.py:

class TaskForm(forms.ModelForm): due_date = forms.DateField( widget=forms.DateInput(attrs={'type': 'date'}), required=False ) class Meta: model = Task fields = ['title', 'description', 'category', 'priority', 'due_date']

Обновление представления списка задач

Измените функцию task_list в views.py, чтобы учитывать фильтрацию по статусу выполнения:

def task_list(request): # Существующий код status = request.GET.get('status') if status == 'overdue': tasks = tasks.filter(due_date__lt=timezone.now().date()) elif status == 'upcoming': tasks = tasks.filter(due_date__gte=timezone.now().date()) # Остальной код 

Обновление шаблона списка задач

Добавьте фильтрацию по статусу выполнения в task_list.html:

<p> Фильтр: <a href="{% url 'task_list' %}">Все задачи</a> | <a href="{% url 'task_list' %}?status=overdue">Просроченные</a> | <a href="{% url 'task_list' %}?status=upcoming">Предстоящие</a> </p> <ul> {% for task in page_obj %} <li{% if task.is_overdue %} class="overdue"{% endif %}> {{ task.title }} - {{ task.get_priority_display }} приоритет {% if task.due_date %} - Срок: {{ task.due_date }} {% endif %} <!-- Остальной код --> </li> {% empty %} <li>Нет задач</li> {% endfor %} </ul>

Добавление комментариев к задачам

Комментарии позволят пользователям обсуждать задачи и добавлять дополнительную информацию.

Создание модели комментария

Добавьте следующий код в models.py:

class Comment(models.Model): task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name='comments') author = models.ForeignKey(User, on_delete=models.CASCADE) text = models.TextField() created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f'Comment by {self.author} on {self.task}'

Создание формы комментария

Добавьте следующий код в forms.py:

class CommentForm(forms.ModelForm): class Meta: model = Comment fields = ['text']

Создание представления для добавления комментария

Добавьте следующую функцию в views.py:

@login_required def add_comment(request, task_id): task = get_object_or_404(Task, id=task_id) if request.method == 'POST': form = CommentForm(request.POST) if form.is_valid(): comment = form.save(commit=False) comment.task = task comment.author = request.user comment.save() return redirect('task_detail', pk=task.pk) else: form = CommentForm() return render(request, 'add_comment.html', {'form': form, 'task': task})

Создание шаблона для добавления комментария

Создайте файл add_comment.html в директории templates:

<h2>Добавить комментарий к задаче "{{ task.title }}"</h2> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">Добавить комментарий</button> </form> <a href="{% url 'task_detail' task.pk %}">Вернуться к задаче</a>

Обновление представления детальной информации о задаче

Добавьте следующую функцию в views.py:

def task_detail(request, pk): task = get_object_or_404(Task, pk=pk) comments = task.comments.all().order_by('-created_at') comment_form = CommentForm() return render(request, 'task_detail.html', { 'task': task, 'comments': comments, 'comment_form': comment_form })

Создание шаблона для детальной информации о задаче

Создайте файл task_detail.html в директории templates:

<h2>{{ task.title }}</h2> <p>{{ task.description }}</p> <p>Приоритет: {{ task.get_priority_display }}</p> {% if task.category %} <p>Категория: {{ task.category }}</p> {% endif %} {% if task.due_date %} <p>Срок выполнения: {{ task.due_date }}{% if task.is_overdue %} (просрочено){% endif %}</p> {% endif %} <h3>Комментарии</h3> {% for comment in comments %} <div> <p>{{ comment.text }}</p> <p>Автор: {{ comment.author }} | {{ comment.created_at }}</p> </div> {% empty %} <p>Нет комментариев</p> {% endfor %} <h4>Добавить комментарий</h4> <form method="post" action="{% url 'add_comment' task.pk %}"> {% csrf_token %} {{ comment_form.as_p }} <button type="submit">Добавить комментарий</button> </form> <a href="{% url 'task_list' %}">Вернуться к списку задач</a>

Обновление URL-маршрутов

Добавьте новые URL-маршруты в urls.py:

path('task/<int:pk>/', views.task_detail, name='task_detail'), path('task/<int:task_id>/comment/', views.add_comment, name='add_comment'),

Добавление функции поиска по нескольким полям

Расширенный поиск позволит пользователям находить задачи по различным критериям.

Читайте также  Влияние взлома сайта на его полную деиндексацию

Создание формы расширенного поиска

Добавьте следующий код в forms.py:

class AdvancedSearchForm(forms.Form): query = forms.CharField(required=False, label='Поиск') category = forms.ModelChoiceField(queryset=Category.objects.all(), required=False, label='Категория') priority = forms.ChoiceField(choices=[('', '---')] + Task.PRIORITY_CHOICES, required=False, label='Приоритет') status = forms.ChoiceField(choices=[ ('', '---'), ('overdue', 'Просроченные'), ('upcoming', 'Предстоящие'), ], required=False, label='Статус') start_date = forms.DateField(required=False, widget=forms.DateInput(attrs={'type': 'date'}), label='С даты') end_date = forms.DateField(required=False, widget=forms.DateInput(attrs={'type': 'date'}), label='По дату')

Обновление представления списка задач

Измените функцию task_list в views.py, чтобы использовать форму расширенного поиска:

from django.db.models import Q def task_list(request): form = AdvancedSearchForm(request.GET) tasks = Task.objects.all() if form.is_valid(): query = form.cleaned_data.get('query') category = form.cleaned_data.get('category') priority = form.cleaned_data.get('priority') status = form.cleaned_data.get('status') start_date = form.cleaned_data.get('start_date') end_date = form.cleaned_data.get('end_date') if query: tasks = tasks.filter(Q(title__icontains=query) | Q(description__icontains=query)) if category: tasks = tasks.filter(category=category) if priority: tasks = tasks.filter(priority=priority) if status == 'overdue': tasks = tasks.filter(due_date__lt=timezone.now().date()) elif status == 'upcoming': tasks = tasks.filter(due_date__gte=timezone.now().date()) if start_date: tasks = tasks.filter(due_date__gte=start_date) if end_date: tasks = tasks.filter(due_date__lte=end_date) tasks = tasks.order_by('-created_at') paginator = Paginator(tasks, 10) page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) return render(request, 'task_list.html', { 'page_obj': page_obj, 'form': form })

Обновление шаблона списка задач

Измените task_list.html, чтобы включить форму расширенного поиска:

<h2>Расширенный поиск</h2> <form method="get"> {{ form.as_p }} <button type="submit">Поиск</button> </form> <h2>Список задач</h2> <!-- Существующий код для отображения списка задач -->

Добавление функции экспорта задач

Экспорт задач позволит пользователям сохранять свои задачи в различных форматах.

Создание функции экспорта в CSV

Добавьте следующую функцию в views.py:

import csv from django.http import HttpResponse def export_tasks_csv(request): response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="tasks.csv"' writer = csv.writer(response) writer.writerow(['Title', 'Description', 'Category', 'Priority', 'Due Date', 'Created At']) tasks = Task.objects.all().values_list('title', 'description', 'category__name', 'priority', 'due_date', 'created_at') for task in tasks: writer.writerow(task) return response

Добавление URL-маршрута для экспорта

Добавьте следующий маршрут в urls.py:

path('export/csv/', views.export_tasks_csv, name='export_tasks_csv'),

Добавление ссылки на экспорт в шаблон списка задач

Добавьте следующий код в task_list.html:

<a href="{% url 'export_tasks_csv' %}">Экспорт задач в CSV</a>

Добавление функции импорта задач

Импорт задач позволит пользователям загружать задачи из файлов.

Создание формы для импорта CSV

Добавьте следующий код в forms.py:

class ImportCSVForm(forms.Form): csv_file = forms.FileField(label='Выберите CSV файл')

Создание функции импорта из CSV

Добавьте следующую функцию в views.py:

import csv import io from django.contrib import messages @login_required def import_tasks_csv(request): if request.method == 'POST': form = ImportCSVForm(request.POST, request.FILES) if form.is_valid(): csv_file = request.FILES['csv_file'] decoded_file = csv_file.read().decode('utf-8') io_string = io.StringIO(decoded_file) next(io_string) # Пропускаем заголовок for row in csv.reader(io_string, delimiter=',', quotechar='"'): _, created = Task.objects.get_or_create( title=row[0], description=row[1], category=Category.objects.get_or_create(name=row[2])[0], priority=row[3], due_date=row[4] if row[4] else None, ) messages.success(request, 'Задачи успешно импортированы') return redirect('task_list') else: form = ImportCSVForm() return render(request, 'import_tasks.html', {'form': form})

Создание шаблона для импорта задач

Создайте файл import_tasks.html в директории templates:

<h2>Импорт задач из CSV</h2> <form method="post" enctype="multipart/form-data"> {% csrf_token %} {{ form.as_p }} <button type="submit">Импортировать</button> </form> <a href="{% url 'task_list' %}">Вернуться к списку задач</a>

Добавление URL-маршрута для импорта

Добавьте следующий маршрут в urls.py:

path('import/csv/', views.import_tasks_csv, name='import_tasks_csv'),

Добавление ссылки на импорт в шаблон списка задач

Добавьте следующий код в task_list.html:

<a href="{% url 'import_tasks_csv' %}">Импорт задач из CSV</a>

Добавление уведомлений о предстоящих задачах

Уведомления помогут пользователям не забывать о важных задачах.

Создание модели уведомления

Добавьте следующий код в models.py:

class Notification(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) task = models.ForeignKey(Task, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) is_read = models.BooleanField(default=False) def __str__(self): return f'Уведомление для {self.user} о задаче {self.task}'

Создание функции для генерации уведомлений

Добавьте следующую функцию в views.py:

from django.utils import timezone def generate_notifications(): tomorrow = timezone.now().date() + timezone.timedelta(days=1) tasks = Task.objects.filter(due_date=tomorrow) for task in tasks: Notification.objects.get_or_create(user=task.user, task=task)

Настройка регулярного выполнения генерации уведомлений

Для регулярного выполнения генерации уведомлений можно использовать Celery или Django-crontab. Например, с использованием Django-crontab добавьте следующий код в settings.py:

INSTALLED_APPS = [ # ... 'django_crontab', ] CRONJOBS = [ ('0 0 * * *', 'your_app.views.generate_notifications') ]

Отображение уведомлений

Добавьте следующую функцию в views.py для отображения уведомлений:

@login_required def notifications(request): notifications = Notification.objects.filter(user=request.user, is_read=False) return render(request, 'notifications.html', {'notifications': notifications})

Создание шаблона для отображения уведомлений

Создайте файл notifications.html в директории templates:

<h2>Уведомления</h2> <ul> {% for notification in notifications %} <li> Задача "{{ notification.task.title }}" должна быть выполнена завтра <a href="{% url 'task_detail' notification.task.pk %}">Перейти к задаче</a> </li> {% empty %} <li>Нет новых уведомлений</li> {% endfor %} </ul> <a href="{% url 'task_list' %}">Вернуться к списку задач</a>

Добавление URL-маршрута для уведомлений

Добавьте следующий маршрут в urls.py:

path('notifications/', views.notifications, name='notifications'),

Добавление ссылки на уведомления в базовый шаблон

Добавьте следующий код в ваш базовый шаблон (обычно base.html):

{% if user.is_authenticated %} <a href="{% url 'notifications' %}">Уведомления ({{ user.notification_set.filter(is_read=False).count }})

Заключение

В этой статье мы рассмотрели процесс создания функционального приложения для управления задачами с использованием Django. Мы охватили следующие темы:

  • Установка Django и создание проекта
Советы по созданию сайтов