Второй - сложность алгоритма и затрачиваемые ресурсы.
В используемом списке бранных слов насчитывается свыше 1000 слов.
Сообщение от пользователя очищается от пунктуации и разделяется на множество (set) слов.
При большом потоке сообщений, это может сильно увеличить нагрузку на сервер и замедлить работу бота.
Я опишу уже улучшенный вариант, к которому мы пришли с подписчиком @rusheslav после тестирования фильтра в чате, но если у вас есть комментарии или рекомендации по улучшению кода, буду рад!
Множество запрещённых слов.
Использовать будем готовый список: https://github.com/bars38/Russian_ban_words
Вы можете составить свой или найти другой.
Скачиваем файл
В корне проекта создаём директорию
Открываем файл
В этой константе создаётся множество из слов в файле.
Фильтрующая функция.
В пакете
Создаём асинхронную функцию
Код функции:
По ходу действий:
Создаём переменную
После проверки на наличие сообщения создаём переменную
Далее проходимся циклом
Если слово есть среди запрещённых, заменяем его на звёздочки в количестве длинны слова и выставляем "флаг" о наличии в тексте запрещённых слов.
Далее проверка "флага", если переменная
В противном случае бот сперва удаляет исходное сообщение. Записывает сообщение и информацию от кого в лог файл. Затем отправляет стикер по его идентификатору, после чего отправляет сообщение с исправленным текстом.
Как получить идентификатор стикера.
Для получения идентификатора стикера, достаточно отправить боту https://t.iss.one/idstickerbot стикер, идентификатор которого хотите получить.
В ответ он пришлёт идентификатор.
Готово.
Завершение
Осталось только зарегистрировать обработчик. Добавляем в файл
Готово. Теперь бот фильтрует нежелательные слова в сообщениях. Конечно это не панацея и мы все знаем, как можно исхитриться в Русском языке, но основную часть отсеивать будет. А потом просто добавляем слова.
Дополнительно: Изменение логгера.
Изначально логгер находился в файле
Вынес логгер в файл
В используемом списке бранных слов насчитывается свыше 1000 слов.
Сообщение от пользователя очищается от пунктуации и разделяется на множество (set) слов.
При большом потоке сообщений, это может сильно увеличить нагрузку на сервер и замедлить работу бота.
Я опишу уже улучшенный вариант, к которому мы пришли с подписчиком @rusheslav после тестирования фильтра в чате, но если у вас есть комментарии или рекомендации по улучшению кода, буду рад!
Множество запрещённых слов.
Использовать будем готовый список: https://github.com/bars38/Russian_ban_words
Вы можете составить свой или найти другой.
Скачиваем файл
words.txt. Для большей наглядности, я его переименовал в ban_words.txt.В корне проекта создаём директорию
res и помещаем туда файл.Открываем файл
settings.py и в начале, после импортов создаём константу BAN_WORDS.В этой константе создаётся множество из слов в файле.
BAN_WORDS = set(line.strip() for line in open('res/ban_words.txt'))Фильтрующая функция.
В пакете
handlers создадим новый файл filter_words.py.Создаём асинхронную функцию
check_message, принимающую message.Код функции:
import string
from aiogram.types import Message
from botlogic import views
from botlogic.settings import BAN_WORDS, logger
async def check_message(message: Message):
contains_ban_word = False
if message.text:
message_words = set(message.text.translate(str.maketrans('', '', string.punctuation)).split())
filtered_message = message.text
for word in message_words:
if word.lower() in BAN_WORDS:
filtered_message = filtered_message.replace(word, "*" * len(word))
contains_ban_word = True
if contains_ban_word:
await message.delete()
logger.info(f"Удалено сообщение от пользователя {message.from_user.username}: {message.text}")
await message.answer_sticker('CAACAgIAAxkBAAEKbW1lGVW1I6zFVLyovwo2rSgIt1l35QADJQACYp0ISWYMy8-mubjIMAQ')
await message.answer(views.filtered_message(message.from_user.username, filtered_message))
По ходу действий:
Создаём переменную
contains_ban_word. Это "флаг", по умолчанию считаем, что в сообщении нет запрещённых слов.После проверки на наличие сообщения создаём переменную
message_words, в которой создаём множество очищенных от пунктуации слов. Множество не позволяет хранить в себе два одинаковых объекта, тем самым в переменной будут только уникальные слова. И переменную filtered_message, в которую помещаем копию сообщения.Далее проходимся циклом
for по множеству слов из сообщения.Если слово есть среди запрещённых, заменяем его на звёздочки в количестве длинны слова и выставляем "флаг" о наличии в тексте запрещённых слов.
Далее проверка "флага", если переменная
contains_ban_word по-прежнему в изначальном состоянии False, то бот ничего не делает. В противном случае бот сперва удаляет исходное сообщение. Записывает сообщение и информацию от кого в лог файл. Затем отправляет стикер по его идентификатору, после чего отправляет сообщение с исправленным текстом.
Как получить идентификатор стикера.
Для получения идентификатора стикера, достаточно отправить боту https://t.iss.one/idstickerbot стикер, идентификатор которого хотите получить.
В ответ он пришлёт идентификатор.
Готово.
Завершение
Осталось только зарегистрировать обработчик. Добавляем в файл
main.py следующую строку: dp.message.register(check_message). Отсутствие второго аргумента означает, что бот будет обрабатывать все сообщения.Готово. Теперь бот фильтрует нежелательные слова в сообщениях. Конечно это не панацея и мы все знаем, как можно исхитриться в Русском языке, но основную часть отсеивать будет. А потом просто добавляем слова.
Дополнительно: Изменение логгера.
Изначально логгер находился в файле
main.py и не записывал никуда события, только отображал в терминале.Вынес логгер в файл
settings.py. Определил два обработчика, для терминала и для файла.Код нового логгера:
Файлы к посту, можно получить в боте по коду: 702209
Пост на сайте.
Поддержать канал.
# Логгер
logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter(
"%(asctime)s - [%(levelname)s] - %(name)s - (%(filename)s).%(funcName)s(%(lineno)d) - %(message)s")
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(formatter)
file_handler = logging.FileHandler("logs.txt")
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(console_handler)
logger.addHandler(file_handler)
Файлы к посту, можно получить в боте по коду: 702209
Пост на сайте.
Поддержать канал.
Возрастной опрос =)
Сколько вам лет?
Сколько вам лет?
Anonymous Poll
3%
До 15
0%
От 16 до 18
13%
От 19 до 25
40%
От 26 до 35
36%
От 36 до 45
6%
От 46 до 55
1%
От 56
1%
Не скажу, я стесняшка☺️
😱5
Соберём результаты опроса по возрасту подписчиков.
В опросе приняло участие 47 человек!
Получаются следующие цифры:
2 подписчика до 15 лет.
На третьем месте подписчики от 19 до 25 лет - в числе 8 проголосовавших.
Бо́льшая часть, а именно 19 человек в возрасте от 26 до 35.
Не отстают и подписчики от 36 до 45, их насчитывается 16.
Один подписчик в возрасте 46-55.
И одна(ин) стеснительный, пожелавший остаться неизвестным)
В комментарии к опросу пришло предложение сделать опрос по городам подписчиков.
Вместо опроса, пишите в комментариях из какого вы города! Потом также оформлю результаты.
В опросе приняло участие 47 человек!
Получаются следующие цифры:
2 подписчика до 15 лет.
На третьем месте подписчики от 19 до 25 лет - в числе 8 проголосовавших.
Бо́льшая часть, а именно 19 человек в возрасте от 26 до 35.
Не отстают и подписчики от 36 до 45, их насчитывается 16.
Один подписчик в возрасте 46-55.
И одна(ин) стеснительный, пожелавший остаться неизвестным)
В комментарии к опросу пришло предложение сделать опрос по городам подписчиков.
Вместо опроса, пишите в комментариях из какого вы города! Потом также оформлю результаты.
Приветствую.
В комментариях к шуточному опросу про тестирование систем оповещения, зашла речь о бункерах. И мне вспомнился один хороший фильм на эту тему.
Посему, предлагаю ввести "пятничную" рубрику с фильмом на вечер от меня и с вашими вариантами в комментариях.
Фильм на сегодня: Взрыв из прошлого (1998).
Краткий синопсис: Адам Уэббер родился нормальным ребенком, но, по глупому недоразумению, провел 35 лет в бомбоубежище вместе со своими родителями. Наивный и искренний, он впервые оказывается среди людей в бушующем Лос-Анджелесе 90-х! И кто знает - может, он еще успеет наверстать упущенное?!
Посмотреть фильм можно по ссылке: https://www.sspoisk.ru/film/2408
Может быть у вас есть свой вариант фильма на вечер? Делитесь им в комментариях!
В комментариях к шуточному опросу про тестирование систем оповещения, зашла речь о бункерах. И мне вспомнился один хороший фильм на эту тему.
Посему, предлагаю ввести "пятничную" рубрику с фильмом на вечер от меня и с вашими вариантами в комментариях.
Фильм на сегодня: Взрыв из прошлого (1998).
Краткий синопсис: Адам Уэббер родился нормальным ребенком, но, по глупому недоразумению, провел 35 лет в бомбоубежище вместе со своими родителями. Наивный и искренний, он впервые оказывается среди людей в бушующем Лос-Анджелесе 90-х! И кто знает - может, он еще успеет наверстать упущенное?!
Посмотреть фильм можно по ссылке: https://www.sspoisk.ru/film/2408
Может быть у вас есть свой вариант фильма на вечер? Делитесь им в комментариях!
AIOgram3 15. Обработка события вступления или покидания чата
Последняя (на данный момент) задача - это приветствие нового участника чата и оповещение о том, что кто-то нас покинул.
Решение достаточно простое и пост будет коротким.
Последняя (на данный момент) задача - это приветствие нового участника чата и оповещение о том, что кто-то нас покинул.
Решение достаточно простое и пост будет коротким.
Обработка событий.
Откроем файл
Обе функции принимают
В теле функции напишем отправку сообщения в ответ на событие, обращаясь к методам
Код функций:
Регистрация обработчиков.
Переходим в файл
Файлы к посту, можно получить в боте по коду: 164296
Пост на сайте.
Поддержать канал.
#aiogram #гайды #python
Откроем файл
events.py в пакете handlers и создадим две асинхронные функции: on_user_join и on_user_left.Обе функции принимают
event - объект класса ChatMemberUpdated.В теле функции напишем отправку сообщения в ответ на событие, обращаясь к методам
new_chat_member и old_chat_member.Код функций:
from aiogram.types import ChatMemberUpdatedНе забудьте написать функции, возвращающие текст сообщения в файле
async def on_user_join(event: ChatMemberUpdated):
await event.answer(views.join_message(event.new_chat_member.user.first_name))
async def on_user_left(event: ChatMemberUpdated):
await event.answer(views.left_message(event.old_chat_member.user.first_name))
views.py.Регистрация обработчиков.
Переходим в файл
main.py и добавляем следующие строки:from aiogram.filters import ChatMemberUpdatedFilter, IS_NOT_MEMBER, IS_MEMBERГотово! Теперь если новый пользователь зайдёт в чат, его поприветствует бот, а если кто-то его покинет, бот уведомит и об этом.
dp.chat_member.register(on_user_join, ChatMemberUpdatedFilter(IS_NOT_MEMBER >> IS_MEMBER))
dp.chat_member.register(on_user_left, ChatMemberUpdatedFilter(IS_MEMBER >> IS_NOT_MEMBER))
Файлы к посту, можно получить в боте по коду: 164296
Пост на сайте.
Поддержать канал.
#aiogram #гайды #python
🔥1
Django 31. Форма авторизации и кнопка выхода
Продолжаем развивать проект.
В этом и нескольких следующих постах, мы добавим возможность пользователям регистрироваться, авторизовываться на сайте и выходить с него, сбрасывать свой пароль, а также реализуем страницу с профилем пользователя.
И начнём мы с создания нового приложения.
Приложение user_app.
В прошлом посте я упоминал о важности разделения разных логических блоков на Django-приложения. Поэтому для пользователей сделаем отдельное приложение
Для создания нового приложения выполните в терминале следующую команду:
Создастся новая директория с основными файлами.
Сразу откроем файл
Продолжаем развивать проект.
В этом и нескольких следующих постах, мы добавим возможность пользователям регистрироваться, авторизовываться на сайте и выходить с него, сбрасывать свой пароль, а также реализуем страницу с профилем пользователя.
И начнём мы с создания нового приложения.
Приложение user_app.
В прошлом посте я упоминал о важности разделения разных логических блоков на Django-приложения. Поэтому для пользователей сделаем отдельное приложение
user_app.Для создания нового приложения выполните в терминале следующую команду:
python manage.py startapp user_app
Создастся новая директория с основными файлами.
Сразу откроем файл
settings.py и добавим новое приложение в список INSTALLED_APPS - 'user_app.apps.UserAppConfig',Авторизация.
Форма авторизации.
Создадим форму авторизации.
На самом деле, делать этого не обязательно.
Можно воспользоваться встроенной формой, собственно от которой будем наследоваться, однако тут встаёт вопрос с её отображением. У стандартной формы отсутствуют стили.
Можно конечно их прописать с помощью CSS-селекторов, но у меня в данный момент используется Bootstrap5.
Для того чтобы воспользоваться его возможностями, необходимо форме определить конкретные стили, а для этого нужно её переопределить.
В директории приложения
Создадим класс
Затем создадим два поля:
Первое будет
Первым атрибутом будет максимальная длина имени пользователя. По умолчанию в модели пользователя максимальная длина составляет 150 символов, укажем столько же или можете по своему усмотрению указать меньше.
Вторым будет название поля.
Третьим атрибутом будет виджет, в котором определим текстовое поле ввода. Внутри в качестве атрибутов присвоим полю класс, а также укажем текст внутри поля.
Второе поле
Первый атрибут такой же - максимальная длина, которая равна 128 символам.
Второй - название поля.
Третьим атрибутом определим виджет, в этот раз это будет поле ввода пароля. Точно также передаём в атрибутах класс и текст внутри поля.
Ниже создаём подкласс
Первым полем будет используемая модель пользователя. Поскольку мы пока используем стандартную модель, её и указываем. Если же вы используете расширенную модель пользователя, то указывайте её.
Вторым полем мы указываем поля формы. В нашем случае их всего два, имя пользователя и пароль.
Код:
Представление страницы авторизации.
Откроем файл
Напишем класс
В классе пропишем всего три поля:
-
-
-
Также переопределим метод
Код:
Форма авторизации.
Создадим форму авторизации.
На самом деле, делать этого не обязательно.
Можно воспользоваться встроенной формой, собственно от которой будем наследоваться, однако тут встаёт вопрос с её отображением. У стандартной формы отсутствуют стили.
Можно конечно их прописать с помощью CSS-селекторов, но у меня в данный момент используется Bootstrap5.
Для того чтобы воспользоваться его возможностями, необходимо форме определить конкретные стили, а для этого нужно её переопределить.
В директории приложения
user_app создадим новый файл forms.py.Создадим класс
LoginForm, унаследованный от AuthenticationForm.Затем создадим два поля:
Первое будет
username. В нём определим поле символов. Первым атрибутом будет максимальная длина имени пользователя. По умолчанию в модели пользователя максимальная длина составляет 150 символов, укажем столько же или можете по своему усмотрению указать меньше.
Вторым будет название поля.
Третьим атрибутом будет виджет, в котором определим текстовое поле ввода. Внутри в качестве атрибутов присвоим полю класс, а также укажем текст внутри поля.
Второе поле
password. Также является полем символов. Первый атрибут такой же - максимальная длина, которая равна 128 символам.
Второй - название поля.
Третьим атрибутом определим виджет, в этот раз это будет поле ввода пароля. Точно также передаём в атрибутах класс и текст внутри поля.
Ниже создаём подкласс
Meta.Первым полем будет используемая модель пользователя. Поскольку мы пока используем стандартную модель, её и указываем. Если же вы используете расширенную модель пользователя, то указывайте её.
Вторым полем мы указываем поля формы. В нашем случае их всего два, имя пользователя и пароль.
Код:
from django import forms
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User
class LoginForm(AuthenticationForm):
username = forms.CharField(
max_length=150,
label='Имя пользователя',
widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Введите имя пользователя'
})
)
password = forms.CharField(
max_length=128,
label='Пароль',
widget=forms.PasswordInput(attrs={
'class': 'form-control',
'placeholder': 'Введите пароль'
})
)
class Meta:
model = User
fields = ['username', 'password']
Представление страницы авторизации.
Откроем файл
views.py.Напишем класс
CustomLoginView, унаследованный от LoginView.В классе пропишем всего три поля:
-
authentication_form - в этом поле указываем класс нашей переопределённой формы.-
template_name - в этом поле указываем HTML-файл шаблона.-
extra_context - в этом поле указываем дополнительные переменные, передаваемые в шаблон. Также переопределим метод
get_success_url. В этом методе, воспользовавшись функцией reverse_lazy указываем на какую страницу перейдёт пользователь после авторизации. Пока у нас нет страницы профиля, будем перенаправлять пользователя на главную страницу.Код:
from django.contrib.auth.views import LoginView
from django.urls import reverse_lazy
from user_app.forms import LoginForm
class CustomLoginView(LoginView):
authentication_form = LoginForm
template_name = 'user_app/login.html'
extra_context = {'title': 'Авторизация на сайте'}
def get_success_url(self):
return reverse_lazy('blog:index')
👍1
Шаблон страницы авторизации.
В директории
В этом файле прописываем тег формы.
Внутри прописываем:
- Тег
- Проверку на наличие не связанных с полями ошибок. Если ошибки есть, выводим их.
- В цикле
- Кнопку для отправки формы.
Код:
URL-паттерн страницы входа.
Создадим новый файл
Указываем имя приложения и в списке
Код:
Теперь необходимо добавить приложение в основной файл. Откроем файл
Все страницы связанные с пользователем будут начинаться на
Например:
-
-
-
- И так далее....
Выход.
Выход с сайта - очень простой функционал, но есть два варианта его исполнения:
1. Если вам не нужна промежуточная страница.
2. Если вам нужна промежуточная страница.
Второй вариант, это продолжение первого. В первом случае при выходе пользователя с сайта, он будет переправлен на указанную вами страницу, например, главную. Во втором же варианте, после выхода пользователя с сайта, он попадёт на специальную страницу на которой, например, будет кнопка повторной авторизации или ещё что-то, что вам необходимо.
Рассмотрим оба варианта.
Откроем файл
Для выхода используем встроенное в Django представление. Определяем URL и название.
На этом месте начинаются различия между первым и вторым вариантом.
Для первого варианта достаточно открыть файл
Пример для главной страницы:
Для второго варианта необходимо в URL-паттерне внутри представления добавить путь к шаблону:
Затем создать этот шаблон с необходимым вам содержимым, например:
Готово.
Кнопка входа и выхода в шапке сайта.
Остался последний "штрих" - добавить кнопку для входа и выхода в шапку сайта.
При этом, кнопка входа должна быть видна только неавторизованному пользователю, а кнопка выхода авторизованному соответственно.
В директории
templates создадим новую директорию user_app, а в ней файл login.html.В этом файле прописываем тег формы.
Внутри прописываем:
- Тег
csrf_token. Данный тег обеспечивает защиту формы.- Проверку на наличие не связанных с полями ошибок. Если ошибки есть, выводим их.
- В цикле
for перебираем поля формы. Выводим название поля и само поле.- Кнопку для отправки формы.
Код:
<form method="post">
{% csrf_token %}
{% if form.non_field_errors %}
<div class="alert alert-danger">
{{ form.non_field_errors }}
</div>
{% endif %}
{% for field in form %}
<p class="form-label">{{ field.label }}</p>
<p>{{ field }}</p>
{% endfor %}
<button type="submit" class="btn btn-outline-success">Войти</button>
</form>
URL-паттерн страницы входа.
Создадим новый файл
urls.py.Указываем имя приложения и в списке
urlpatterns добавляем путь для страницы авторизации.Код:
from django.urls import path
from user_app import views
app_name = 'user_app'
urlpatterns = [
path('login/', views.CustomLoginView.as_view(), name='login'),
]
Теперь необходимо добавить приложение в основной файл. Откроем файл
urls.py в директории проекта и добавим новую строку:path('user/', include('user_app.urls', namespace='user_app')),Все страницы связанные с пользователем будут начинаться на
user. Например:
-
user/login - авторизация-
user/signup - регистрация-
user/<username> - профиль- И так далее....
Выход.
Выход с сайта - очень простой функционал, но есть два варианта его исполнения:
1. Если вам не нужна промежуточная страница.
2. Если вам нужна промежуточная страница.
Второй вариант, это продолжение первого. В первом случае при выходе пользователя с сайта, он будет переправлен на указанную вами страницу, например, главную. Во втором же варианте, после выхода пользователя с сайта, он попадёт на специальную страницу на которой, например, будет кнопка повторной авторизации или ещё что-то, что вам необходимо.
Рассмотрим оба варианта.
Откроем файл
urls.py в директории приложения. Добавим в список urlpatterns следующую строку и определим новый импорт:from django.contrib.auth import views as auth_views
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
Для выхода используем встроенное в Django представление. Определяем URL и название.
На этом месте начинаются различия между первым и вторым вариантом.
Для первого варианта достаточно открыть файл
settings.py и определить новый параметр LOGOUT_REDIRECT_URL, прописав в нём прямой путь или имя URL-паттерна.Пример для главной страницы:
LOGOUT_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = 'blog:index'
Для второго варианта необходимо в URL-паттерне внутри представления добавить путь к шаблону:
path('logout/', auth_views.LogoutView.as_view(template_name='user_app/logout.html'), name='logout'),Затем создать этот шаблон с необходимым вам содержимым, например:
{% extends 'blog/base.html' %}
{% block content %}
<div class="form-section container">
<h2>Вы успешно вышли с сайта</h2>
<a href="{% url 'user_app:login' %}">Войти в личный кабинет снова</a>
</div>{% endblock %}Готово.
Кнопка входа и выхода в шапке сайта.
Остался последний "штрих" - добавить кнопку для входа и выхода в шапку сайта.
При этом, кнопка входа должна быть видна только неавторизованному пользователю, а кнопка выхода авторизованному соответственно.
🔥1
Откроем файл
Файлы к посту, можно получить в боте по коду: 896551
Пост на сайте.
Поддержать канал.
header.html и в удобное место добавим следующий код:{% if user.is_authenticated %}
<div class="dropdown">
<button class="btn btn-primary my-btn dropdown-toggle me-3" type="button"
data-bs-toggle="dropdown" aria-expanded="false">
{{ request.user }}
</button>
<ul class="dropdown-menu dd-color">
<li><a class="dropdown-item dd-item-color" href="{% url 'user_app:logout' %}">Выйти</a></li>
</ul>
</div>
{% else %}
<li class="nav-item">
<a class="nav-link btn btn-primary my-btn me-3"
href="{% url 'user_app:login' %}">Войти</a>
</li>
{% endif %}
Можно запустить Django и протестировать возможность входа и выхода с сайта.Файлы к посту, можно получить в боте по коду: 896551
Пост на сайте.
Поддержать канал.
🔥2
Приветствую.
На одном из проходимых мной курсов, итоговым заданием необходимо было сделать прототип сервиса по сокращению ссылок.
Задание достаточно простое и мне стало интересно, а что если вынести фронт на Vue, а бэк пусть остаётся на Django?
Также, дополнительным плюсом будет иметь свой сервис сокращения ссылок, поскольку часто ссылка + UTF метки занимают много места, а сервисы типа click.ru|bit.ly|vk.cc и прочие, помечаются как небезопасные.
Результатом стал сайт https://lkeep.ru/
Работать будет так: https://lkeep.ru/l/EMDRTbZUpi
На данный момент из "косяков" только отсутствие адаптивной вёрстки и неработающий(недописанный) функционал копирования ссылки в лк.
Мне нужны ваши отзывы. Как вам, может что-то улучшить/изменить? Пишите в комментариях!
P.S. Регистрация обязательна, иначе это будет такая же помойка как и другие сайты.
На одном из проходимых мной курсов, итоговым заданием необходимо было сделать прототип сервиса по сокращению ссылок.
Задание достаточно простое и мне стало интересно, а что если вынести фронт на Vue, а бэк пусть остаётся на Django?
Также, дополнительным плюсом будет иметь свой сервис сокращения ссылок, поскольку часто ссылка + UTF метки занимают много места, а сервисы типа click.ru|bit.ly|vk.cc и прочие, помечаются как небезопасные.
Результатом стал сайт https://lkeep.ru/
Работать будет так: https://lkeep.ru/l/EMDRTbZUpi
На данный момент из "косяков" только отсутствие адаптивной вёрстки и неработающий(недописанный) функционал копирования ссылки в лк.
Мне нужны ваши отзывы. Как вам, может что-то улучшить/изменить? Пишите в комментариях!
P.S. Регистрация обязательна, иначе это будет такая же помойка как и другие сайты.
Django 32. Форма регистрации
Авторизацию мы добавили. Теперь добавим возможность регистрироваться на сайте.
В целом, процесс примерно такой же как и с авторизацией.
Продолжаем работать в директории приложения
Почти весь пост будем использовать, написанный в прошлом посте код с небольшими изменениями.
Форма регистрации.
Откроем файл
Далее добавляем 4 поля:
Поля
Поле
Далее прописываем внутренний класс
Авторизацию мы добавили. Теперь добавим возможность регистрироваться на сайте.
В целом, процесс примерно такой же как и с авторизацией.
Продолжаем работать в директории приложения
user_app.Почти весь пост будем использовать, написанный в прошлом посте код с небольшими изменениями.
Форма регистрации.
Откроем файл
forms.py и создадим новый класс RegistrationForm, унаследованный от UserCreationForm.Далее добавляем 4 поля:
username, email, password1 и password2.Поля
username и password можно скопировать из формы авторизации. Они такие же. Разве, что в поле password2 изменим название и описание поля.Поле
email описывается похожим образом, но для валидации используется EmailInput.Далее прописываем внутренний класс
Meta, в котором указываем модель и поля формы.