Первый фриланс проект - школа паралимпийского резерва
Автор: Иван Ашихмин
Всем привет!
Вчера закончилась работа по проекту для Хабаровской краевой спортивно-адаптивной школы паралимпийского и сурдлимпийского резерва. Проект длился почти год - с июня 2023 г. по конец мая 2024 г.
Задача заключалась в создании новостного сайта школы для замены устаревшего.
О том, почему так долго и как всё проходило расскажу в этом посте.
Сайт школы: https://kski.ru
Старый сайт школы: https://old.kski.ru
С чего всё началось?
Автор: Иван Ашихмин
Всем привет!
Вчера закончилась работа по проекту для Хабаровской краевой спортивно-адаптивной школы паралимпийского и сурдлимпийского резерва. Проект длился почти год - с июня 2023 г. по конец мая 2024 г.
Задача заключалась в создании новостного сайта школы для замены устаревшего.
О том, почему так долго и как всё проходило расскажу в этом посте.
Сайт школы: https://kski.ru
Старый сайт школы: https://old.kski.ru
С чего всё началось?
🔥5
Шёл 2023-й год, я ещё учился в GeekBrains, только начал думать о канале в Telegram. В один из дней, в разговоре с одногруппником Юрием, он сообщает, что, возможно, будет заказ на новый сайт для школы. Начали обсуждать на чём его можно сделать и дошли до разработки с нуля на Django. К слову, Django я в то время знал весьма посредственно, хотя мой дипломный проект уже был готов, а у Юры другой стек, он больше по ботам в Telegram, автоматизации, парсерам и сайтам на CMS-движках.
Несколько дней спустя он мне написал с предложением заняться проектом вместе. Честно сказать, я сперва подумал, что это шутка, т.к. знал и умел тогда не-то, чтобы много. Ещё учиться и учиться, а тут, бац, "давай делать проект!". Да ещё и денег заплатят! Не то, что бы много, конечно, но "дарёному коню в зубы не смотрят". Это была возможность. Та самая возможность получить практический опыт, а не все те лабораторные задачки в GB. Я согласился.
На следующее утро я всё ещё думая, что это он просто ошибся, переспросил у него, на что получил положительный ответ. И началась работа.
Начало работы.
Было составлено первоначальное ТЗ:
- Фреймворк - Django.
- БД - MySQL.
- Менеджер БД - PHPMyAdmin.
- Веб-сервер - Nginx.
- Фронтенд должен работать на CSS-фреймворке - Bootstrap.
- В админке должен быть визуальный редактор для удобного добавления статей с возможностью добавления медиафайлов.
- На сайте должен быть поиск по материалам.
- Необходимы группы пользователей с разными уровнями прав.
- Необходимо логирование действий пользователей в админке.
- На сайте должны быть категории и материалы.
- Должна быть пагинация.
- Должна быть форма обратной связи с отправкой сообщения пользователя администратору по email.
- Должен быть раздел "Фотогалерея" с удобным управлением в админке.
Задача поставлена, также были обозначены первые сроки - до конца года, но хотят пораньше. Понял, принял и взялся за работу.
Создал первоначальный проект в Django и сделал приватный репозиторий для всего этого дела.
Было решено сразу всё делать используя Docker-контейнеры и Docker Compose, поэтому были созданы необходимые Dockerfile и docker-compose.yml. Прописаны сервисы БД, PHPMyAdmin, Nginx. Юра предоставил для разработки технический домен и VPS-сервер.
При прописывании БД, порты MySQL были прописаны наружу сервера, для того, чтобы можно было вести разработку используя БД сервера, без необходимости потом делать миграции и перенос содержимого.
Довольно быстро был выполнен начальный пласт работ - созданы необходимые модели, добавлен визуальный редактор CKeditor 4, подключен Bootstrap, созданы технические шаблоны с примерами вывода информации из БД.
В это же время Юрий занялся шаблоном сайта, разбираясь с шаблонизатором Django.
Позже были добавлены "хлебные крошки" на страницы сайта, превьюшки для статей, дополнительные кастомизации админки, теги к статьям и поиск.
Архитектура, а скорее структура менялась в процессе. Сперва было две модели - для категории статей и для статей. Затем понадобились контентные страницы (для разного рода документов школы), а затем и страницы с видео. Дабы не перегружать две модели вешая на них с указанием разных типов, для каждого были написаны свои модели. Это позволило разделить функционал и более удобно настраивать необходимые разделы.
Первые сложности.
Первая сложность возникла с реализацией галереи. Я тогда не представлял, как можно реализовать галерею с альбомами, да и сейчас бы, наверное, задумался о реализации. Выбор пал на готовую библиотеку django-photologue. Удобная библиотека, позволяющая загружать изображения не только по одному, но и в zip-архиве, создавать альбомы и управлять ими.
Пришлось немного править шаблоны библиотеки под макет сайта, но в целом трудность решена. Хотя, с этой библиотекой позже возникла ещё одна проблема, но об этом в конце поста.
Вторая большая сложность возникла при использовании библиотеки django-mptt. Она позволяет создавать древовидные категории. Сложностей было несколько:
Несколько дней спустя он мне написал с предложением заняться проектом вместе. Честно сказать, я сперва подумал, что это шутка, т.к. знал и умел тогда не-то, чтобы много. Ещё учиться и учиться, а тут, бац, "давай делать проект!". Да ещё и денег заплатят! Не то, что бы много, конечно, но "дарёному коню в зубы не смотрят". Это была возможность. Та самая возможность получить практический опыт, а не все те лабораторные задачки в GB. Я согласился.
На следующее утро я всё ещё думая, что это он просто ошибся, переспросил у него, на что получил положительный ответ. И началась работа.
Начало работы.
Было составлено первоначальное ТЗ:
- Фреймворк - Django.
- БД - MySQL.
- Менеджер БД - PHPMyAdmin.
- Веб-сервер - Nginx.
- Фронтенд должен работать на CSS-фреймворке - Bootstrap.
- В админке должен быть визуальный редактор для удобного добавления статей с возможностью добавления медиафайлов.
- На сайте должен быть поиск по материалам.
- Необходимы группы пользователей с разными уровнями прав.
- Необходимо логирование действий пользователей в админке.
- На сайте должны быть категории и материалы.
- Должна быть пагинация.
- Должна быть форма обратной связи с отправкой сообщения пользователя администратору по email.
- Должен быть раздел "Фотогалерея" с удобным управлением в админке.
Задача поставлена, также были обозначены первые сроки - до конца года, но хотят пораньше. Понял, принял и взялся за работу.
Создал первоначальный проект в Django и сделал приватный репозиторий для всего этого дела.
Было решено сразу всё делать используя Docker-контейнеры и Docker Compose, поэтому были созданы необходимые Dockerfile и docker-compose.yml. Прописаны сервисы БД, PHPMyAdmin, Nginx. Юра предоставил для разработки технический домен и VPS-сервер.
При прописывании БД, порты MySQL были прописаны наружу сервера, для того, чтобы можно было вести разработку используя БД сервера, без необходимости потом делать миграции и перенос содержимого.
Довольно быстро был выполнен начальный пласт работ - созданы необходимые модели, добавлен визуальный редактор CKeditor 4, подключен Bootstrap, созданы технические шаблоны с примерами вывода информации из БД.
В это же время Юрий занялся шаблоном сайта, разбираясь с шаблонизатором Django.
Позже были добавлены "хлебные крошки" на страницы сайта, превьюшки для статей, дополнительные кастомизации админки, теги к статьям и поиск.
Архитектура, а скорее структура менялась в процессе. Сперва было две модели - для категории статей и для статей. Затем понадобились контентные страницы (для разного рода документов школы), а затем и страницы с видео. Дабы не перегружать две модели вешая на них с указанием разных типов, для каждого были написаны свои модели. Это позволило разделить функционал и более удобно настраивать необходимые разделы.
Первые сложности.
Первая сложность возникла с реализацией галереи. Я тогда не представлял, как можно реализовать галерею с альбомами, да и сейчас бы, наверное, задумался о реализации. Выбор пал на готовую библиотеку django-photologue. Удобная библиотека, позволяющая загружать изображения не только по одному, но и в zip-архиве, создавать альбомы и управлять ими.
Пришлось немного править шаблоны библиотеки под макет сайта, но в целом трудность решена. Хотя, с этой библиотекой позже возникла ещё одна проблема, но об этом в конце поста.
Вторая большая сложность возникла при использовании библиотеки django-mptt. Она позволяет создавать древовидные категории. Сложностей было несколько:
🔥4
- Первая была связана с отображением древовидных категорий в админке. Эта сложность возникла не сразу, а после того, как мы сменили шаблон админки со стандартного на django-jazzmin. Пришлось немного править файлы шаблона.
- Вторая была связана с отображением выпадающего списка категорий на страницах сайта. Изначально была мысль делать выпадающий список, в котором будут свои выпадашки следующего уровня и это доставило много проблем, но какая-никакая, первая реализация была сделана.
В процессе Юра то и дело подкидывал задачи, например, нужно было связать фотогалерею со статьёй. Задача оказалась не трудной, достаточно было в модели статьи прописать внешний ключ на модель альбома. Это позволило при написании статьи выбирать связанную с ней галерею.
Ещё одной задачей было реализовать видеоархив. Необходимо было вставлять только ссылку на YouTube, при этом на странице выводить встраиваемый плеер, а в качестве обложки страницы брать превьюшку видео. Поскольку получать каждый раз превьюшку видео с YouTube чревато баном, для получения превьюшки была написана функция, получающая изображение и сохраняющая её на диске. Вызывается функция при сохранении новой страницы с видео в админке, там же и происходит формирование плеера.
На всё это ушёл месяц. Проект в большей степени был выполнен. И началось затишье...
Провал на пол года.
Юрий показал текущий на тот момент вариант руководству и мы начали ждать следующих распоряжений по сайту. Они пришли в феврале вместе с многостраничным документом от министерства образования. В документе описывались требования, которым должен соответствовать сайт бюджетной организации.
Изучив документ, в целом практически не нашли ничего нового. Небольшие правки шаблона, но был и один пункт - версия для слабовидящих. Работу по её внедрению взял на себя Юра. В интернете есть несколько сайтов предоставляющих скрипт для этого и почти все платно. Был найден бесплатный вариант, доработан и установлен на сайт.
Юрий занялся переносом данных со старого сайта на новый.
Legacy наше всё.
Руководство школы решило сохранить старый сайт как архив. И раз у нас куплен сервер под новый сайт, зачем платить за хостинг для старого? Давайте перенесём старый сайт на сервер.
Что может пойти не так? А вот, что - старый сайт был написан в 2011-м году. С тех пор он не обновлялся, а следовательно, базируется на очень старых технологиях:
- Apache 2.2
- PHP 5.2
- MySQL 5.7
Отойдя от ностальгических воспоминаний, я принялся за работу. Первой идеей было установить LAMP, но в нём самая старая версия PHP - 7.2. Далее были эксперименты с панелями Vesta и Hestia, но и там PHP был относительно свежий. Но, видимо не мне одному понадобился PHP 5.2, поскольку был найден docker-образ с установленным PHP и Apache. Установить MySQL версии 5.7 не составило труда, он доступен в репозитории Docker Hub.
Однако, сайт не заработал. Жаловался на базу данных, мол не может подключиться.
После ряда попыток "подружить" современные технологии со старыми, перезагрузок, правок файлов - в общем действий "методом тыка", старый сайт удалось завести.
Чтобы не мешать старый сайт и новый, для старого сайта был создан второй Docker compose файл, содержащий php, mysql и phpmyadmin.
Последний месяц работы.
Когда работа по переносу данных была закончена и и сайт был почти готов, начали доводить его до ума.
Реализовали форму обратной связи с применением celery для отправки почты администратору в фоновом режиме. Поскольку в форме присутствует возможность к сообщению прикрепить файл, был написан валидатор для прикрепляемых файлов.
Были сделаны мелкие правки для передачи нужных данных в шаблоны.
Я писал выше о проблеме реализации выпадающих списков в меню на страницах сайта, для её решения было решено сделать отдельную модель для меню сайта. Также с использованием mptt, но без дополнительных выпадающих списков. Теперь в меню указаны только нужные разделы, а не все существующие.
- Вторая была связана с отображением выпадающего списка категорий на страницах сайта. Изначально была мысль делать выпадающий список, в котором будут свои выпадашки следующего уровня и это доставило много проблем, но какая-никакая, первая реализация была сделана.
В процессе Юра то и дело подкидывал задачи, например, нужно было связать фотогалерею со статьёй. Задача оказалась не трудной, достаточно было в модели статьи прописать внешний ключ на модель альбома. Это позволило при написании статьи выбирать связанную с ней галерею.
Ещё одной задачей было реализовать видеоархив. Необходимо было вставлять только ссылку на YouTube, при этом на странице выводить встраиваемый плеер, а в качестве обложки страницы брать превьюшку видео. Поскольку получать каждый раз превьюшку видео с YouTube чревато баном, для получения превьюшки была написана функция, получающая изображение и сохраняющая её на диске. Вызывается функция при сохранении новой страницы с видео в админке, там же и происходит формирование плеера.
На всё это ушёл месяц. Проект в большей степени был выполнен. И началось затишье...
Провал на пол года.
Юрий показал текущий на тот момент вариант руководству и мы начали ждать следующих распоряжений по сайту. Они пришли в феврале вместе с многостраничным документом от министерства образования. В документе описывались требования, которым должен соответствовать сайт бюджетной организации.
Изучив документ, в целом практически не нашли ничего нового. Небольшие правки шаблона, но был и один пункт - версия для слабовидящих. Работу по её внедрению взял на себя Юра. В интернете есть несколько сайтов предоставляющих скрипт для этого и почти все платно. Был найден бесплатный вариант, доработан и установлен на сайт.
Юрий занялся переносом данных со старого сайта на новый.
Legacy наше всё.
Руководство школы решило сохранить старый сайт как архив. И раз у нас куплен сервер под новый сайт, зачем платить за хостинг для старого? Давайте перенесём старый сайт на сервер.
Что может пойти не так? А вот, что - старый сайт был написан в 2011-м году. С тех пор он не обновлялся, а следовательно, базируется на очень старых технологиях:
- Apache 2.2
- PHP 5.2
- MySQL 5.7
Отойдя от ностальгических воспоминаний, я принялся за работу. Первой идеей было установить LAMP, но в нём самая старая версия PHP - 7.2. Далее были эксперименты с панелями Vesta и Hestia, но и там PHP был относительно свежий. Но, видимо не мне одному понадобился PHP 5.2, поскольку был найден docker-образ с установленным PHP и Apache. Установить MySQL версии 5.7 не составило труда, он доступен в репозитории Docker Hub.
Однако, сайт не заработал. Жаловался на базу данных, мол не может подключиться.
После ряда попыток "подружить" современные технологии со старыми, перезагрузок, правок файлов - в общем действий "методом тыка", старый сайт удалось завести.
Чтобы не мешать старый сайт и новый, для старого сайта был создан второй Docker compose файл, содержащий php, mysql и phpmyadmin.
Последний месяц работы.
Когда работа по переносу данных была закончена и и сайт был почти готов, начали доводить его до ума.
Реализовали форму обратной связи с применением celery для отправки почты администратору в фоновом режиме. Поскольку в форме присутствует возможность к сообщению прикрепить файл, был написан валидатор для прикрепляемых файлов.
Были сделаны мелкие правки для передачи нужных данных в шаблоны.
Я писал выше о проблеме реализации выпадающих списков в меню на страницах сайта, для её решения было решено сделать отдельную модель для меню сайта. Также с использованием mptt, но без дополнительных выпадающих списков. Теперь в меню указаны только нужные разделы, а не все существующие.
🔥3
У нас возникла проблема с библиотекой фотогалереи, а именно - при загрузке архива с изображениями должен создаваться новый альбом со своим slug'ом на основе указанного названия альбома, но он не создавался. Причина была в том, что при создании альбома непосредственно в админке, поле slug заполняется одновременно с названием альбома силами JavaScript, а при создании альбома путём загрузки архива оно создаётся используя функцию slugify из Django. С этой функцией я уже сталкивался ранее и даже писал об этом в одном из постов по Django.
Проблема в том, что стандартная функция не преобразует кириллицу. Взять и изменить код в файлах библиотеки не так то просто, но это же Django, а значит можно подключить библиотеку как приложение. Это и было сделано. Удалил библиотеку из зависимостей и поместил директорию с файлами приложения в проект, поправил импорты и всё заработало. Далее оставалось дело за малым, в одном файлике изменить используемую библиотеку для слагификации названия альбома.
Оставался последний шаг - сменить технический домен на основной с поддержкой https.
С бесплатными сертификатами есть одна проблема, их нужно обновлять каждые три месяца. Это можно обойти написав скрипт, но мало ли, что пойдёт не так у владельцев сайта. Было решено заменить nginx на caddy. Caddy это современный вебсервер, напоминающий nginx структурой файла конфигурации, но в нём есть один важный плюс - он автоматически получает сертификат для сайта и сам его продлевает по истечении срока действия.
После того, как убедились, что всё работает как надо перенесли домен со старого хостинга на сервер. С переносом тоже были проблемы - регистратор R01 никак не хотел менять NS-сервера у домена. Очень странное поведение, но после обращения в поддержку NS-ы сменили.
Оставалось только заменить домен в конфигурационных файлах. Всё!
У нас получилось в итоге два Docker Compose файла - для нового и старого сайта. По сути у нас два сайта, две версии MySQL и два связанных с ними PHPMyAdmin. Благодаря докеру это не вызывает никаких проблем с версионностью и позволяет управлять контейнерами без вреда для остального.
Заключение.
На всё про всё ушёл год. Хотя работы по сути было на 2-3 месяца. Однако, работа над этим проектом позволила заняться реальным, а не PET-проектом. Дала толчок к существованию канала.
Не бойтесь браться за то, что кажется сложным. Пусть это проект для кого-то или личный. Всё это опыт, навыки и повод гордиться собой.
Пост на сайте
Поддержать проект
#Django #Проект #Celery #Фриланс #КСКИ #Заказ
Проблема в том, что стандартная функция не преобразует кириллицу. Взять и изменить код в файлах библиотеки не так то просто, но это же Django, а значит можно подключить библиотеку как приложение. Это и было сделано. Удалил библиотеку из зависимостей и поместил директорию с файлами приложения в проект, поправил импорты и всё заработало. Далее оставалось дело за малым, в одном файлике изменить используемую библиотеку для слагификации названия альбома.
Оставался последний шаг - сменить технический домен на основной с поддержкой https.
С бесплатными сертификатами есть одна проблема, их нужно обновлять каждые три месяца. Это можно обойти написав скрипт, но мало ли, что пойдёт не так у владельцев сайта. Было решено заменить nginx на caddy. Caddy это современный вебсервер, напоминающий nginx структурой файла конфигурации, но в нём есть один важный плюс - он автоматически получает сертификат для сайта и сам его продлевает по истечении срока действия.
После того, как убедились, что всё работает как надо перенесли домен со старого хостинга на сервер. С переносом тоже были проблемы - регистратор R01 никак не хотел менять NS-сервера у домена. Очень странное поведение, но после обращения в поддержку NS-ы сменили.
Оставалось только заменить домен в конфигурационных файлах. Всё!
У нас получилось в итоге два Docker Compose файла - для нового и старого сайта. По сути у нас два сайта, две версии MySQL и два связанных с ними PHPMyAdmin. Благодаря докеру это не вызывает никаких проблем с версионностью и позволяет управлять контейнерами без вреда для остального.
Заключение.
На всё про всё ушёл год. Хотя работы по сути было на 2-3 месяца. Однако, работа над этим проектом позволила заняться реальным, а не PET-проектом. Дала толчок к существованию канала.
Не бойтесь браться за то, что кажется сложным. Пусть это проект для кого-то или личный. Всё это опыт, навыки и повод гордиться собой.
Пост на сайте
Поддержать проект
#Django #Проект #Celery #Фриланс #КСКИ #Заказ
🔥8👍1
Docker ушёл из РФ! Как это исправить?
Автор: Иван Ашихмин
Сегодня утром многие были удивлены новостью о том, что Docker заблокировал свой главный репозиторий Docker Hub для ряда стран, включая и Россию. Новость, конечно, неприятная, но вполне ожидаемая. Давайте разберёмся как это исправить.
Docker Hub - это основной источник образов. При сборке контейнера, Docker в первую очередь обращается туда, однако, путь туда нам закрыт. Однако, Docker не ограничивается только основным репозиторием. Docker позволяет делать собственные репозитории. Помимо этого, есть и сторонние "зеркала". Ими мы и воспользуемся.
В данный момент под запрет попадают пользователи из России использующие Docker Desktop, но, вероятно, позже будет затронут и Docker Engine, работающий на VPS и серверах.
Решение проблемы для Docker Desktop.
Для решения проблемы необходимо прописать дополнительные зеркала в конфигурационный файл.
Автор: Иван Ашихмин
Сегодня утром многие были удивлены новостью о том, что Docker заблокировал свой главный репозиторий Docker Hub для ряда стран, включая и Россию. Новость, конечно, неприятная, но вполне ожидаемая. Давайте разберёмся как это исправить.
Docker Hub - это основной источник образов. При сборке контейнера, Docker в первую очередь обращается туда, однако, путь туда нам закрыт. Однако, Docker не ограничивается только основным репозиторием. Docker позволяет делать собственные репозитории. Помимо этого, есть и сторонние "зеркала". Ими мы и воспользуемся.
В данный момент под запрет попадают пользователи из России использующие Docker Desktop, но, вероятно, позже будет затронут и Docker Engine, работающий на VPS и серверах.
Решение проблемы для Docker Desktop.
Для решения проблемы необходимо прописать дополнительные зеркала в конфигурационный файл.
🔥7🤔1
Откройте приложение Docker Desktop и перейдите в настройки. В нём выбираем Docker Engine.
В окне будет редактор с предзаписанной конфигурацией в виде JSON. Необходимо добавить новый ключ со списком зеркал:
Мой конфиг выглядит так:
После чего нажимаем кнопку "Apply & restart". После перезагрузки всё будет работать.
Решение проблемы на VPS.
В данный момент на VPS Docker работает без проблем, однако подготовиться не помешает.
Файл конфигурации Docker находится по пути:
Откроем файл, выполнив команду
Если у вас открылся пустой редактор, значит файла у вас не было и после сохранения, он появится.
Точно так же как и в предыдущем пункте, необходимо в JSON добавить ключ со списком. Если у вас как у меня файла не было, то вставляем следующее:
Если у вас файл конфигурации был, то добавьте новый блок.
Сохраняем файл сочетанием клавиш
После этого необходимо перезапустить службу Docker, выполнив следующую команду:
Заключение.
Получать такие новости очень неприятно. Одно дело когда уходят (блокируют) какие-то их местные компании, которыми у нас никто не пользовался. Совсем по другому ощущается блокировка инструмента, которым пользуешься буквально каждый день.
Пост на сайте
Поддержать проект
#Docker #санкции #Docker_hub #обход
В окне будет редактор с предзаписанной конфигурацией в виде JSON. Необходимо добавить новый ключ со списком зеркал:
"registry-mirrors": [
"https://dockerhub.timeweb.cloud",
"https://mirror.gcr.io",
"https://huecker.io"
]
Мой конфиг выглядит так:
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"registry-mirrors": [
"https://dockerhub.timeweb.cloud",
"https://mirror.gcr.io",
"https://huecker.io"
]
}
После чего нажимаем кнопку "Apply & restart". После перезагрузки всё будет работать.
Решение проблемы на VPS.
В данный момент на VPS Docker работает без проблем, однако подготовиться не помешает.
Файл конфигурации Docker находится по пути:
/etc/docker/daemon.json, но его там может и не быть.Откроем файл, выполнив команду
sudo nano /etc/docker/daemon.json.Если у вас открылся пустой редактор, значит файла у вас не было и после сохранения, он появится.
Точно так же как и в предыдущем пункте, необходимо в JSON добавить ключ со списком. Если у вас как у меня файла не было, то вставляем следующее:
{
"registry-mirrors": [
"https://dockerhub.timeweb.cloud",
"https://mirror.gcr.io",
"https://huecker.io"
]
}
Если у вас файл конфигурации был, то добавьте новый блок.
Сохраняем файл сочетанием клавиш
CTRL+S и закрываем CTRL+X.После этого необходимо перезапустить службу Docker, выполнив следующую команду:
sudo systemctl restart docker.Заключение.
Получать такие новости очень неприятно. Одно дело когда уходят (блокируют) какие-то их местные компании, которыми у нас никто не пользовался. Совсем по другому ощущается блокировка инструмента, которым пользуешься буквально каждый день.
Пост на сайте
Поддержать проект
#Docker #санкции #Docker_hub #обход
🔥10👍3🤮1
Вместе следим за событиями!
Автор: Иван Ашихмин
Приветствую всех!
В суете повседневной работы и дел нередко бывает сложно следить за всеми происходящими событиями, новостями и обновлениями. Легко можно пропустить что-то важное, как, например, утренний пост о Docker.
Недавнюю новость о Docker, которую скинули в наш чат "Кот на салфетке", заметил благодаря Юрию. Спасибо ему за это! Однако, далеко не вся интересная и важная информация доходит до нас через привычные каналы.
Поэтому хочу обратиться к вам. Если у вас есть интересные новости или важные обновления, которые вы считаете стоящими нашего внимания, пожалуйста, делитесь ими в чате канала или пишите мне в личные сообщения (ссылка в описании канала).
Вместе мы сможем быть в курсе всех актуальных событий!
Пост на сайте
Поддержать проект
#код_на_салфетке #Новости #обновления #чат
Автор: Иван Ашихмин
Приветствую всех!
В суете повседневной работы и дел нередко бывает сложно следить за всеми происходящими событиями, новостями и обновлениями. Легко можно пропустить что-то важное, как, например, утренний пост о Docker.
Недавнюю новость о Docker, которую скинули в наш чат "Кот на салфетке", заметил благодаря Юрию. Спасибо ему за это! Однако, далеко не вся интересная и важная информация доходит до нас через привычные каналы.
Поэтому хочу обратиться к вам. Если у вас есть интересные новости или важные обновления, которые вы считаете стоящими нашего внимания, пожалуйста, делитесь ими в чате канала или пишите мне в личные сообщения (ссылка в описании канала).
Вместе мы сможем быть в курсе всех актуальных событий!
Пост на сайте
Поддержать проект
#код_на_салфетке #Новости #обновления #чат
🔥5👍1
Приветствую!
С 3-го по 9-е июня Хабр Карьера устраивает мероприятие "Вайб чек" для бэкендеров. Обещают вакансии, тематический квиз, игру в настолку и призы.
Если вы сейчас находитесь в поиске работы или хотите принять участие в мероприятии, то присоединяемся по ссылке: https://vibe.habr.com/
Где: Онлайн
Когда: 03-09 июня
Как попасть? Регистрация https://vibe.habr.com/
Успейте зарегистрироваться до 2-го июня.
Напишите в комментариях, будете ли вы принимать участие в мероприятии?
С 3-го по 9-е июня Хабр Карьера устраивает мероприятие "Вайб чек" для бэкендеров. Обещают вакансии, тематический квиз, игру в настолку и призы.
Если вы сейчас находитесь в поиске работы или хотите принять участие в мероприятии, то присоединяемся по ссылке: https://vibe.habr.com/
Где: Онлайн
Когда: 03-09 июня
Как попасть? Регистрация https://vibe.habr.com/
Успейте зарегистрироваться до 2-го июня.
Напишите в комментариях, будете ли вы принимать участие в мероприятии?
🔥5
Здравствуйте, дорогие друзья!
Наступил тот самый вечер, которого мы все ждали с таким нетерпением - вечер пятницы. Это время, когда мы можем отбросить все заботы и просто насладиться просмотром фильма.
Каждую пятницу мы собираемся вместе, чтобы открыть для себя новый фильм, который может удивить нас, заставить задуматься, рассмешить или просто подарить нам несколько часов удовольствия. Надеюсь, вы уже готовы к уютному вечеру с попкорном и отличным кино.
Фильм: Пушки Акимбо
Год: 2019
Скучное существование Майлза, разработчика видеоигр принимает драматический оборот, когда он случайно оказывается следующим участником SKIZM. Организаторы транслируют запрещенные, смертельные сражения в реальном времени на весь мир. Хотя Майлз справляется со всеми соперниками на отлично, ему придется сразится с безжалостной чемпионкой подпольных игр по прозвищу Никс.
https://www.kinopoisk.ru/film/1142604/
https://www.sspoisk.ru/film/1142604/
Желаю вам приятного просмотра и незабываемого вечера!
Наступил тот самый вечер, которого мы все ждали с таким нетерпением - вечер пятницы. Это время, когда мы можем отбросить все заботы и просто насладиться просмотром фильма.
Каждую пятницу мы собираемся вместе, чтобы открыть для себя новый фильм, который может удивить нас, заставить задуматься, рассмешить или просто подарить нам несколько часов удовольствия. Надеюсь, вы уже готовы к уютному вечеру с попкорном и отличным кино.
Фильм: Пушки Акимбо
Год: 2019
Скучное существование Майлза, разработчика видеоигр принимает драматический оборот, когда он случайно оказывается следующим участником SKIZM. Организаторы транслируют запрещенные, смертельные сражения в реальном времени на весь мир. Хотя Майлз справляется со всеми соперниками на отлично, ему придется сразится с безжалостной чемпионкой подпольных игр по прозвищу Никс.
https://www.kinopoisk.ru/film/1142604/
https://www.sspoisk.ru/film/1142604/
Желаю вам приятного просмотра и незабываемого вечера!
🔥4
Обновление библиотеки - AIOgram 3.7.0
Автор: Иван Ашихмин
Вышла новая версия AIOgram 3.7.0.
Установить новую версию можно, выполнив команду:
Что нового?
- Добавлено новое хранилище для хранения машины состояний на основе Mongo DB -
- Полная поддержка Bot API 7.4.
Багфиксы.
- Исправлен некорректный парсинг пользовательских эмодзи в MarkdownV2 в
Устаревшее и удалённое.
- Удалены устаревшие аргументы из класса Bot:
Пример использования
Автор: Иван Ашихмин
Вышла новая версия AIOgram 3.7.0.
Установить новую версию можно, выполнив команду:
pip install -U aiogram
Что нового?
- Добавлено новое хранилище для хранения машины состояний на основе Mongo DB -
aiogram.fsm.storage.MongoStorage.- Полная поддержка Bot API 7.4.
Багфиксы.
- Исправлен некорректный парсинг пользовательских эмодзи в MarkdownV2 в
aiogram.utils.text_decorations.Устаревшее и удалённое.
- Удалены устаревшие аргументы из класса Bot:
parse_mode, disable_web_page_preview, protect_content, как ранее было объявлено в 3.4.0.Пример использования
parse_mode в версии 3.7.0:from aiogram import Bot
from aiogram.client.default import DefaultBotProperties
bot = Bot(token=token, default=DefaultBotProperties(parse_mode='Markdown'))
Прочее.
- Улучшена согласованность и читаемость кода в примерах кода за счет рефакторинга импортов, настройки базового URL вебхука, изменения инициализации экземпляра бота для использования
DefaultBotProperties и обновления обработчиков сообщений роутера.P.S.
Проблема, о которой я писал в посте "Бот-автоответчик с ChatGPT для Бизнес-аккаунта в Telegram на Aiogram 3”, не исправлена.
Пост на сайте
Поддержать проект
#Telegram #Bot_API #список_изменений #Новости #aiogram #новая_версия
Что выведет код с изображения ниже? №24
Anonymous Quiz
22%
True
53%
False
11%
SyntaxError
14%
TypeError
🔥3
Вчера мы опубликовали задачу на внимательность, логику и знание работы функции
Код задачи:
Разбор задачи.
Давайте разберём эту задачу на внимательность.
В переменную
Перед каждым элементом стоит приставка
Разберём каждый элемент списка:
-
-
-
В итоге получаем в переменной
Затем при помощи функции
Функция
Поскольку в нашем списке есть один элемент, равный
any(). С задачей справилось 46% ответивших.Код задачи:
x = [not 1, not 'a', not 0 != 0]
print(not any(x))
Разбор задачи.
Давайте разберём эту задачу на внимательность.
В переменную
x помещаем список с тремя элементами - [not 1, not 'a', not 0 != 0].Перед каждым элементом стоит приставка
not, тем самым сообщая интерпретатору, что стоящее после неё значение стоит расценивать как булев тип (True или False). Разберём каждый элемент списка:
-
not 1 - Любое число, отличное от 0, расценивается как True, но поскольку у нас инверсия, получаем значение - False.-
not 'a' - Со строками ещё проще: любой символ, кроме непосредственно пустой строки (''), расценивается как True. В нашем случае 'а' в результате инверсии становится False.-
not 0 != 0 - Тут происходит проверка неравенства. Так как 0 равен 0, а мы проверяем обратное, получаем в ответ False, но затем инвертируем его в True.В итоге получаем в переменной
x следующий список: [False, False, True].Затем при помощи функции
print() выводим результат работы функции any(), также инвертировав ответ.Функция
any() возвращает True, если хотя бы один элемент переданной в функцию коллекции равен True, в противном случае возвращает False.Поскольку в нашем списке есть один элемент, равный
True, то и функция вернёт True. Однако из-за приставки not результат будет инвертирован, и в конечном выводе мы получим False.🔥3
Вчера была опубликована первая задача из рубрики "Найди ошибку". Она была рассчитана на внимательность.
Первым, кто назвал правильный ответ, был Артём Д.
Код задачи:
Ответ:
Ответ прост и банален. В строке
Также были вопросы к конструкции
Так же и с
Затем сравнение
Первым, кто назвал правильный ответ, был Артём Д.
Код задачи:
a = 1
b = 1
if a == (not b):
print('a не равно b")
else:
print("a равно b")
Ответ:
Ответ прост и банален. В строке
print('a не равно b") в качестве открывающей кавычки указана одинарная ', а в качестве закрывающей двойная ". В таком виде код работать не будет. Открывающая кавычка должна совпадать с закрывающей.Также были вопросы к конструкции
a == (not b), но и тут всё просто:not b - означает, что b рассцениваем как bool, а поскольку b = 1, то это True, после инвертирования получаем False.Так же и с
a, т.к. a = 1, значит это True. Затем сравнение
True == False? Так как они неравны, блок if не выполняется и на печать выводится функция print() из блока else - a равно b.🔥3👍2
Django 42. Запуск Django-проекта на VPS
Автор: Иван Ашихмин
Вот мы и добрались до запуска нашего проекта на сервере.
Этот пост – первый из двух, посвященных данной теме. В нём мы с вами подготовим Django для работы в Docker-контейнере и запустим его на VPS на встроенном веб-сервере. В следующем посте мы объединим Django, PostgreSQL, NGINX и Telegram-бота в одном Docker compose-сервисе.
Пост является частью серии постов "Сайт на Django", и всё происходящее будет демонстрироваться на примере того, что мы делали на протяжении 41-го поста. Кроме того, он будет частично дублировать пост "AIOgram3 17. Подготовка к разворачиванию на сервере" с поправкой на особенности Django.
Приступим.
Переменные окружения.
Автор: Иван Ашихмин
Вот мы и добрались до запуска нашего проекта на сервере.
Этот пост – первый из двух, посвященных данной теме. В нём мы с вами подготовим Django для работы в Docker-контейнере и запустим его на VPS на встроенном веб-сервере. В следующем посте мы объединим Django, PostgreSQL, NGINX и Telegram-бота в одном Docker compose-сервисе.
Пост является частью серии постов "Сайт на Django", и всё происходящее будет демонстрироваться на примере того, что мы делали на протяжении 41-го поста. Кроме того, он будет частично дублировать пост "AIOgram3 17. Подготовка к разворачиванию на сервере" с поправкой на особенности Django.
Приступим.
Переменные окружения.
🔥4
Переменные окружения позволят прописать значения, такие, как логин и пароль базы данных, секретный ключ или данные от почтового сервера, в специальном файле
Для того чтобы всё продолжало работать локально, установим библиотеку
Не забудьте добавить установленную библиотеку в файл
В корне проекта создадим файл
В самом начале файла
Для получения данных из переменных окружения мы воспользуемся методом
Нам необходимо заменить значения следующих переменных на указанную выше строку, сделав ключом имя переменной, а её текущее содержимое прописать в
-
-
-
-
-
-
-
-
-
Пример замены в
Обратите внимание на параметр
Пример
Обратите внимание на формат
Кроме того, необходимо изменить параметр
После того, как вынесли все важные данные из
Dockerfile.
Следующим шагом будет создание
Создайте файл
Разберём по порядку:
-
.env (dotenv). Таким образом можно собрать все важные данные в одном файле без необходимости прописывать их непосредственно в коде (хардкодить).Для того чтобы всё продолжало работать локально, установим библиотеку
python-dotenv, выполнив команду:pip install python-dotenv
Не забудьте добавить установленную библиотеку в файл
requirements.txt!В корне проекта создадим файл
.env и откроем файл settings.py в директории проекта.В самом начале файла
settings.py после импортов добавим вызов функции load_dotenv(). Это необходимо, чтобы данные из .env-файла подтягивались при локальном запуске. На сервере это не нужно.from dotenv import load_dotenv
load_dotenv()
Для получения данных из переменных окружения мы воспользуемся методом
.get('ключ') из функции environ() в пакете os – os.environ.get('ключ'), где ключ – это переменная в .env-файле.Нам необходимо заменить значения следующих переменных на указанную выше строку, сделав ключом имя переменной, а её текущее содержимое прописать в
.env-файле:-
SECRET_KEY.-
NAME.-
USER.-
PASSWORD.-
HOST.-
PORT.-
EMAIL_HOST.-
EMAIL_HOST_USER.-
EMAIL_HOST_PASSWORD.Пример замены в
settings.py:SECRET_KEY = os.environ.get('SECRET_KEY')
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ.get('DB_NAME'),
"USER": os.environ.get('DB_USER'),
"PASSWORD": os.environ.get('DB_PASSWORD'),
"HOST": os.environ.get('DB_HOST'),
"PORT": int(os.environ.get('DB_PORT')),
}
}
Обратите внимание на параметр
PORT. Он приведён к типу int, поскольку по умолчанию все данные из переменных окружения – строки.Пример
.env-файла:SECRET_KEY=abcde...
DB_NAME=db_name
DB_USER=db_user
DB_PASSWORD=db_password
DB_HOST=postgres
DB_PORT=5432
Обратите внимание на формат
имя_переменной=значение_переменной, без кавычек.Кроме того, необходимо изменить параметр
ALLOWED_HOSTS, прописав в него IP-адрес VPS, локальный адрес (127.0.0.1) и адрес домена, если он подключен к VPS. Должно быть примерно так:ALLOWED_HOSTS = ["127.0.0.1", "pressanybutton.ru", "0.0.0.0"]
# Вместо 0.0.0.0 пропишите IP-адрес вашего VPS.
После того, как вынесли все важные данные из
settings.py в .env, можете проверить, что всё работает как прежде, запустив проект локально.Dockerfile.
Следующим шагом будет создание
Dockerfile. Это специальный файл с набором инструкции по сборке Docker-образа.Создайте файл
Dockerfile без расширения со следующим содержимым:FROM python:3.11.4-buster
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /code
RUN pip install --upgrade pip
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
EXPOSE 8000
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Разберём по порядку:
-
FROM python:3.11.4-buster - В этой строке указываем на используемый при сборке базовый образ. В нашем случае это Python 3.11.4. Можно взять любую версию, включая 3.12, однако учитывайте совместимости библиотек! В нашем проекте используется Django 4.2.2, поэтому и используется Python 3.11.🔥5
-
-
-
-
-
-
-
-
-
.dockerignore файл.
По аналогии с файлом
В нашем случае не нужно, чтобы внутрь контейнера попал
В файле пропишем всего одну строку –
Копирование файлов на VPS.
Скопировать файлы проекта можно разными способами, например, воспользовавшись git (репозиторий на github или другом сервисе) или использовав SFTP.
Я воспользуюсь SFTP и программой для этого WinSCP для Windows. Для этого подойдут и другие программы, например, FileZilla, XFTP и прочие.
Опущу этот процесс, т.к. он индивидуален, и каждый сам выбирает способ доставки файлов проекта на сервер.
Сборка образа.
После того, как проект подготовлен и скопированы файлы, приступим к сборке образа.
Запуск Docker-контейнера состоит из двух этапов. Первый – сборка или использование готового образа. В нашем случае готового образа нет, поэтому его необходимо создать. Второй этап заключается в запуске контейнера с указанием параметров запуска и собранного контейнера.
Все дальнейшие действия будут производиться на VPS. Подключитесь к серверу по SSH и перейдите в директорию с проектом. Момент с подключением и работой с сервером я опущу. Если вам нужен гайд по работе с сервером, сообщите об этом в комментариях (Подписчики с Boosty имеют приоритет в просьбах на будущие посты 😉)
Для сборки образа в директории проекта выполним команду:
Разберём команду:
-
-
-
ENV PYTHONDONTWRITEBYTECODE=1 - Эта переменная окружения говорит Python не записывать файлы байт-кода (.pyc) на диск. Обычно Python автоматически компилирует исходные файлы .py в файлы байт-кода .pyc, чтобы ускорить последующий запуск программы. Однако в контейнерных окружениях это может быть нежелательно-
ENV PYTHONUNBUFFERED=1 - Эта переменная окружения отключает буферизацию вывода Python. По умолчанию Python буферизует ввод и вывод, чтобы улучшить производительность. Это значит, что вывод в терминал или лог-файлы может быть задержан до тех пор, пока буфер не заполнится. Установка этой переменной в 1 отключает буферизацию, что приводит к немедленному выводу всех данных. Это полезно в контейнерных приложениях.-
WORKDIR /code - В этой строке указываем, что рабочая директория с файлами проекта будет по пути /code относительно корневой директории файловой системы /.-
RUN pip install --upgrade pip - В этой строке выполняется команда обновления pip.-
COPY requirements.txt /code/ - В этой строке происходит копирование файла зависимостей в рабочую директорию внутри образа.-
RUN pip install -r requirements.txt - В этой строке происходит установка зависимостей в окружение Python внутри образа.-
COPY . /code/ - В этой строке копируем файлы проекта в рабочую директорию.-
EXPOSE 8000 - В этой строке указываем, что наш образ будет "вещать" на 8000-м порту.-
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] - В этой строке выполняем команду запуска веб-сервера Django, дополнительно указывая 0.0.0.0:8000, что позволяет веб-серверу вещать не только в пределах 127.0.0.1/localhost, но и быть доступным для других устройств в сети (сетевых интерфейсов)..dockerignore файл.
По аналогии с файлом
.gitignore, запрещающим добавление в индекс системы контроля версий нежелательных файлов, таких, как .env или файлов от IDE, для Docker есть такой же файл - .dockerignore.В нашем случае не нужно, чтобы внутрь контейнера попал
.env-файл, поэтому в корне проекта создадим .dockerignore-файл.В файле пропишем всего одну строку –
.env.Копирование файлов на VPS.
Скопировать файлы проекта можно разными способами, например, воспользовавшись git (репозиторий на github или другом сервисе) или использовав SFTP.
Я воспользуюсь SFTP и программой для этого WinSCP для Windows. Для этого подойдут и другие программы, например, FileZilla, XFTP и прочие.
Опущу этот процесс, т.к. он индивидуален, и каждый сам выбирает способ доставки файлов проекта на сервер.
Сборка образа.
После того, как проект подготовлен и скопированы файлы, приступим к сборке образа.
Запуск Docker-контейнера состоит из двух этапов. Первый – сборка или использование готового образа. В нашем случае готового образа нет, поэтому его необходимо создать. Второй этап заключается в запуске контейнера с указанием параметров запуска и собранного контейнера.
Все дальнейшие действия будут производиться на VPS. Подключитесь к серверу по SSH и перейдите в директорию с проектом. Момент с подключением и работой с сервером я опущу. Если вам нужен гайд по работе с сервером, сообщите об этом в комментариях (Подписчики с Boosty имеют приоритет в просьбах на будущие посты 😉)
Для сборки образа в директории проекта выполним команду:
sudo docker build -t project_image .
Разберём команду:
-
sudo docker - Вызываем Docker с правами администратора (root).-
build - Сообщаем, что нам нужно собрать образ.-
-t project_image - Присваиваем образу тег (имя), по которому будем обращаться к нему. Можно указать просто имя образа, а также дополнительно версию или другое обозначение, например, -t project_image:dev.🔥3