Первый урок по 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'), ] 

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

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

Читайте также  Наступление новой эры адаптивного веб-дизайна

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

Добавьте следующие функции в 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 и создание проекта
Советы по созданию сайтов