И снова здравствуйте. В преддверии старта курса «Web-разработчик на Python» наш внештатный автор подготовил интересный материал, которым с радостью делимся с вами.
![](https://habrastorage.org/webt/fj/ze/xp/fjzexptqv3s9n9nqjpg5wvl-xog.png)
Джанго это мощный фреймворк для создания веб-приложений. Изначально Django был создан для того, чтобы быстро создавать, например, новостные сайты (или другие сайты, который нужно создавать максимально быстро). И после нативного PHP не покидает ощущение, что ты едешь на очень быстрой машине разработки. Чтобы посмотреть все его возможности для быстрой разработки, мы с вами попробуем создать простое Todo — приложение.
![](https://habrastorage.org/webt/js/cr/kg/jscrkgjwti_yxuwa87dnxygdupo.jpeg)
Начнем с формулировки краткого т.з. У нас будет небольшое веб-приложение с версткой на Bulma (да, я очень люблю Bulma. Возможно, когда-нибудь я сверну на Bootstrap или Picnic, но всему свое время). У нас (пока) нет авторизаций и пользователь может создавать, редактировать и удалять либо категорию дел, либо карточку todo, которая связана с какой-либо категорией, которую создал пользователь. Todo карточку или категорию можно удалить, поставив галочку на checkbox и нажав кнопку удалить.
Немного поговорим о Django. Django реализует архитектурный паттерн MVT (Модель Представление Шаблон), которая немного отличается от знакомого большинству MVC (Модель Представление Контроллер) на котором работает Ruby on Rails и Laravel.
Модель (Model) Модель в Django описывает схему данных в БД. С Django ORM, вы можете самостоятельно описывать поля и любые другие типы данных, и совершать миграции для упрощения разработки.
Представление (View) В представлении в Django вы задаете основную логику и алгоритмы приложения, получаете различные данные из базы данных или манипулируете ими. Представление обычно базируется на функциях request\response. Response представляет из себя обычно HTTP redirect, HTTP error(404), MimeTypes или какой-либо шаблон.
Шаблон Шаблон в Django это простой HTML код со специальным шаблонным языком Django. DTL (Django Template Language) — это язык, с помощью которого вы можете динамически менять содержимое страницы (к примеру, изменять имя пользователя на странице, в зависимости от того, как зовут авторизовавшегося пользователя).
Настройки Файл настроек в Django, в котором находятся все настройки вашего веб-приложения. Он включает в себя секретный ключ, папки с шаблонами, middlewares (которые отвечают, например за то, чтобы ваши приватные альбомы не увидели другие пользователи), подключение к базе данных, и много всего остального.
Url Файл настройки роутинга — примерно то же самое, что и в Angular или Laravel. Это связывает представление с url запросами.
Страница Админа Так как Django изначально был спроектирован для быстрого прототипирования и развертывания новостных сайтов, админка включена в комплект по умолчанию.
До последнего времени активно поддерживались и развивались две основные ветки Python: 2.7 и 3.x. Я буду использовать версию 3.7.3 в данной статье, но на самом деле это не так важно. Если вы правда хотите знать разницу между ними, есть специальная вики. С другой стороны, сейчас уже нет никакого смысла использовать Python версии 2.7 — обновление языка остановилось на 2.7.17 (если я правильно понимаю документацию на официальном сайте). Это означает, что есть смысл переводить проекты написанные на Python 2.7.x на новую ветку, а вот новые писать на 2 версии совсем бессмысленно.
Если вы работаете на Mac или Ubuntu — у вас уже скорее всего установлен Python, однако 2 версии. Python третьей версии придется скачивать отдельно, и вызывать его в командной строке вы сможете через python3. В любом случае, лучше всего скачать последний релиз здесь.
На самом деле первое приложение на Django вы можете начать разрабатывать и не создавая свое виртуальное окружение, однако навык создания виртуального окружения может пригодится если вы, например, разрабатываете приложение с определенной версией библиотеки и не хотите устанавливать библиотеки глобально и замусоривать ваш system.
Так как же использовать virtual env?
![](https://habrastorage.org/webt/zr/ad/dh/zraddhn6g-mcadwn6xn-7ys1yim.png)
1) Самый простой вариант. Вы можете скачать замечательный IDE от JET BRAINS PyCharm Community Edition отсюда. После установки PyCharm создайте новый проект, и Pycharm по умолчанию предложит вам создать Virtual Env, в котором будет возможность установить нужную версию Django (или по умолчанию последнюю, которая на момент написания данной статьи 3.0.2):
2) Чуть более хардкорный вариант:
А что, если вы хотите запустить Django в virtual env, к примеру, в любимой папке?
Во, первых, создаем папку, в которой мы будет творить:
Дальше вводим следующие команды для активации venv, где django_env имя нашего виртуального окружения:
Далее наше виртуальное окружение активировалось. Можем поставить необходимые пакеты. В нашем случае это Django:
Если вы захотите выключить виртуальное окружение, чтобы вернуться в ваш глобальный python (вернуться в контекст system), введите следующую команду:
Хорошо, надеюсь с виртуальным окружением мы разобрались. Если возникли какие-то проблемы и дополнительные вопросы, полезные ссылочки можно найти здесь и здесь .
Допустим вы выбрали какой-то из способов создания своего виртуального окружения (или даже делаете все глобально, что же, никто не запрещает вам это делать). Теперь проходим в папку проекта и начинаем его создание:
Так, после того как Django открыл стартовую страницу, необходимо проинсталлировать наше приложение todolist в основное приложение. Открываем
Следующим шагом будет связывание приложения с базой данных. Если базы данных — это не то, с чем вы хотите возиться, вам стоит воспользоваться решением по умолчанию — SQlite. Я же решил воспользоваться PostgreSQL — она популярна и классически связана с Django, кроме того, потом мы можем захотеть увеличить производительность приложения. Инструкций как устанавливать PostgreSQL на все операционные системы достаточно много. Я разрабатываю под MacOS и не без небольших танцев с бубном я поставил эту базу данных, скачав сам Postgres.app отсюда . Что касается интерфейсов для БД, то здесь я воспользовался Postico и пробной версии для разработки приложения нам вполне хватит (хотя в принципе можно обойтись и без неё, потому что все наше взаимодействие с базой данных будет построено через само веб-приложение и миграции). Кроме того, пришлось поставить psycopg2 в виртуальное окружение проекта (без этого драйвера с БД ваше приложение работать не будет).
Дальше нужно настроить работу статики. По-прежнему редактируем файл
Для того, чтобы у вас заработала статика, проверьте что в списке INSTALLED_APPS находился пакет, отвечающий за статику:
И последнее в подготовительных работах, нам нужно ещё настроить базовую работу url в проекте:
Я добавил редирект так как хочу, чтобы с дефолтной страницы localhost сразу переходил на подстраницу category(чтобы не дай бог пользователь не потерялся). Также у нас есть роутинг на две страницы: категорий и дел.
Итак, надеюсь ваше приложение не упало. Далее мы можем наконец-то переходить к созданию самого приложения:
Дальше приступим к созданию модели, которая будет базово взаимодействовать с нашей базой данных. Для создания модели открываем файл
Отлично! Да, здесь у нас будет только две колонки в таблице Категорий: id и name. Дальше создадим таблицу для наших дел. Думаю, из комментариев все понятно:
После того, как ваша модель будет готова, необходимо создать миграции:
И потом запускаете сами миграции:
Откроем файл
Потом начинаем создание нашего дела. У экземпляра дела будут поля самого текста, даты, до которой должно быть закончено дело, категория дела, и объединенный контент:
После этого добавим функции добавления и удаления дел:
С тудушками все. Дальше можем перейти к странице Категорий. Создаем функцию категорий, в которой у нас тоже будет функция добавления и удаления категории. Принципиально здесь ничего нового не будет, у нас так же здесь будет возможность добавления и удаления:
На этом мы заканчиваем с файлом
Как вы помните, чтобы не писать css лишний раз, я воспользовался
![](https://habrastorage.org/webt/zr/ad/dh/zraddhn6g-mcadwn6xn-7ys1yim.png)
Создаем
Дальше у нас пойдут страницы
Тудушка:
И
Всем спасибо! На этом все. Возможно, где-то не идеальна верстка, или есть другие предложения по улучшению приложения, всех жду в комментарии. По традиции, несколько полезных ссылок:
![](https://habrastorage.org/webt/fj/ze/xp/fjzexptqv3s9n9nqjpg5wvl-xog.png)
Джанго это мощный фреймворк для создания веб-приложений. Изначально Django был создан для того, чтобы быстро создавать, например, новостные сайты (или другие сайты, который нужно создавать максимально быстро). И после нативного PHP не покидает ощущение, что ты едешь на очень быстрой машине разработки. Чтобы посмотреть все его возможности для быстрой разработки, мы с вами попробуем создать простое Todo — приложение.
![](https://habrastorage.org/webt/js/cr/kg/jscrkgjwti_yxuwa87dnxygdupo.jpeg)
Начнем с формулировки краткого т.з. У нас будет небольшое веб-приложение с версткой на Bulma (да, я очень люблю Bulma. Возможно, когда-нибудь я сверну на Bootstrap или Picnic, но всему свое время). У нас (пока) нет авторизаций и пользователь может создавать, редактировать и удалять либо категорию дел, либо карточку todo, которая связана с какой-либо категорией, которую создал пользователь. Todo карточку или категорию можно удалить, поставив галочку на checkbox и нажав кнопку удалить.
Основные концепции Django
Немного поговорим о Django. Django реализует архитектурный паттерн MVT (Модель Представление Шаблон), которая немного отличается от знакомого большинству MVC (Модель Представление Контроллер) на котором работает Ruby on Rails и Laravel.
Модель (Model) Модель в Django описывает схему данных в БД. С Django ORM, вы можете самостоятельно описывать поля и любые другие типы данных, и совершать миграции для упрощения разработки.
Представление (View) В представлении в Django вы задаете основную логику и алгоритмы приложения, получаете различные данные из базы данных или манипулируете ими. Представление обычно базируется на функциях request\response. Response представляет из себя обычно HTTP redirect, HTTP error(404), MimeTypes или какой-либо шаблон.
Шаблон Шаблон в Django это простой HTML код со специальным шаблонным языком Django. DTL (Django Template Language) — это язык, с помощью которого вы можете динамически менять содержимое страницы (к примеру, изменять имя пользователя на странице, в зависимости от того, как зовут авторизовавшегося пользователя).
Настройки Файл настроек в Django, в котором находятся все настройки вашего веб-приложения. Он включает в себя секретный ключ, папки с шаблонами, middlewares (которые отвечают, например за то, чтобы ваши приватные альбомы не увидели другие пользователи), подключение к базе данных, и много всего остального.
Url Файл настройки роутинга — примерно то же самое, что и в Angular или Laravel. Это связывает представление с url запросами.
Страница Админа Так как Django изначально был спроектирован для быстрого прототипирования и развертывания новостных сайтов, админка включена в комплект по умолчанию.
Установка Python и Django
Творческое отступление
Автор этой статьи (то есть я) кроме написания статей занимается еще и обучением основам питона детей. По долгу службы я ставил Python и его пакеты на достаточно большое количество разнообразных машин. И кроме переустановок питона, один раз для установки пакета глобально сработал даже даунгрейд версии языка. Да, так тоже бывает.
Версии Python
До последнего времени активно поддерживались и развивались две основные ветки Python: 2.7 и 3.x. Я буду использовать версию 3.7.3 в данной статье, но на самом деле это не так важно. Если вы правда хотите знать разницу между ними, есть специальная вики. С другой стороны, сейчас уже нет никакого смысла использовать Python версии 2.7 — обновление языка остановилось на 2.7.17 (если я правильно понимаю документацию на официальном сайте). Это означает, что есть смысл переводить проекты написанные на Python 2.7.x на новую ветку, а вот новые писать на 2 версии совсем бессмысленно.
Инсталляция Python
Если вы работаете на Mac или Ubuntu — у вас уже скорее всего установлен Python, однако 2 версии. Python третьей версии придется скачивать отдельно, и вызывать его в командной строке вы сможете через python3. В любом случае, лучше всего скачать последний релиз здесь.
Создание своего виртуального окружения
На самом деле первое приложение на Django вы можете начать разрабатывать и не создавая свое виртуальное окружение, однако навык создания виртуального окружения может пригодится если вы, например, разрабатываете приложение с определенной версией библиотеки и не хотите устанавливать библиотеки глобально и замусоривать ваш system.
Так как же использовать virtual env?
![](https://habrastorage.org/webt/zr/ad/dh/zraddhn6g-mcadwn6xn-7ys1yim.png)
1) Самый простой вариант. Вы можете скачать замечательный IDE от JET BRAINS PyCharm Community Edition отсюда. После установки PyCharm создайте новый проект, и Pycharm по умолчанию предложит вам создать Virtual Env, в котором будет возможность установить нужную версию Django (или по умолчанию последнюю, которая на момент написания данной статьи 3.0.2):
pip3 install django
2) Чуть более хардкорный вариант:
А что, если вы хотите запустить Django в virtual env, к примеру, в любимой папке?
Во, первых, создаем папку, в которой мы будет творить:
mkdir myfirstdjango && cd myfirstdjango
Дальше вводим следующие команды для активации venv, где django_env имя нашего виртуального окружения:
python3 -m venv django_env
source django_env/bin/activate
Далее наше виртуальное окружение активировалось. Можем поставить необходимые пакеты. В нашем случае это Django:
pip3 install django
Если вы захотите выключить виртуальное окружение, чтобы вернуться в ваш глобальный python (вернуться в контекст system), введите следующую команду:
deactivate
Хорошо, надеюсь с виртуальным окружением мы разобрались. Если возникли какие-то проблемы и дополнительные вопросы, полезные ссылочки можно найти здесь и здесь .
Создание самого проекта
Допустим вы выбрали какой-то из способов создания своего виртуального окружения (или даже делаете все глобально, что же, никто не запрещает вам это делать). Теперь проходим в папку проекта и начинаем его создание:
django-admin startproject todo #создаем корневую папку вашего проекта
cd todo #проходим в нее
python manage.py startapp todolist #как бы подприложение todolist
python3 manage.py runserver 8100 #поднимаем сервер на нашем любимом незанятом порте, 8000 по умолчанию
Так, после того как Django открыл стартовую страницу, необходимо проинсталлировать наше приложение todolist в основное приложение. Открываем
settings.py
и добавляем в уже имеющийся список приложений наш собственный todolist:INSTALLED_APPS = [
#предустановленные админки, аутентификации и остальное из коробки, не вижу смысла здесь перечислять
'todolist',
]
Следующим шагом будет связывание приложения с базой данных. Если базы данных — это не то, с чем вы хотите возиться, вам стоит воспользоваться решением по умолчанию — SQlite. Я же решил воспользоваться PostgreSQL — она популярна и классически связана с Django, кроме того, потом мы можем захотеть увеличить производительность приложения. Инструкций как устанавливать PostgreSQL на все операционные системы достаточно много. Я разрабатываю под MacOS и не без небольших танцев с бубном я поставил эту базу данных, скачав сам Postgres.app отсюда . Что касается интерфейсов для БД, то здесь я воспользовался Postico и пробной версии для разработки приложения нам вполне хватит (хотя в принципе можно обойтись и без неё, потому что все наше взаимодействие с базой данных будет построено через само веб-приложение и миграции). Кроме того, пришлось поставить psycopg2 в виртуальное окружение проекта (без этого драйвера с БД ваше приложение работать не будет).
Дальше нужно настроить работу статики. По-прежнему редактируем файл
settings.py
, теперь в самом конце добавляем работу со статикой:STATIC_URL = '/static/'
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static')
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
Для того, чтобы у вас заработала статика, проверьте что в списке INSTALLED_APPS находился пакет, отвечающий за статику:
django.contrib.staticfiles,
на тот случай, если произойдет ошибка.И последнее в подготовительных работах, нам нужно ещё настроить базовую работу url в проекте:
from django.conf.urls import url
from django.contrib import admin
from todolist.views import todo
from todolist.views import category
from todolist.views import redirect_view
urlpatterns = [
url(r'$^', redirect_view ),
url(r'^admin/', admin.site.urls),
url(r'^todo/', todo, name="TodoList"),
url(r'^category/', category, name="Category"),
]
Я добавил редирект так как хочу, чтобы с дефолтной страницы localhost сразу переходил на подстраницу category(чтобы не дай бог пользователь не потерялся). Также у нас есть роутинг на две страницы: категорий и дел.
Итак, надеюсь ваше приложение не упало. Далее мы можем наконец-то переходить к созданию самого приложения:
Создание модели Todo и Категорий
Дальше приступим к созданию модели, которая будет базово взаимодействовать с нашей базой данных. Для создания модели открываем файл
models.py
в нашем todolist и начинаем творить. Начнем с того, что создадим таблицу категорий:from django.utils import timezone #мы будем получать дату создания todo
from django.db import models
class Category(models.Model): # Таблица категория которая наследует models.Model
name = models.CharField(max_length=100) #varchar.Нам потребуется только имя категории
class Meta:
verbose_name = ("Category") # человекочитаемое имя объекта
verbose_name_plural = ("Categories") #человекочитаемое множественное имя для Категорий
def __str__(self):
return self.name # __str__ применяется для отображения объекта в интерфейсе
Отлично! Да, здесь у нас будет только две колонки в таблице Категорий: id и name. Дальше создадим таблицу для наших дел. Думаю, из комментариев все понятно:
class TodoList(models.Model):
title = models.CharField(max_length=250)
content = models.TextField(blank=True) #текстовое поле
created = models.DateField(default=timezone.now().strftime("%Y-%m-%d")) # дата создания
due_date = models.DateField(default=timezone.now().strftime("%Y-%m-%d")) #до какой даты нужно было сделать дело
category = models.ForeignKey(Category, default="general",on_delete=models.PROTECT) # foreignkey с помощью которой мы будем осуществлять связь с таблицей Категорий
class Meta: #используем вспомогательный класс мета для сортировки наших дел
ordering = ["-created"] #сортировка дел по времени их создания
def __str__(self):
return self.title
После того, как ваша модель будет готова, необходимо создать миграции:
python3 manage.py makemigrations
И потом запускаете сами миграции:
python3 manage.py migrate
Создание view
Откроем файл
view.py
в todolist и отредактируем его. Для начала добавим необходимые импорты и редирект с главной на category:from django.shortcuts import render, redirect #для отображения и редиректа берем необходимые классы
from django.http import HttpResponse
from .models import TodoList, Category #не забываем наши модели
def redirect_view(request):
return redirect("/category") # редирект с главной на категории
Потом начинаем создание нашего дела. У экземпляра дела будут поля самого текста, даты, до которой должно быть закончено дело, категория дела, и объединенный контент:
def todo(request):
todos = TodoList.objects.all() #запрашиваем все объекты todo через менеджер объектов
categories = Category.objects.all() #так же получаем все Категории
После этого добавим функции добавления и удаления дел:
if request.method == "POST": #проверяем то что метод именно POST
if "Add" in request.POST: #проверяем метод добавления todo
title = request.POST["description"] #сам текст
date = str(request.POST["date"]) #дата, до которой должно быть закончено дело
category = request.POST["category_select"] #категория, которой может выбрать или создать пользователь.
content = title + " -- " + date + " " + category # полный склеенный контент
Todo = TodoList(title=title, content=content, due_date=date, category=Category.objects.get(name=category))
Todo.save() # сохранение нашего дела
return redirect("/todo") # перегрузка страницы (ну вот так у нас будет устроено очищение формы)
if "Delete" in request.POST: #если пользователь собирается удалить одно дело
checkedlist = request.POST.getlist('checkedbox') # берем список выделенные дел, которые мы собираемся удалить
for i in range(len(checkedlist)): #мне почему-то не нравится эта конструкция
todo = TodoList.objects.filter(id=int(checkedlist[i]))
todo.delete() #удаление дела
return render(request, "todo.html", {"todos": todos, "categories": categories})
С тудушками все. Дальше можем перейти к странице Категорий. Создаем функцию категорий, в которой у нас тоже будет функция добавления и удаления категории. Принципиально здесь ничего нового не будет, у нас так же здесь будет возможность добавления и удаления:
def category(request):
categories = Category.objects.all() #запрашиваем все объекты Категорий
if request.method == "POST": #проверяем что это метод POST
if "Add" in request.POST: #если собираемся добавить
name = request.POST["name"] #имя нашей категории
category = Category(name=name) #у нашей категории есть только имя
category.save() # сохранение нашей категории
return redirect("/category")
if "Delete" in request.POST: # проверяем есть ли удаление
check = request.POST.getlist('check') #немного изменил название массива в отличии от todo, что бы было меньше путаницы в коде
for i in range(len(check)):
try:
сateg = Category.objects.filter(id=int(check[i]))
сateg.delete() #удаление категории
except BaseException: # вне сомнения тут нужно нормально переписать обработку ошибок, но на первое время хватит и этого
return HttpResponse('<h1>Сначала удалите карточки с этими категориями)</h1>')
return render(request, "category.html", {"categories": categories})
На этом мы заканчиваем с файлом
view
и можем переходить к шаблонам:Работа с шаблонами
Как вы помните, чтобы не писать css лишний раз, я воспользовался
bulma.css
для упрощения верстки. Т.к. наши страницы категорий и todo буду очень схожи, я создал три файла:base.html
, который будет включать в себя все одинаковое, что у нас есть на страницах, а в category.html
, todo.html
будут располагаются отличия:![](https://habrastorage.org/webt/zr/ad/dh/zraddhn6g-mcadwn6xn-7ys1yim.png)
Создаем
base.html
и редактируем его:<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title> Приложение для дел</title>
{% load static %}
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.png' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'bulma.min.css' %}">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<div django-app="TaskManager">
<nav class ="navbar is-success" role="navigation" aria-label="main navigation">
<div class="navbar-menu ">
<div class="navbar-start">
<a class="navbar-item" href="../category"> Категории</a>
<a class="navbar-item" href="../todo"> Список дел </a>
</div>
</div>
</nav>
<!-- в блок контент мы будем подгружать наши странички категорий и тудушек-->
{% block content %}
{% endblock %}
</div>
</body>
</html>
Дальше у нас пойдут страницы
todo.html
и category.html
:Тудушка:
{% extends 'base.html' %}
{% block content %}
<div class="columns has-background-black-ter is-centered has-text-white-bis" style="min-height:101vh;">
<!-- на самом деле можно было обойтись и hero, но я обратился к inline-css -->
<div class="column is-half">
<h1 class="is-size-3 has-text-centered"> Список дел </h1>
<form action="" method="post">
{% csrf_token %}
<!-- csrf для базовой безопасности нашего приложения -->
<div class="field has-text-centered">
<label for="description" class="label has-text-white-bis">Введите дело</label>
<div class="control">
<input type="text" id="description" class="input" placeholder="Чем собираетесь заняться?"
name="description" required>
</div>
</div>
<div class="columns">
<div class="column">
<label for="category">Категории</label>
<div class="control">
<div class="select">
<select id="category" class="select" name="category_select" required>
<!--поставишь такой required, и не надо пустые поляв бд валидизировать. Не повторять в продакшене-->
<option class="disabled" value="">Выберите категорию дела</option>
{% for category in categories %}
<option class="" value="{{ category.name }}" name="{{ category.name }}">
{{ category.name }}</option>
{% endfor %}
</select>
</div>
</div>
</div>
<div class="column">
<label for="dueDate">Выберите дату</label>
<input type="date" id="dueDate" class="input calendar" name="date" required>
</div>
</div>
<div class="column">
<div class="field">
<button class="button is-primary" name="Add" type="submit">
<span class="icon is-small">
<i class="fa fa-plus"></i>
</span>
<span>Добавить задание</span>
</button>
<button class="button is-link" name="Delete" formnovalidate="" type="submit">
<span class="icon is-small">
<i class="fa fa-trash-o"></i>
</span>
<span>
Удалить дело
</span>
</button>
</div>
</div>
<div class="list is-hoverable">
{% for todo in todos %}
<!-- шаблонный язык django- for loop -->
<div class="list-item">
<label class="checkbox">
<input type="checkbox" class=" checkbox" name="checkedbox" value="{{ todo.id }}">
<span class="complete-">{{ todo.title }}</span>
</label>
<span class=" category-{{ todo.category }} has-text-info">{{ todo.category }}</span>
<strong class="is-pulled-right"><i class="fa fa-calendar"></i>{{ todo.created }} -
{{ todo.due_date }}</strong>
</div>
{% endfor %}
</div>
</form>
</div>
</div>
{% endblock %}
И
category.html
. В ней у нас не особо много чего меняется, принципиально никак не отличается от todo.html
:{% extends 'base.html' %}
{% block content %}
<div class="columns has-background-link has-text-white is-centered" style="min-height: 101vh;">
<div class="column is-half">
<h1 class="is-size-4 has-text-centered"> Отредактируйте ваши категории </h1>
<form action="" method="post">
{% csrf_token %}
<!-- csrf для базовой безопасности нашего приложения -->
<div class="field has-text-centered">
<label for="description" class="label has-text-white-bis"> Введите категории </label>
<div class="control">
<input type="text" id="description" class="input" placeholder="Какого рода у вас дела?"
name="name" required>
</div>
<div class="field">
<button class="button is-primary" name="Add" type="submit">
<span class="icon is-small">
<i class="fa fa-plus"></i>
</span>
<span>Добавить категорию</span>
</button>
<button class="button is-danger" name="Delete" formnovalidate="" type="submit">
<span class="icon is-small">
<i class="fa fa-trash-o"></i>
</span>
<span> Удалить категорию </span>
</button>
</div>
</div>
<!-- cписок наших категорий -->
<div class="list is-hoverable">
{% for category in categories %}
<div class="list-item">
<label class="checkbox">
<input type="checkbox" class="checkbox" name="check" value="{{category.id}}">
<span class="complete-">{{ category.name }}</span>
</label>
</div>
{% endfor %}
</div>
</form>
</div>
{% endblock %}
Всем спасибо! На этом все. Возможно, где-то не идеальна верстка, или есть другие предложения по улучшению приложения, всех жду в комментарии. По традиции, несколько полезных ссылок:
- Официальная документация Django, если вы хотите разрабатывать на новой 3 версии
- В русскоязычной интернете не так много хороший гайдов по поводу ООП, но этот мне кажется самым полезным
- Русскоязычная документация на PostgreSQL
staticlab
У вас отступы в питоновском коде поехали.