Приветствую вас, дорогие участники!
Очередная неделя пролетела как МКС вокруг земного шара. Вечер пятницы... Что может быть прекрасней, чем когда наконец можно отложить все дела до понедельника? Ну или хотя бы на пару часов. Ведь именно такая длительность нашего следующего фильма. Заваривайте чаёк и устраивайтесь поудобнее. Погнали!
Фильм: Мятежная Луна, часть 1
Год: 2022
Перевод: Профессиональный, многоголосый
Жестокий тиран угрожает жителям мирной колонии на краю галактики, и их единственной надеждой становится таинственная незнакомка.
Ставьте реакции и делитесь своим мнением. Приятного просмотра
https://www.sspoisk.ru/film/4538172/?utm_referrer=www.google.com
Очередная неделя пролетела как МКС вокруг земного шара. Вечер пятницы... Что может быть прекрасней, чем когда наконец можно отложить все дела до понедельника? Ну или хотя бы на пару часов. Ведь именно такая длительность нашего следующего фильма. Заваривайте чаёк и устраивайтесь поудобнее. Погнали!
Фильм: Мятежная Луна, часть 1
Год: 2022
Перевод: Профессиональный, многоголосый
Жестокий тиран угрожает жителям мирной колонии на краю галактики, и их единственной надеждой становится таинственная незнакомка.
Ставьте реакции и делитесь своим мнением. Приятного просмотра
https://www.sspoisk.ru/film/4538172/?utm_referrer=www.google.com
🔥3
🎅Новогоднее поздравление
Авторы: Иван Ашихмин, Андрей Лебедев
Приветствую.
Вот и закончился 2023 год. Для меня это выдался непростой год. Много учёбы, какие-то проекты, дела, вписывался практически во всё и изрядно так устал) В следующем году пора бы заняться контролем времени, защитить диплом в GB, успешно пройти стажировку и наконец-то начать искать работу)
Хочу пожелать Вам в новом году успехов в учёбе, побольше перспективных проектов, найти или сменить работу на более интересную и конечно же здоровья (особенно ментального, выгорание штука такая, неприятная). И самое главное - не говнокодьте! Пишите красивый, эффективно работающий код и всё будет хорошо!)
Хочу передать слово коллегам:
Андрей Лебедев:
Авторы: Иван Ашихмин, Андрей Лебедев
Приветствую.
Вот и закончился 2023 год. Для меня это выдался непростой год. Много учёбы, какие-то проекты, дела, вписывался практически во всё и изрядно так устал) В следующем году пора бы заняться контролем времени, защитить диплом в GB, успешно пройти стажировку и наконец-то начать искать работу)
Хочу пожелать Вам в новом году успехов в учёбе, побольше перспективных проектов, найти или сменить работу на более интересную и конечно же здоровья (особенно ментального, выгорание штука такая, неприятная). И самое главное - не говнокодьте! Пишите красивый, эффективно работающий код и всё будет хорошо!)
Хочу передать слово коллегам:
Андрей Лебедев:
🔥5❤2
Не знаю, получилось ли у меня в этом году освоить новые знания и стать лучше как разработчик. Иногда кажется, что я забыл больше, чем узнал. Но в этом году я присоединился к замечательной команде канала «Код на салфетке», а также к проекту, который был инициирован моими друзьями. Я благодарен им за эти возможности и за неповторимую атмосферу на канале и во всех связанных с ним чатиках.
Всем нашим читателям и единомышленникам хочу пожелать в новом году приблизиться к достижению своих целей. И помните: как бы сложно ни было, вы не одни. Рядом есть люди, готовые помочь. Нужно только попросить.
Артур Мурзыев:
С Новым Годом, дорогие подписчики! Желаю вам процветания, всех благ в любых аспектах вашей жизни и успехов во всех делах!
Напишите в комментариях как прошёл год для Вас и какие планы на новый 2024 год!
Пост на сайте
Поддержать проект
#Код_на_салфетке #новый_год #поздравление
Всем нашим читателям и единомышленникам хочу пожелать в новом году приблизиться к достижению своих целей. И помните: как бы сложно ни было, вы не одни. Рядом есть люди, готовые помочь. Нужно только попросить.
Артур Мурзыев:
С Новым Годом, дорогие подписчики! Желаю вам процветания, всех благ в любых аспектах вашей жизни и успехов во всех делах!
Напишите в комментариях как прошёл год для Вас и какие планы на новый 2024 год!
Пост на сайте
Поддержать проект
#Код_на_салфетке #новый_год #поздравление
❤4🔥4👍1
Статистика сайта за месяц 04.12-04.01
Автор: Иван Ашихмин
Прошёл ещё месяц и даже сменился год! Что же у нас по статистике сайта?
Статистика продолжает расти! Хотя и была просадка перед новым годом. Доля поисковых запросов растёт, что не может не радовать (всё ещё ищу того, кто поможет с SEO 😭). На втором месте практически нога в ногу идут переходы из Dzen и прямые переходы на сайт по домену. Четвёртое и пятое место делят внутренние переходы и переходы из паблика в VK.
В сухом итоге:
- Посетители: Было 785, стало 1040. Прирост 32.48%.
- Переходы из Dzen: Было 13.1%, стало 8.69%. Падение 33.66%.
- Переходы из Telegram-канала: Было 18%, ушли из топа.
- Переходы из поиска: Было 58.3%, стало 69.4%. Прирост 19.03%.
- Переходы из VK сообщества: Было 0%, стало 3.06%.
Автор: Иван Ашихмин
Прошёл ещё месяц и даже сменился год! Что же у нас по статистике сайта?
Статистика продолжает расти! Хотя и была просадка перед новым годом. Доля поисковых запросов растёт, что не может не радовать (всё ещё ищу того, кто поможет с SEO 😭). На втором месте практически нога в ногу идут переходы из Dzen и прямые переходы на сайт по домену. Четвёртое и пятое место делят внутренние переходы и переходы из паблика в VK.
В сухом итоге:
- Посетители: Было 785, стало 1040. Прирост 32.48%.
- Переходы из Dzen: Было 13.1%, стало 8.69%. Падение 33.66%.
- Переходы из Telegram-канала: Было 18%, ушли из топа.
- Переходы из поиска: Было 58.3%, стало 69.4%. Прирост 19.03%.
- Переходы из VK сообщества: Было 0%, стало 3.06%.
🔥5
Приветствую, друзья!
Вижу, что все живы после новогоднего празднества))
Бывает так, что можно устать просто отдыхая. В голове пустота, а в какой-то момент и вовсе становится скучно. И чтобы скрасить ваш холодный зимний вечер, я иду к вам с фильмом, как Дед Мороз с конфетами)
Не нужны ни стишки, ни песни. Просто расслабьтесь и наслаждайтесь просмотром)
Фильм: Скотт Пилигрим против всех
Год: 2010
Скотт Пилигрим нашел девушку своей мечты. Но на его пути стоит более сложная задача: чтобы встречаться с ней, Скотту придется победить ее семерых бывших и очень злых парней
Приятного просмотра)
https://www.sspoisk.ru/film/105948/?utm_referrer=www.google.com
Вижу, что все живы после новогоднего празднества))
Бывает так, что можно устать просто отдыхая. В голове пустота, а в какой-то момент и вовсе становится скучно. И чтобы скрасить ваш холодный зимний вечер, я иду к вам с фильмом, как Дед Мороз с конфетами)
Не нужны ни стишки, ни песни. Просто расслабьтесь и наслаждайтесь просмотром)
Фильм: Скотт Пилигрим против всех
Год: 2010
Скотт Пилигрим нашел девушку своей мечты. Но на его пути стоит более сложная задача: чтобы встречаться с ней, Скотту придется победить ее семерых бывших и очень злых парней
Приятного просмотра)
https://www.sspoisk.ru/film/105948/?utm_referrer=www.google.com
🔥2
Django 39. Капча и подтверждение регистрации по email
Автор: Иван Ашихмин
Когда мы с вами работали над формой регистрации, мы упустили одну важную деталь – ботов. Если ничего не предпринимать, боты будут регистрироваться на сайте в большом количестве, нагружая базу данных заведомо неактуальной информацией, плодя спам в комментариях под постами и доставляя немало других мелких и не очень неприятностей.
Для решения этой проблемы мы сделаем следующее:
1. Добавим на страницу регистрации Google reCAPTCHA, для явной защиты от ботов и массовых регистраций. Да, это не самая лучшая защита от ботов, но 99% всё же будут отсеяны.
2. Добавим обязательное подтверждение регистрации по email. Этим мы отсеем оставшихся ботов.
Google reCAPTCHA.
Для того, чтобы у нас был доступ к сервису reCAPTCHA, необходимо получить ключи доступа.
Автор: Иван Ашихмин
Когда мы с вами работали над формой регистрации, мы упустили одну важную деталь – ботов. Если ничего не предпринимать, боты будут регистрироваться на сайте в большом количестве, нагружая базу данных заведомо неактуальной информацией, плодя спам в комментариях под постами и доставляя немало других мелких и не очень неприятностей.
Для решения этой проблемы мы сделаем следующее:
1. Добавим на страницу регистрации Google reCAPTCHA, для явной защиты от ботов и массовых регистраций. Да, это не самая лучшая защита от ботов, но 99% всё же будут отсеяны.
2. Добавим обязательное подтверждение регистрации по email. Этим мы отсеем оставшихся ботов.
Google reCAPTCHA.
Для того, чтобы у нас был доступ к сервису reCAPTCHA, необходимо получить ключи доступа.
Откроем сайт и авторизуемся: https://www.google.com/recaptcha/admin/
Выбираем "Создать" и заполняем три поля:
- Ярлык - вводим название сайта.
- Тип reCAPTCHA - выбираем "С помощью заданий (v2)".
- Домены - вводим домен без
Нажимаем кнопку "Отправить". Откроется страница с ключами доступа, не закрывайте её, далее они нам понадобятся.
Django reCAPTCHA.
Для добавления капчи на страницу регистрации мы воспользуемся готовой библиотекой
Установим библиотеку, выполнив команду:
Также добавим
Откроем файл
Там же создадим два параметра настроек:
-
-
Добавляем поле в форму.
Откроем файл
Добавим в него всего одно поле:
Этого достаточно. Теперь, открыв страницу регистрации, мы увидим новое поле с капчей.
Если вам нужны расширенные настройки, то документация к библиотеке доступна по ссылке: https://github.com/django-recaptcha/django-recaptcha
Подтверждение регистрации по email.
Для реализации отправки письма с подтверждением регистрации нам потребуется:
- Написать класс отправки письма. Это же будет заготовкой для внедрения фоновой отправки писем используя Celery.
- Изменить наш класс представления для регистрации и добавить два новых.
- Сделать три простых шаблона.
Обратите внимание, что для работы отправки почты необходимо прописать почтовый сервер в файле
Класс отправки почты.
Начнём с класса, реализующего методы для отправки почты. Это также будет являться заготовкой для внедрения Celery, позволяющего выполнять задачи в фоне, но об этом в другой раз.
В директории приложения
Создадим класс
Первым методом будет конструктор класса
В нём будет четыре поля:
-
-
-
-
Вторым методом будет
В нём создадим три переменные:
Выбираем "Создать" и заполняем три поля:
- Ярлык - вводим название сайта.
- Тип reCAPTCHA - выбираем "С помощью заданий (v2)".
- Домены - вводим домен без
https или www.Нажимаем кнопку "Отправить". Откроется страница с ключами доступа, не закрывайте её, далее они нам понадобятся.
Django reCAPTCHA.
Для добавления капчи на страницу регистрации мы воспользуемся готовой библиотекой
Django reCAPTCHA.Установим библиотеку, выполнив команду:
pip install django-recaptcha
Также добавим
django-recaptcha4.0.0 в requirements.txt.Откроем файл
settings.py и добавим django_recaptcha в INSTALLED_APPS.Там же создадим два параметра настроек:
-
RECAPTCHA_PUBLIC_KEY - в этом параметре указываем первый полученный на сайте ключ "Ключ сайта".-
RECAPTCHA_PRIVATE_KEY - в этом параметре указываем второй полученный на сайте ключ "Секретный ключ".RECAPTCHA_PUBLIC_KEY = ""
RECAPTCHA_PRIVATE_KEY = ""
Добавляем поле в форму.
Откроем файл
forms.py в директории приложения user_app и найдём наш класс RegistrationForm.Добавим в него всего одно поле:
from django_recaptcha.fields import ReCaptchaField
captcha = ReCaptchaField()
Этого достаточно. Теперь, открыв страницу регистрации, мы увидим новое поле с капчей.
Если вам нужны расширенные настройки, то документация к библиотеке доступна по ссылке: https://github.com/django-recaptcha/django-recaptcha
Подтверждение регистрации по email.
Для реализации отправки письма с подтверждением регистрации нам потребуется:
- Написать класс отправки письма. Это же будет заготовкой для внедрения фоновой отправки писем используя Celery.
- Изменить наш класс представления для регистрации и добавить два новых.
- Сделать три простых шаблона.
Обратите внимание, что для работы отправки почты необходимо прописать почтовый сервер в файле
settings.py. Подробнее об этом можно прочитать в посте "Django 12. Настройка отправки почты"Класс отправки почты.
Начнём с класса, реализующего методы для отправки почты. Это также будет являться заготовкой для внедрения Celery, позволяющего выполнять задачи в фоне, но об этом в другой раз.
В директории приложения
user_app создадим новый файл tasks.py.Создадим класс
SendEmail.Первым методом будет конструктор класса
__init__, принимающий аргумент user.В нём будет четыре поля:
-
self.user - в него помещаем переданный в конструктор аргумент user. Это объект пользователя.-
self.current_site - в него из класса Sites получаем домен сайта.-
self.token - используя функцию default_token_generator и метод make_token, на основе пользователя создаём токен.-
self.uid - в этом поле мы кодируем числовое значение id пользователя в base64.class SendEmail:
def __init__(self, user: User):
self.user = user
self.current_site = Site.objects.get_current().domain
self.token = default_token_generator.make_token(self.user)
self.uid = urlsafe_base64_encode(str(self.user.pk).encode())
Вторым методом будет
send_activate_email.В нём создадим три переменные:
👍2
-
-
-
Ниже, обращаясь ко встроенному в класс пользователя методу
Полный код класса:
Под классом создаём функцию
Именно эту функцию будем вызывать из представления для отправки почты, а в будущем она будет выполняться как задача Celery.
В функции в переменную
Следующей строчкой вызываем метод
Изменение представления регистрации.
Откроем файл
В нём нам необходимо изменить метод
Изначально он был такой:
В этом методе, сохраняем зарегистрированного пользователя.
Теперь же нам необходимо его доработать, а именно:
- В модели пользователя есть поле
- Вызвать функцию отправки почты, передав в неё объект зарегистрированного пользователя.
reset_password_url - в ней, используя функцию reverse_lazy, получаем путь для активации, передавая uid и token.-
subject - в ней создаём строку с текстом для темы письма.-
message - в ней создаём строку с телом письма. Позволяется использовать HTML-разметку, также используя функцию render_to_string, можно создать HTML-файл с шаблоном письма и отправлять его.Ниже, обращаясь ко встроенному в класс пользователя методу
email_user, отправляем ему письмо, которое передаёт в него тему и сообщение.def send_activate_email(self):
reset_password_url = reverse_lazy(
"user_app:signup_confirm", kwargs={"uidb64": self.uid, "token": self.token}
)
subject = f"Активация аккаунта на сайте {self.current_site}"
message = (
f"Благодарим за регистрацию на сайте {self.current_site}.\n"
"Для активации учётной записи, пожалуйста перейдите по ссылке:\n"
f"https://{self.current_site}{reset_password_url}\n"
)
self.user.email_user(subject=subject, message=message)
Полный код класса:
from django.contrib.auth.models import User
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.models import Site
from django.urls import reverse_lazy
from django.utils.http import urlsafe_base64_encode
class SendEmail:
def __init__(self, user: User):
self.user = user
self.current_site = Site.objects.get_current().domain
self.token = default_token_generator.make_token(self.user)
self.uid = urlsafe_base64_encode(str(self.user.pk).encode())
def send_activate_email(self):
reset_password_url = reverse_lazy(
"user_app:signup_confirm", kwargs={"uidb64": self.uid, "token": self.token}
)
subject = f"Активация аккаунта на сайте {self.current_site}"
message = (
f"Благодарим за регистрацию на сайте {self.current_site}.\n"
"Для активации учётной записи, пожалуйста перейдите по ссылке:\n"
f"https://{self.current_site}{reset_password_url}\n"
)
self.user.email_user(subject=subject, message=message)
Под классом создаём функцию
activate_email_task, принимающую пользователя в аргументах.Именно эту функцию будем вызывать из представления для отправки почты, а в будущем она будет выполняться как задача Celery.
В функции в переменную
send_email помещаем экземпляр класса SendEmail.Следующей строчкой вызываем метод
send_activate_email.def activate_email_task(user: User):
send_email = SendEmail(user=user)
send_email.send_activate_email()
Изменение представления регистрации.
Откроем файл
views.py в директории приложения user_app и найдём наш класс для регистрации CustomRegistrationView.В нём нам необходимо изменить метод
form_valid.Изначально он был такой:
def form_valid(self, form):
form.save()
return super().form_valid(form)
В этом методе, сохраняем зарегистрированного пользователя.
Теперь же нам необходимо его доработать, а именно:
- В модели пользователя есть поле
is_active, определяющее активирован/активен пользователь или нет. По умолчанию он установлен в True, нам необходимо после регистрации присваивать False.- Вызвать функцию отправки почты, передав в неё объект зарегистрированного пользователя.
И тут проявляется забавная особенность. Если оставить
1. Регистрация пользователя - первое время изменения.
2. Деактивация пользователя и сохранение - второе время изменения.
3. Отправка письма с токеном на основе времени изменения из пункта 2.
4. Вызов
Проще говоря, пользователю приходит невалидная ссылка для активации аккаунта. Это решается изменением последнего шага на
Код метода:
Также необходимо изменить метод
Представление страницы активации и завершения регистрации.
Сделаем два представления:
1. На первое будем перенаправлять после регистрации. Оно будет просто выводить страницу с текстом, не более.
2. На второе пользователь будет попадать перейдя по ссылке из письма. В нём будет логика валидации токена и активации пользователя.
Начнём с первого представления. Создадим класс
В нём пропишем два поля:
1.
2.
Код представления:
Второе представление будет объёмнее. Создадим класс
В классе создаём метод
В начале идёт блок
Если декодировать не удастся или пользователь с таким
Далее блок
Если условие выполняется:
- Активируем пользователя, установив значение
- Сохраняем пользователя.
- Используя функцию
- Возвращаем работу функции
Если условие не было выполнено:
- Возвращаем работу функции
Код представления:
return super().form_valid(form) в конце метода, то активация работать не будет. Оказывается, генерация токена берёт за основу время изменения пользователя и получается следующая последовательность:1. Регистрация пользователя - первое время изменения.
2. Деактивация пользователя и сохранение - второе время изменения.
3. Отправка письма с токеном на основе времени изменения из пункта 2.
4. Вызов
super().form_valid(form), который в свою очередь тоже сохраняет объект - третье время изменения.Проще говоря, пользователю приходит невалидная ссылка для активации аккаунта. Это решается изменением последнего шага на
return HttpResponseRedirect(self.get_success_url()).Код метода:
def form_valid(self, form):
user: User = form.save()
user.is_active = False
user.save()
activate_email_task(user)
return HttpResponseRedirect(self.get_success_url())
Также необходимо изменить метод
get_success_url, а именно изменить маршрут на страницу после регистрации с сообщением об отправке почты.def get_success_url(self):
return reverse_lazy("user_app:signup_done")
Представление страницы активации и завершения регистрации.
Сделаем два представления:
1. На первое будем перенаправлять после регистрации. Оно будет просто выводить страницу с текстом, не более.
2. На второе пользователь будет попадать перейдя по ссылке из письма. В нём будет логика валидации токена и активации пользователя.
Начнём с первого представления. Создадим класс
CustomRegistrationDoneView, унаследованный от TemplateView.В нём пропишем два поля:
1.
template_name - файл шаблона страницы.2.
extra_context - заголовок страницы.Код представления:
class CustomRegistrationDoneView(TemplateView):
template_name = "user_app/signup_done.html"
extra_context = {"title": "Регистрация завершена, активируйте учётную запись."}
Второе представление будет объёмнее. Создадим класс
CustomRegistrationConfirmView, унаследованный от базового класса View.В классе создаём метод
get, принимающий в агрументах request, uidb64, token.В начале идёт блок
try-except, в котором мы декодируем uidb64 в int и получаем соответствующего пользователя в переменную user.Если декодировать не удастся или пользователь с таким
id не будет найден, то поднимется исключение, в обработке которого в переменную user присваиваем None.Далее блок
if-else. В условии проверяем, что user не является None и, что токен соответствует пользователю. Если условие выполняется:
- Активируем пользователя, установив значение
is_active, равное True.- Сохраняем пользователя.
- Используя функцию
login, авторизуем пользователя, передавая в функцию request и user.- Возвращаем работу функции
render, передав в неё request, путь до шаблона, уведомляющего об успешной активации, и контекст, содержащий заголовок страницы.Если условие не было выполнено:
- Возвращаем работу функции
render, передав в неё request, путь до шаблона, уведомляющего об ошибке активации, и контекст, содержащий заголовок страницы.Код представления:
class CustomRegistrationConfirmView(View):
def get(self, request, uidb64, token):
try:
uid = urlsafe_base64_decode(uidb64)
user = User.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
if user is not None and default_token_generator.check_token(user, token):
user.is_active = True
user.save()
login(request, user)
return render(
request,
"user_app/signup_confirmed.html",
{"title": "Учётная запись активирована."},
)
else:
return render(
request,
"user_app/signup_not_confirmed.html",
{"title": "Ошибка активации учётной записи."},
)
URL-маршруты.
Добавим для наших представлений соответствующие им маршруты в файл
urls.py:path("signup/", views.CustomRegistrationView.as_view(), name="signup"),
path(
"signup_done/", views.CustomRegistrationDoneView.as_view(), name="signup_done"
),
path(
"signup_confirm/<uidb64>/<token>/",
views.CustomRegistrationConfirmView.as_view(),
name="signup_confirm",
),Шаблоны представлений.
У нас два представления, использующих три шаблона. Откройте директорию с шаблонами приложения
user_app и создайте три файла:-
signup_done.html - страница с уведомлением, что письмо было отправлено.-
signup_confirmed.html - страница успешного подтверждения почты.-
signup_not_confirmed.html - страницы ошибки при подтверждении.signup_done.html
{% extends "blog/base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="container mt-3 justify-content-center d-flex">
<div class="col-lg-4 col-sm-12">
<h2>Регистрация завершена.</h2>
<p>Для активации учётной записи необходимо подтвердить вашу электронную почту.</p>
<p>Письмо со ссылкой для активации уже отправлено.</p>
</div>
</div>
{% endblock %}signup_confirmed.html
{% extends "blog/base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="container mt-3 justify-content-center d-flex">
<div class="col-lg-4 col-sm-12">
<h2>Учётная запись активирована.</h2>
<p>Ваша электронная почта была подтверждена успешно.</p>
<a href="{% url "user_app:user_profile" username=user.username %}" class="btn btn-primary my-btn mb-3">
Перейти в личный кабинет
</a>
</div>
</div>
{% endblock %}signup_not_confirmed.html
{% extends "blog/base.html" %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="container mt-3 justify-content-center d-flex">
<div class="col-lg-4 col-sm-12">
<h2>Ошибка активации учётной записи.</h2>
<p>Произошла ошибка при активации вашей учётной записи.</p>
<p> Пожалуйста, убедитесь, что вы переходите по корректной ссылке из письма.</p>
</div>
</div>
{% endblock %}🔥3
Они все похожи, и, по сути, можно обойтись одним шаблоном, передавая в него необходимый текст.
Заключение.
Теперь нам не страшны боты, регистрирующиеся на сайте и без какой-либо пользы раздувающие базу.
В одном из следующих постов мы добавим фоновую отправку электронной почты, используя Celery. Кроме того, я бы хотел реализовать удаление неактивированных учётных записей, скажем, раз в неделю.
Файлы к посту, можно получить в боте по коду: 256843
Пост на сайте
Поддержать проект
#Python #Django #Гайды #email #представления #капча #reCAPTCHA
Заключение.
Теперь нам не страшны боты, регистрирующиеся на сайте и без какой-либо пользы раздувающие базу.
В одном из следующих постов мы добавим фоновую отправку электронной почты, используя Celery. Кроме того, я бы хотел реализовать удаление неактивированных учётных записей, скажем, раз в неделю.
Файлы к посту, можно получить в боте по коду: 256843
Пост на сайте
Поддержать проект
#Python #Django #Гайды #email #представления #капча #reCAPTCHA
🔥5
Второй месяц стажировки в LAD Academy
Автор: Иван Ашихмин
Второй месяц пролетел быстро, а вот стажировка идёт не очень активно.
В прошлом посте "Начало работ", посвящённом первому месяцу, мы определились с первоначальными задачами:
1. Создание "основы":
1.1. Создание Django-проекта.
1.2. Создание модели пользователя и его менеджера.
1.3. Расписать правила работы в git.
2. Реализовать:
2.1. Регистрацию.
2.2. Авторизацию.
2.3. Логаут.
2.4. Сброс пароля.
Первую задачу взял на себя наш лид. Через несколько дней всё было готово.
Далее последовали обсуждения модели пользователя: какие поля нужны и как менеджер создаёт нового пользователя. В процессе лиду пришлось вносить правки в код.
Автор: Иван Ашихмин
Второй месяц пролетел быстро, а вот стажировка идёт не очень активно.
В прошлом посте "Начало работ", посвящённом первому месяцу, мы определились с первоначальными задачами:
1. Создание "основы":
1.1. Создание Django-проекта.
1.2. Создание модели пользователя и его менеджера.
1.3. Расписать правила работы в git.
2. Реализовать:
2.1. Регистрацию.
2.2. Авторизацию.
2.3. Логаут.
2.4. Сброс пароля.
Первую задачу взял на себя наш лид. Через несколько дней всё было готово.
Далее последовали обсуждения модели пользователя: какие поля нужны и как менеджер создаёт нового пользователя. В процессе лиду пришлось вносить правки в код.
🔥2
Когда с основой разобрались, на очередном созвоне оставшиеся задачи были распределены между всеми участниками команды, после чего мы начали работу.
Мне досталось две совсем небольшие задачи: авторизация и сериализатор регистрации. Справился я с ними достаточно быстро. Авторизация и вовсе заняла несколько строк кода, поскольку мы используем готовую библиотеку для генерации JWT.
К тому моменту, как я закончил сериализатор, представление для регистрации другой участник ещё не сделал, но как-то проверить его работу было необходимо. Тогда я решил попрактиковаться с Unit-тестами. Написал покрывающий тест для сериализатора, а затем для авторизации и логаута.
В процессе тестирования снова обнаружились недочёты и после обсуждений они были исправлены.
Остальные участники взяли на себя оставшиеся задачи. Какие-то были просты в написании, а какие-то весьма комплексны. Так, например, один из участников занимавшихся сбросом пароля, выполнил свою задачу и дополнительно добавил Celery для отправки электронной почты.
Примерно в середине месяца внезапно для всех нас покинул один из членов команды. Как нам позже сообщили, человек решил сосредоточиться на собственных проектах. Таким образом, нас осталось пять бэкэндеров.
Завершив выполнение задач, мы немного "впали в спячку". Ждали того, что решат продакты по дальнейшему развитию проекта. В итоге они решили подробно изучить тему, а мы получили "карт бланш".
Нам было поручено провести ряд исследований. Цель – изучить конкурентов и их устройство для дальнейшего планирования разработки.
Было несколько исследований, которые мы распределили среди членов команды. Я попросил закрепить за мной интересующую меня тему - "Возможность подключения различных интерпретаторов/компиляторов для выполнения пользовательского кода". Интересна она мне по той причине, что я на своём сайте также планирую однажды ввести что-то вроде "песочницы" для кода или тесты, связанные с кодом, но это пока только планы.
Этой задачей занялись мы с лидом. Сперва мы довольно долго обсуждали варианты запуска хотя бы кода на Python. Основная сложность состояла не в самом факте запуска, т.к. можно установить интерпретаторы с компиляторами и вызывать их. Проблема заключается в безопасности: пользовательский код необходимо запускать изолированно, дабы он не мог причинить вреда рабочему окружению.
Конечно же, в итоге мы решили использовать Docker-контейнеры с различными языками программирования. Изучив вопрос, мы договорились поискать готовые решения. Их оказалось не то чтобы много. Главный критерий, которым мы руководствовались при выборе, – возможность развернуть сервис на собственных серверах. Таких готовых решений оказалось ещё меньше.
В итоге был составлен документ, описывающий плюсы и минусы найденых решений. Лид выбрал то, которое мы будем использовать в проекте, и отправился к руководству узнавать про возможность развёртывания на серверах.
На этом закончился 2023 год, и мы ушли на "новогодние каникулы". Конечно, другие команды не сидели всё это время сложа руки. Аналитики с техписами активно составляли документацию, а дизайнеры готовили макеты для фронтов.
Вот так прошёл второй месяц. Небыстро, но достаточно интересно. В чате команды часто происходят обсуждения, в которых рождается истина. На созвонах очень дружелюбная и открытая атмосфера.
На январь у нас большие планы и наверняка будет много работы, но об этом в следующий раз.
Пост на сайте
Поддержать проект
#Django #Стажировка #LAD_Academy #Backend #LAD #Код_на_салфетке
Мне досталось две совсем небольшие задачи: авторизация и сериализатор регистрации. Справился я с ними достаточно быстро. Авторизация и вовсе заняла несколько строк кода, поскольку мы используем готовую библиотеку для генерации JWT.
К тому моменту, как я закончил сериализатор, представление для регистрации другой участник ещё не сделал, но как-то проверить его работу было необходимо. Тогда я решил попрактиковаться с Unit-тестами. Написал покрывающий тест для сериализатора, а затем для авторизации и логаута.
В процессе тестирования снова обнаружились недочёты и после обсуждений они были исправлены.
Остальные участники взяли на себя оставшиеся задачи. Какие-то были просты в написании, а какие-то весьма комплексны. Так, например, один из участников занимавшихся сбросом пароля, выполнил свою задачу и дополнительно добавил Celery для отправки электронной почты.
Примерно в середине месяца внезапно для всех нас покинул один из членов команды. Как нам позже сообщили, человек решил сосредоточиться на собственных проектах. Таким образом, нас осталось пять бэкэндеров.
Завершив выполнение задач, мы немного "впали в спячку". Ждали того, что решат продакты по дальнейшему развитию проекта. В итоге они решили подробно изучить тему, а мы получили "карт бланш".
Нам было поручено провести ряд исследований. Цель – изучить конкурентов и их устройство для дальнейшего планирования разработки.
Было несколько исследований, которые мы распределили среди членов команды. Я попросил закрепить за мной интересующую меня тему - "Возможность подключения различных интерпретаторов/компиляторов для выполнения пользовательского кода". Интересна она мне по той причине, что я на своём сайте также планирую однажды ввести что-то вроде "песочницы" для кода или тесты, связанные с кодом, но это пока только планы.
Этой задачей занялись мы с лидом. Сперва мы довольно долго обсуждали варианты запуска хотя бы кода на Python. Основная сложность состояла не в самом факте запуска, т.к. можно установить интерпретаторы с компиляторами и вызывать их. Проблема заключается в безопасности: пользовательский код необходимо запускать изолированно, дабы он не мог причинить вреда рабочему окружению.
Конечно же, в итоге мы решили использовать Docker-контейнеры с различными языками программирования. Изучив вопрос, мы договорились поискать готовые решения. Их оказалось не то чтобы много. Главный критерий, которым мы руководствовались при выборе, – возможность развернуть сервис на собственных серверах. Таких готовых решений оказалось ещё меньше.
В итоге был составлен документ, описывающий плюсы и минусы найденых решений. Лид выбрал то, которое мы будем использовать в проекте, и отправился к руководству узнавать про возможность развёртывания на серверах.
На этом закончился 2023 год, и мы ушли на "новогодние каникулы". Конечно, другие команды не сидели всё это время сложа руки. Аналитики с техписами активно составляли документацию, а дизайнеры готовили макеты для фронтов.
Вот так прошёл второй месяц. Небыстро, но достаточно интересно. В чате команды часто происходят обсуждения, в которых рождается истина. На созвонах очень дружелюбная и открытая атмосфера.
На январь у нас большие планы и наверняка будет много работы, но об этом в следующий раз.
Пост на сайте
Поддержать проект
#Django #Стажировка #LAD_Academy #Backend #LAD #Код_на_салфетке
🔥6
Приветствую вас в этот волшебный вечер пятницы!
Ничто не сравнится с уютом домашнего кресла, вкусными угощениями и волнующими приключениями на экране. Погрузитесь в атмосферу вечера, наслаждайтесь каждым кадром и дайте себе отдых после насыщенной недели. Приготовьтесь к волнующему вечеру с фильмом, который оставит след в вашем сердце!
Фильм: Общество снега
Год: 2023
В 1972 году рейс 571 ВВС Уругвая, который был зафрахтован для перевозки команды по регби в Чили, потерпел крушение в самом сердце Анд. Только 29 из 45 пассажиров выжили в аварии. Оказавшись в ловушке в одном из самых недоступных мест на планете, они вынуждены прибегать к крайним мерам, чтобы остаться в живых.
https://www.sspoisk.ru/film/4745702/
Приятного просмотра)
Ничто не сравнится с уютом домашнего кресла, вкусными угощениями и волнующими приключениями на экране. Погрузитесь в атмосферу вечера, наслаждайтесь каждым кадром и дайте себе отдых после насыщенной недели. Приготовьтесь к волнующему вечеру с фильмом, который оставит след в вашем сердце!
Фильм: Общество снега
Год: 2023
В 1972 году рейс 571 ВВС Уругвая, который был зафрахтован для перевозки команды по регби в Чили, потерпел крушение в самом сердце Анд. Только 29 из 45 пассажиров выжили в аварии. Оказавшись в ловушке в одном из самых недоступных мест на планете, они вынуждены прибегать к крайним мерам, чтобы остаться в живых.
https://www.sspoisk.ru/film/4745702/
Приятного просмотра)
🔥2
Что выведет код с изображения ниже?
Anonymous Quiz
14%
Class One value
41%
Class Two value
24%
TypeError
21%
Ничего из перечисленного выше
Отдохнули от задачек за каникулы? Это видно по вашим ответам на вчерашнюю задачу.
Ключ к решению задачи заключается в понимании того, как работает присваивание ключа в Python-словаре, а также специфики хэширования объектов пользовательских классов.
В викторине приняли участие 21 человек. Правильных ответов было 9, это 43%! Правельный ответ самый популярный, праздники пошли на пользу🙂. Второй по популярности ответ -
Код задачи:
Структура задачи.
В самом начале мы создаём два класса:
В обоих классах прописываем dunder-метод` repr`, возвращающий строку текста с названием класса.
Далее создаем экземпляр класса
В переменной
Затем, обратившись к атрибуту
Выводим на печать значение переменной
Так почему мы получили в ответе Class Two value?
Первое, чему можно было бы удивиться, так это тому факту, что изменяемый объект (а объекты пользовательских классов по умолчанию изменяемы) можно использовать в качестве ключа в словаре Python. На самом деле к ключам в словарях применяется требование о хэшируемости, а не о неизменяемости объекта. Большинство встроенных неизменяемых типов данных в Python хэшируемы, отсюда и путаница. Объекты пользовательских классов хэшируемы по умолчанию поэтому вполне могут быть использованы в качестве ключей в словарях.
Второй неочевидный момент связан с тем, что мы "на лету" меняем класс объекта, записанного в переменную
Таким образом,
Ключ к решению задачи заключается в понимании того, как работает присваивание ключа в Python-словаре, а также специфики хэширования объектов пользовательских классов.
В викторине приняли участие 21 человек. Правильных ответов было 9, это 43%! Правельный ответ самый популярный, праздники пошли на пользу🙂. Второй по популярности ответ -
TypeError, за него проголосовало 7 человек.Код задачи:
class MyClass:
def __repr__(self):
return "Class One"
class MyClassTwo:
def __repr__(self):
return "Class Two"
a = MyClass()
dct = {a: "value"}
a.__class__ = MyClassTwo
print(a, dct[a])
Структура задачи.
В самом начале мы создаём два класса:
MyClass и MyClassTwo.В обоих классах прописываем dunder-метод` repr`, возвращающий строку текста с названием класса.
Далее создаем экземпляр класса
MyClass и записываем его в переменную a.В переменной
dct создаём словарь, где ключом будет содержимое переменной a (то есть экземпляр класса MyClass), а значением строка `"value".Затем, обратившись к атрибуту
__class__ объекта в переменной a, мы заменяем имя класса на MyClassTwo, меняя тем самым и класс объекта.Выводим на печать значение переменной
a и значение по ключу переменной a.Так почему мы получили в ответе Class Two value?
Первое, чему можно было бы удивиться, так это тому факту, что изменяемый объект (а объекты пользовательских классов по умолчанию изменяемы) можно использовать в качестве ключа в словаре Python. На самом деле к ключам в словарях применяется требование о хэшируемости, а не о неизменяемости объекта. Большинство встроенных неизменяемых типов данных в Python хэшируемы, отсюда и путаница. Объекты пользовательских классов хэшируемы по умолчанию поэтому вполне могут быть использованы в качестве ключей в словарях.
Второй неочевидный момент связан с тем, что мы "на лету" меняем класс объекта, записанного в переменную
a, но это никак не нарушает возможности обратиться к значению, которое записано в словарь по ключу, находящемуся в a. Как же так? У нас изменился объект в ключе, но по нему всё ещё можно вызвать привязанное к изначальному объекту значение? Получается, что так. И это также связано с особенностями хэширования объектов пользовательских классов. Дело в том, что хэширование объектов пользовательских классов происходит по id(), которое - сюрприз - остаётся прежним, несмотря на изменеине класса объекта с одного пользовательского на другой. В этом легко убедиться, запустив следующий код:class MyClass:
def __repr__(self):
return "Class One"
class MyClassTwo:
def __repr__(self):
return "Class Two"
a = MyClass()
print(id(a)) # 4323000272
a.__class__ = MyClassTwo
print(id(a)) # 4323000272
Таким образом,
id объекта не меняется при изменении его класса через атрибут __class__, следовательно, и хэш остаётся тем же самым. А, значит, и ключ в словаре остаётся неизменным. Живите с этим...🔥6👍1👏1
Основы ООП на Python. ч. 1
Автор: Андрей Лебедев
В декабре мы проводили опрос, чтобы узнать, какую тему о Python наши читатели хотели бы разобрать в следующем посте рубрики “Код в мешке”. Выбор большинства пал на ООП (объектно-ориентированное программирование): так ответило 36% проголосовавших. Что ж, ваша воля для нас – закон.
Автор: Андрей Лебедев
В декабре мы проводили опрос, чтобы узнать, какую тему о Python наши читатели хотели бы разобрать в следующем посте рубрики “Код в мешке”. Выбор большинства пал на ООП (объектно-ориентированное программирование): так ответило 36% проголосовавших. Что ж, ваша воля для нас – закон.
🔥5
Python полон парадоксов. С одной стороны, код в Python совсем необязательно должен быть выполнен в методологии ООП. Создавая телеграмм-бота, например, или простенький скрипт для парсинга данных с какого-нибудь сайта, вполне естественно обходиться без ООП. С другой стороны, как вы уже, наверное, неоднократно слышали, всё в Python является объектом, то есть экземпляром какого-то класса. Это касается буквально всего: строк, целых чисел, списков, функций и т.д. Таким образом, если вы пишете код на Python, вы автоматически используете ООП. Поэтому даже если вы планируете до конца своих дней писать код, например, в структурной парадигме, изучить ООП всё равно стоит. Чем лучше вы будете его понимать, тем эффективнее вы будете работать с классами, написанными другими людьми.
Что такое ООП?
В учебниках или статьях вы найдёте примерно следующее определение ООП:
*️⃣ парадигма программирования, в центре которой данные и объекты, а не функции, как при процедурном подходе.
*️⃣ методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определённого класса, а классы образуют иерархию наследования.
*️⃣ парадигма разработки, в рамках которой все написанные программы состоят из объектов.
*️⃣ подход, при котором программа рассматривается как набор объектов, взаимодействующих друг с другом. У каждого есть свойства и поведение.
В центре любого определения находится понятие “объекта”, что едва ли удивит человека, который знает, как расшифровывается ООП. Где-то упоминаются классы, где-то – свойства и поведение объектов, но в целом разговор обычно строится вокруг классов (неких шаблонов) и экземпляров этих классов (объектов, которые на основании этих шаблонов создаются). Утверждается, что объектно-ориентированное мышление вообще присуще человеку: мы, мол, видим мир как совокупность объектов, которые как-то друг с другом взаимодействуют. Даже человеческие языки устроены таким образом, чтобы описывать мир в категориях объектов, которые обладают какими-то качествами и что-то делают. В некоторых случаях вспоминают даже древнегреческих философов, а именно Платона с его миром идей и миром вещей. В первом существует, например, идея кошки (класс), некий образ, по подобию которого созданы все кошки из мира вещей (объекты).
Всё это справедливо и всё это важно понимать, но я предлагаю начать с чего-нибудь попроще. Всё программирование, если предельно упростить, – это разговор про данные и их последовательную обработку. А ООП – это способ хранения данных и действий с ними в одном месте. Что это означает, давайте рассмотрим на примере:
Здесь всего один элемент информации (атрибут класса) - имя ученика, а также всего одно действие (метод) - поздороваться. Информация об ученике и его функционал содержится в классе
*️⃣ Код легче писать. Нужная информация и действия хранятся в классе. Их легко снова и снова использовать, создавая экземпляры.
*️⃣ Код легче читать. Если представить, что в нашем классе больше одного метода, то и без дополнительных объяснений будет понятно, что происходит в следующем коде:
*️⃣ Код легче обновлять. Если нам понадобится, чтобы все созданные нами студенты говорили “Добрый день” вместо “Привет”, нам достаточно изменить код в одном месте: в классе
*️⃣ Код легче разрабатывать в команде. Если код распределен по классам и объектам, то над каждым из них может работать один человек, а дальше результаты работы всех можно объединять.
Что такое ООП?
В учебниках или статьях вы найдёте примерно следующее определение ООП:
*️⃣ парадигма программирования, в центре которой данные и объекты, а не функции, как при процедурном подходе.
*️⃣ методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определённого класса, а классы образуют иерархию наследования.
*️⃣ парадигма разработки, в рамках которой все написанные программы состоят из объектов.
*️⃣ подход, при котором программа рассматривается как набор объектов, взаимодействующих друг с другом. У каждого есть свойства и поведение.
В центре любого определения находится понятие “объекта”, что едва ли удивит человека, который знает, как расшифровывается ООП. Где-то упоминаются классы, где-то – свойства и поведение объектов, но в целом разговор обычно строится вокруг классов (неких шаблонов) и экземпляров этих классов (объектов, которые на основании этих шаблонов создаются). Утверждается, что объектно-ориентированное мышление вообще присуще человеку: мы, мол, видим мир как совокупность объектов, которые как-то друг с другом взаимодействуют. Даже человеческие языки устроены таким образом, чтобы описывать мир в категориях объектов, которые обладают какими-то качествами и что-то делают. В некоторых случаях вспоминают даже древнегреческих философов, а именно Платона с его миром идей и миром вещей. В первом существует, например, идея кошки (класс), некий образ, по подобию которого созданы все кошки из мира вещей (объекты).
Всё это справедливо и всё это важно понимать, но я предлагаю начать с чего-нибудь попроще. Всё программирование, если предельно упростить, – это разговор про данные и их последовательную обработку. А ООП – это способ хранения данных и действий с ними в одном месте. Что это означает, давайте рассмотрим на примере:
class Student:
def __init__(self, name=""):
self.name = name
def say_hello(self):
print(f"Привет, я {self.name}!")
Здесь всего один элемент информации (атрибут класса) - имя ученика, а также всего одно действие (метод) - поздороваться. Информация об ученике и его функционал содержится в классе
Student. И это очень удобно по целому ряду причин:*️⃣ Код легче писать. Нужная информация и действия хранятся в классе. Их легко снова и снова использовать, создавая экземпляры.
*️⃣ Код легче читать. Если представить, что в нашем классе больше одного метода, то и без дополнительных объяснений будет понятно, что происходит в следующем коде:
stan = Student(“Стэн”)
stan.say_hello()
stan.do_homework()
stan.sing(“Hello people”)
stan.say_bye()
*️⃣ Код легче обновлять. Если нам понадобится, чтобы все созданные нами студенты говорили “Добрый день” вместо “Привет”, нам достаточно изменить код в одном месте: в классе
Student.*️⃣ Код легче разрабатывать в команде. Если код распределен по классам и объектам, то над каждым из них может работать один человек, а дальше результаты работы всех можно объединять.
🔥5
*️⃣ Код можно использовать в новых проектах. Если вся информация и действия компактно собраны в классе, то его можно использовать в других проектах, создавая соответствующие объекты уже в них.
Что такое self?
В примере выше в двух методах (то есть функциях внутри) класса
Но что же такое
Мы добавили два
*️⃣ вывод объекта
*️⃣ вывод экземпляра класса
Что происходит в результате? В момент инициализации объекта класса
Что еще важно знать про self?
*️⃣ Вместо
При этом стоит помнить, что классическим и общепринятым вариантом всё же считается
*️⃣ Есть способ увидеть все атрибуты, записанные в
Что такое __init__()?
Последний незнакомый элемент синтаксиса, который появился в нашем первом примере, - это метод
Что такое self?
В примере выше в двух методах (то есть функциях внутри) класса
Student в качестве аргумента используется объект self. Редко кто в подробностях рассказывает о том, что это за объект. Чаще говорят о том, что он позволяет делать: он даёт доступ к атрибутам (элементам информации) класса из любого места внутри самого этого класса. В нашем примере с классом Student мы в момент инициации (создания) объекта этого класса методом __init__ ввели атрибут self.name. Благодаря этому ниже – в методе say_hello, куда мы передали объект self, – мы смогли использовать этот же атрибут для того, чтобы ученик говорил приветствие и представлялся по имени.Но что же такое
self? Обычно говорят, что это ссылка на текущий экземпляр класса. Тот самый, который создаётся в момент инициализации. Вернёмся к нашему примеру с классом Student и воспользуемся приёмом, который знаком любому начинающему питонисту: в любой непонятной ситуации выводи всё в консоль print’ом!
class Student:
def __init__(self, name=""):
self.name = name
print(self) # <__main__.Student object at 0x1062c7790>
def say_hello(self):
print(f"Привет, я {self.name}!")
stan = Student("Стэн")
print(stan) # <__main__.Student object at 0x1062c7790>
Мы добавили два
print’а:*️⃣ вывод объекта
self в методе __init__ сразу после записи имени ученика в атрибут self.name,*️⃣ вывод экземпляра класса
Student сразу после его создания и записи в переменную stan.Что происходит в результате? В момент инициализации объекта класса
Student, который мы записываем в переменную stan, на печать выводится объект self. Из записи <__main__.Student object at 0x1062c7790> видно, что этот объект класса Student, находящийся в модуле main, хранится в ячейке памяти за номером 0x1062c7790. Дальше на печать выводится объект в переменной stan, и мы видим, что это тот же самый объект, хранящийся в той же ячейке. Именно это и означает формулировка “ссылка на текущий экземпляр класса”.Что еще важно знать про self?
*️⃣ Вместо
self можно использовать любое другое название для переменной текущего объекта, но выбранного имени необходимо последовательного придерживаться в коде класса:
class Student:
def __init__(child, name=""):
self.name = name
def say_hello(child):
print(f"Привет, я {child.name}!")
При этом стоит помнить, что классическим и общепринятым вариантом всё же считается
self. Об этом вам будут стараться напоминать даже некоторые IDE.*️⃣ Есть способ увидеть все атрибуты, записанные в
self. Для этого нужно обратиться к словарю __dict__, который ассоциирован с self:
class Student:
def __init__(self, name="", age=0):
self.name = name
self.age = age
print(self.__dict__)
def say_hello(self):
print(f"Привет, я {self.name}!")
stan = Student("Стэн", 8)
# {'name': 'Стэн', 'age': 8}
Что такое __init__()?
Последний незнакомый элемент синтаксиса, который появился в нашем первом примере, - это метод
__init__, известный также как конструктор класса. Если упростить, то он служит для записи передаваемых при создании объекта данных в атрибуты объекта self. Так, например, мы передавали имя ученика при создании экземпляра класса Student.🔥5