Код на салфетке
2.21K subscribers
747 photos
15 videos
2 files
790 links
Канал для тех, кому интересно программирование на Python и не только.

Сайт: https://pressanybutton.ru/
Чат: https://t.iss.one/+Li2vbxfWo0Q4ZDk6
Заметки автора: @writeanynotes

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
🔥3🌭1
Что выведет этот код? №23
🔥3
Судя по ответам, вчерашняя задача разделила голосующих по вариантам, если не поровну, то хотя бы близко к этому. Давайте разберём верный ответ.

Код задачи:
x = 0.1
y = 0.10000000000000001
z = round(y, 1)

print(x is y, x == z, z == y, z is x)



Разбор задачи.
Задача похожа на некоторые, которые мы задавали ранее, но в этой есть хитрость (в прочем, как и в других).

Разборы прошлых похожих задач:
№15 - https://t.iss.one/press_any_button/591
№17 - https://t.iss.one/press_any_button/613

Вся суть в значении переменных x и y.
Казалось бы, значение x = 0.1 и y = 0.10000000000000001 - разные числа, следовательно и храниться должны в разных ячейках памяти, но нет.
Всё дело в работе Python с float-числами (числа с плавающей запятой, вещественные числа).
Для питона 0.00...001 - погрешность, которую он предпочитает игнорировать, в следствии чего, значение y считает как 0.1 и даёт ссылку на тот же участок памяти, что и x.

Именно по этому x is y = True, как и z == y = True .

Что касается последнего z is x, то тут именно то, что и должно быть. После применения функции round(), число помещается в новую ячейку памяти.

Всё это можно проверить, выведя значение функции id() по отношению к переменной:
x = 0.1  
y = 0.10000000000000001
z = round(y, 1)

print(x is y, x == z, z == y, z is x)
print(x, y, z)
print(id(x), id(y), id(z))

>>> True True True False
>>> 0.1 0.1 0.1
>>> 2078346127888 2078346127888 2078346131408
🔥4👍1
Всем привет!

Близится лето и с каждым днём всё больше становится конференций, митапов и прочих мероприятий IT-мира.

Об одном из них я хотел бы рассказать вам - Yandex Pytup.

Где: Нижний Новгород и Онлайн
Когда: 01.06.2024
Страница регистрации: https://yandex.ru/pytup

Конференция по Python от Яндекс. На мероприятии будет несколько интересных докладов, например, создание RAG-приложений, про GIL и другие.

Я уже записался в онлайн, будет очень интересно посмотреть и послушать.

Хотел бы рассказывать о подобных мероприятиях, если вам будет интересно - пишите в комментарии!

P.S. Это не реклама ( нам не заплатили🙁 )
🔥8
Приветствую!

В длинных постах можно запутаться поэтому, собираю воедино всё, что есть на данный момент.


Оглавления:
Для удобства навигации есть посты с оглавлениями по темам:

"Сайт на Django"
"Telegram-бот на AIOgram3"
"Применение Docker"
"Полезные инструменты"
"Путь в IT."
"Код в мешке"
"Boosty эксклюзив"


Ресурсы канала:

Уютный и немного безумный чат канала.
Бот с материалами к постам
Сайт со всеми постами
Канал в Dzen
Сообщество в VK


Поддержка.

Если вам нравится канал и выходящий материал, поделитесь ссылкой с людьми, кому это тоже может быть интересно.

Также поддержать канал можно:
Подпиской или донатом на Boosty.

Донатом в нашем Telegram-боте.

Или внеся сайт в исключения вашего блокировщика рекламы.
🔥32👍2
Первый фриланс проект - школа паралимпийского резерва
Автор: Иван Ашихмин

Всем привет!

Вчера закончилась работа по проекту для Хабаровской краевой спортивно-адаптивной школы паралимпийского и сурдлимпийского резерва. Проект длился почти год - с июня 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. Она позволяет создавать древовидные категории. Сложностей было несколько:
🔥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, но без дополнительных выпадающих списков. Теперь в меню указаны только нужные разделы, а не все существующие.
🔥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 #Фриланс #КСКИ #Заказ
🔥8👍1
Docker ушёл из РФ! Как это исправить?
Автор: Иван Ашихмин

Сегодня утром многие были удивлены новостью о том, что Docker заблокировал свой главный репозиторий Docker Hub для ряда стран, включая и Россию. Новость, конечно, неприятная, но вполне ожидаемая. Давайте разберёмся как это исправить.

Docker Hub - это основной источник образов. При сборке контейнера, Docker в первую очередь обращается туда, однако, путь туда нам закрыт. Однако, Docker не ограничивается только основным репозиторием. Docker позволяет делать собственные репозитории. Помимо этого, есть и сторонние "зеркала". Ими мы и воспользуемся.

В данный момент под запрет попадают пользователи из России использующие Docker Desktop, но, вероятно, позже будет затронут и Docker Engine, работающий на VPS и серверах.


Решение проблемы для Docker Desktop.
Для решения проблемы необходимо прописать дополнительные зеркала в конфигурационный файл.
🔥7🤔1
Откройте приложение Docker Desktop и перейдите в настройки. В нём выбираем Docker Engine.

В окне будет редактор с предзаписанной конфигурацией в виде 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, которую скинули в наш чат "Кот на салфетке", заметил благодаря Юрию. Спасибо ему за это! Однако, далеко не вся интересная и важная информация доходит до нас через привычные каналы.

Поэтому хочу обратиться к вам. Если у вас есть интересные новости или важные обновления, которые вы считаете стоящими нашего внимания, пожалуйста, делитесь ими в чате канала или пишите мне в личные сообщения (ссылка в описании канала).

Вместе мы сможем быть в курсе всех актуальных событий!

Пост на сайте
Поддержать проект

#код_на_салфетке #Новости #обновления #чат
🔥5👍1
Приветствую!

С 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/

Желаю вам приятного просмотра и незабываемого вечера!
🔥4
Обновление библиотеки - AIOgram 3.7.0
Автор: Иван Ашихмин

Вышла новая версия 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
Что выведет этот код? №24
🔥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