Код на салфетке
2.22K subscribers
745 photos
14 videos
2 files
788 links
Канал для тех, кому интересно программирование на Python и не только.

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

Реклама и взаимопиар: @Murzyev1995
Сотрудничество и др.: @proDreams
Download Telegram
В
предыдущей функции send_file_start мы получили от пользователя код файла, теперь необходимо выполнить запрос данных по API.
Делаем проверку на введённые данные, если там не только цифры, то отправляем пользователю сообщение, что код неверный и повторно ожидаем ввода. Пропишем сообщение в файле views.py в функции send_file_wrong_input.
Если формат верный, то в блоке if отправляем сообщение из функции send_file_please_wait во views.py, что запрос выполняется.
Здесь же, в блоке if, создаём переменную data и выполняем функцию get_path из файла api_actions.py, передавая в неё текст сообщения от пользователя.
Далее у нас снова проверка, в этот раз на содержимое переменной data, если она пустая, то отправляем пользователю сообщение, что файл не найден и нужно попробовать снова.
Если же в переменной data есть необходимые данные, то создаём переменную file и присваиваем ей объект класса FSInputFile, в параметры которого, передаём путь до файла полученный из переменной data.
Удаляем предыдущее сообщение о выполнении запроса и отправляем файл.
В метод отправки файла передаём chat_id, переменную с путём до файла и подпись к файлу из функции file_caption в файле views.py.
А потом закрываем машину состояний.

Код:
from aiogram.fsm.context import FSMContext
from aiogram.types import Message, FSInputFile

from botlogic import views
from botlogic.settings import bot
from botlogic.utils import api_actions

async def send_file_get_data(message: Message, state: FSMContext):
if message.text.isdigit():
await message.answer(views.send_file_please_wait())
data = api_actions.get_path(message.text)
if data:
file = FSInputFile(path=data['file_path'])
await bot.delete_message(message.chat.id, message.message_id + 1)
await bot.send_document(message.chat.id, document=file, caption=views.file_caption(data['title']))
await state.clear()
else:
await message.answer(views.send_file_not_found())
else:
await message.answer(views.send_file_wrong_input())

Осталось зарегистрировать в файле main.py:
    dp.message.register(send_file.send_file_get_data, SendFileSteps.get_code_from_user)

Можем проверять. Запустим Django в отдельном окне и запустим бота.
Перейдя в бота напишем нашу команду /get_file и в ответ на запрос код файла 0.
И бот в ответ пришлёт файл.

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

Файлы к посту, можно получить в боте по коду: 715723
Пост на сайте.
Поддержать канал.

#aiogram #python #команды #меню #fsm #машина_состояний
👍1
Поправка к посту Django 8 Первая модель.

Как верно подметил Кирилл в чате, если сделать несколько файлов с одинаковым кодом, то при запросе, вылетит ошибка, поскольку мы ищем только один файл с указанным кодом, а на деле их несколько.

Для исправления этого, необходимо в коде модели, в поле code добавить параметр unique=True.
    code = models.IntegerField(default=0,
verbose_name='Код файла',
unique=True)

И применить миграции:
python manage.py makemigrations

python manage.py migrate
👍1
Приветствую.

Пообщавшись в чате с подписчиками, понял, какие интересные и разнообразные личности подписаны на канал и мне стало интересно, откуда вы пришли.
Anonymous Poll
48%
Учусь в GeekBrains 😐
3%
Я с пикабу! 🥳
14%
Нашёл в интернете 🧐
24%
Сам же пригласил 😂
10%
Не скажу 😉
Django 12. Настройка отправки почты

Для большинства сайтов важно иметь возможность отправлять письма пользователям, будь то письмо для сброса пароля или информационная рассылка.

В Django встроен функционал по отправке, однако ему всё же требуется почтовый сервер для отправки почты.

И тут возможны несколько вариантов:
1. Почта будет отправляться через почтовые сервисы, такие как Яндекс, Google или Mail.ru. В таком случае, адрес с которого отправляются письма, будет вида: <название_сайта@gmail.com>, <название_сайта@yandex.ru> или любой другой почтовой службы. Плюс этого способа в том, что он бесплатен и прост в реализации. Минусом конечно же является то, что пользователь вашего сайта, будет получать письмо не от вашего домена, а от сервиса.
👍1
2. Приобрести почтовый сервис для домена. Такая услуга есть и у Яндекса и у Mail.ru и у большинства хостинг провайдеров. В таком случае, у вас будет почтовый адрес вида <info@ваш_домен>. Этот вариант куда привлекательнее, предыдущего. Пользователь будет видеть домен сайта в письме и это положительно скажется. Минусом же является то, что всё стоит денег.
3. Поднять собственный почтовый сервер на VPS. Этот способ позволит контролировать всё, что касается почты и ограничен лишь мощностью сервера и его дисковым пространством. Он достаточно сложен в исполнении, но при этом гарантирует независимость.
Третий вариант отложим на будущее, возможно я напишу, как развернуть свой почтовый сервер.
Остаются первые два пункта, в целом, в плане настроек Django они одинаковые.

Приступим.
Откроем файл settings.py и в самом конце добавим следующий код:
# Настройка почты
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

EMAIL_HOST = 'smtp.yandex.ru'
EMAIL_PORT = 465
EMAIL_HOST_USER = ""
EMAIL_HOST_PASSWORD = ""
EMAIL_USE_TLS = False
EMAIL_USE_SSL = True
SERVER_EMAIL = EMAIL_HOST_USER
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

Разберём по порядку:
- EMAIL_BACKEND - тут мы указываем, какой модуль будет отвечать за отправку почты. Выбираем стандартный для работы по протоколу SMTP.
- EMAIL_HOST - тут мы указываем почтовый сервер. В примере выше, это сервер Яндекс почты, для Gmail это smtp.gmail.com, для других сервисов сервер исходящей почты обычно прописан в справке.
- EMAIL_PORT - порт для подключения к серверу. Обычно это 465, но может и отличаться, читайте справку к интересующему вас серверу.
- EMAIL_HOST_USER и EMAIL_HOST_PASSWORD - в этих полях определяется логин и пароль для подключения к почтовому серверу. Обратите внимание, в качестве логина, передаётся полностью адрес электронной почты!
- EMAIL_USE_TLS и EMAIL_USE_SSL - два параметра определяющих какой тип шифрования используется. Используемый тип, смотрите в справке к почтовому серверу. Обратите внимание, что только один из параметров может быть True, второй обязательно должен быть False!
- И последние два параметра, определяют настройки адреса с которого будет исходить почта.

На этом настройка почты закончена. Ничего сложного, не правда ли? Осталось протестировать, этим займёмся в следующем посте.

Файлы к посту, можно получить в боте по коду: 202223
Пост на сайте.
Поддержать канал.

#django #python #отправка_почты #email
👍1
Django 13. Сброс пароля

Поскольку на сайте пока ничего нет, тестировать будем в админке.
По умолчанию, в окне входа в панель администратора нет кнопки сброса пароля, но такая возможность предусмотрена.

Откроем файл urls.py в директории проекта и в список urlpatterns добавим четыре строки в начало:
from django.contrib.auth import views as auth_views

urlpatterns = [
path('admin/password_reset/', auth_views.PasswordResetView.as_view(), name='admin_password_reset'),
path('admin/password_reset/done/', auth_views.PasswordResetDoneView.as_view(), name='password_reset_done'),
path('admin/reset/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('admin/reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
path('admin/', admin.site.urls),
path('', include('blog.urls', namespace='blog')),
]
👍1
Обратите внимание, новые строки расположены до паттерна входа в панель администратора. Это обусловлено тем, что список читается сверху вниз и если добавить в конец списка, то наши паттерны будут игнорироваться и перекрываться основным, ведущим на страницу авторизации.

Запустим Django и перейдём на страницу авторизации, если вы уже авторизованы в панели, просто в правом верхнем углу нажмите "Выйти".
Над кнопкой входа должна появиться надпись "Забыли свой пароль или имя пользователя?".

При нажатии на неё, откроется страница ввода адреса электронной почты.
Внимание! Если вы при создании суперпользователя не ввели адрес электронной почты, то дальше ничего не получится. Необходимо зайти в панель администратора, в разделе "Пользователи" выбрать вашего пользователя и в соответствующем пункте прописать адрес вашей почты, после чего сохранить и повторить действия.

Вводим адрес электронной почты и нажимаем "Восстановить мой пароль".

На следующей странице увидим сообщение, что письмо отправлено. Перейдём в нашу почту и там уже должно быть письмо. При условии, что вы указали настройки почтового сервера из прошлого поста!

Если письмо пришло, поздравляю! Переходить по ссылке не обязательно, если только не хотите поменять пароль на другой.

Файлы к посту, можно получить в боте по коду: 469410
Пост на сайте.
Поддержать канал.

#django #python #email #сброс_пароля #админка #admin
👍1
Приветствую!

Сегодня запустил бота для канала.
Бот пока умеет совсем не много, а именно у него пока-что, всего одна задача - выдавать материалы к посту.

Для получения архива с файлами, нужно запустить бота, ввести команду /get_file и код из поста.
В ответ придёт сообщение с файлом.

Ссылка на бота: https://t.iss.one/press_any_button_bot

Вполне вероятно, что могут быть какие-либо ошибки или недочёты, если столкнулись с ними, обязательно напишите в комментариях или чате.

А так же если у вас есть интересные идеи для функционала, тоже пишите.

#Новости
Django 14. Модель пользователя бота

Продолжим добавлять функционал боту и Django. Сегодня сделаем модель для пользователя ботом. Это позволит получать статистику по использованию бота прямо в панели администратора Django.

Перейдём в файл models.py в директории приложения и по аналогии с предыдущей моделью, создадим новый класс BotUserModel.
И создадим несколько полей:
class BotUserModel(models.Model):
chat_id = models.BigIntegerField(primary_key=True)
first_name = models.CharField(max_length=50,
verbose_name='Имя')
last_name = models.CharField(max_length=50,
blank=True,
null=True,
verbose_name='Фамилия')
username = models.CharField(max_length=50,
blank=True,
null=True)
created = models.DateTimeField(auto_now_add=True,
verbose_name='Зарегистрирован')
updated = models.DateTimeField(auto_now=True,
verbose_name='Последняя активность')
Разберём, что тут новое:
- В поле chat_id, указали, что это поле является Первичным ключом. То есть, это поле уникально. И использовали поле типа BigIntegerField, поскольку значения Telegram-ID выходят за границы базового IntegerField.
- В полях last_name и username добавили два параметра. blank означает, что поле может быть пустым, а null означает, что оно может иметь значение NULL. Это обусловлено тем, что имя у пользователя Telegram обязательно к заполнению, а вот фамилия или имя пользователя - нет.
- В поле created мы присваиваем текущую, локальную дату(дату сервера). При последующем обновлении модели, это поле не будет изменяться, если конечно его не изменить намерено.
- Поле updated напротив, будет при каждом обновлении модели принимать значение текущего времени.

Добавим базового менеджера, Мета-класс и dunder-метод __str__:
    objects = models.Manager()

class Meta:
ordering = ['-updated']
verbose_name = 'Пользователь бота'
verbose_name_plural = 'Пользователи бота'

def __str__(self):
return self.first_name
В переменную objects мы поместили экземпляр класса Manager. Менеджеры, это удобный способ взаимодействия с объектами в базе данных. С помощью них получаем данные, фильтруем, создаём. В будущем мы переопределим своих менеджеров, но пока достаточно базового.
Из нового в классе Meta только пункт ordering определяющий порядок сортировки записей в базе данных. Для удобства сортировка будет по параметру updated. Обратите внимание на "-", он означает что сортировка будет в обратном порядке, то есть по убыванию, от самых новых к старым.

Перейдём в файл admin.py и зарегистрируем модель в панели администратора:
@admin.register(models.BotUserModel)
class BotUserAdmin(admin.ModelAdmin):
list_display = ('chat_id', 'first_name', 'last_name', 'username', 'created', 'updated')
search_fields = ['chat_id', 'first_name', 'username', ]
Обратит внимание! Если вы регистрировали модель не через декоратор, а через admin.site.register, то код находящийся выше, надо добавлять до строки с регистрацией!
Здесь я указал, что бы отображались все поля модели. Включил поиск по полям chat_id, first_name и username.

Теперь надо применить миграции:
python manage.py makemigrations

python manage.py migrate

Запустим Django python manage.py runserver и убедимся, что модель добавилась в панель администратора.

Файлы к посту, можно получить в боте по коду: 347837
Пост на сайте.
Поддержать канал.

#django #python #модель #бот #aiogram
👍1
Django 15. Пишем API - Добавление пользователя

Теперь давайте напишем API, обращаясь к которому мы будем создавать или обновлять пользователя.

Откроем файл api.py и создадим класс CreateBotUser и статический метод post.
В прошлый раз мы делали метод для GET запроса, в этот раз наш бот не получает, а передаёт данные по API, именно по этому нам нужен POST запрос.
class CreateBotUser(APIView):
@staticmethod
def post(request):


Далее создаём переменную usr_obj в которую мы, с помощью метода get_or_create получим объект пользователя, если пользователь с chat_id уже есть в базе, если же его нет, он будет создан и так же помещен в переменную:
        usr_obj: models.BotUserModel = models.BotUserModel.objects.get_or_create(
chat_id=request.data['chat_id'],
defaults={
'first_name': request.data['first_name'],
'last_name': request.data['last_name'],
'username': request.data['username'],
})[0]
В параметре defaults передаются значения полей, которые будут записаны, если пользователя нет.

Затем, независимо от того, был пользователь только что создан или нет, мы обновляем значение поля updated на актуальное время, вызвав сохранение объекта. И возвращаем пустой ответ со статус-кодом 200:
        usr_obj.save()
return Response(status=200)

Добавим URL-адрес для отправки запроса. Перейдём в файл urls.py и в список urlpatterns отведённый для URL-паттернов нашего API добавим строку:
# Паттерны API
urlpatterns += [
path('bot/get-file/', api.GetFilePath.as_view()),
path('bot/create-user/', api.CreateBotUser.as_view()),
]

На этом создание API закончено, теперь необходимо написать в боте отправку запроса при выполнении команды.

Файлы к посту, можно получить в боте по коду: 786103
👍1
Полезные инструменты - Бесплатный CHAT-GPT4 на вашем сервере

Приветствую.

Буквально вчера мне написал одногруппник и скинул видео. В этом видео рассказывалось о том, как запустить чат GPT у себя на пк. Само видео смотреть не стал, сразу ринулся изучать гитхаб проекта.

Страница проекта: https://github.com/ramonvc/freegpt-webui

В данном проекте собраны различные модели нейросетей. Можно выбрать как GPT-4, так и Sage или Claude.
Вся обработка происходит на сторонних серверах, мы выступаем в роли клиента.

Есть два способа использовать проект.
1. Запускать на локальном ПК.
2. Запускать в Docker-контейнере.

В обоих случаях запуск не вызывает трудностей.
Запуск на ПК.
Для запуска на своём пк, достаточно выполнить несколько действий.
1. Склонировать проект с Github:
git clone https://github.com/ramonvc/freegpt-webui.git

2. Перейти в папку проекта и запустить установку зависимостей:
cd freegpt-webui
pip install -r requirements.txt

3. Запустить скрипт:
python run.py

4. Открыть браузер и перейти по адресу https://127.0.0.1:1338.

Вот и всё. Можно пользоваться.

Запуск в Docker-контейнере.
Тут всё ещё проще.
1. Выполнить команду запуска контейнера:
docker run -p 1338:1338 -d ramonvc/freegpt-webui

2. Открыть браузер и перейти по адресу https://127.0.0.1:1338.

Минимум действий.

Я запускал у себя на сервере в контейнере. Работает отлично, результаты выдаёт относительно корректные, но более подробные что-ли, нежели боты в ТГ.
👍2🔥1
По поводу GPT у людей крайне неоднозначные мнения. И в связи с предыдущим постом, возник вопрос.
Как вы относитесь к GPT? Да и не только к GPT, но и другим подобным нейронкам.
Anonymous Poll
33%
Нравится. Использую постоянно.
37%
Хорошая штука, но пользуюсь редко.
22%
Слышал, но не использую.
4%
Скептически, лучше головой думать.
0%
Категорически против! Точка!
4%
Свой вариант расскажу в комментариях.
AIOgram3 9. Команда start

API для регистрации пользователя написано, теперь нужно сделать команду /start. Эта команда выполняется при первой инициализации бота пользователем.

Без лишних слов. Откроем файл api_actions.py в пакете utils и напишем функцию register_user для отправки данных по API. В качестве аргументов, она будет принимать следующие данные: chat_id, first_name, last_name, username.
Поскольку мы не получаем от API ничего, кроме статус-кода, создавать переменную, как в функции get_path, нет смысла. Сразу обращаемся к библиотеке requests.
В функции выше, мы отправляли GET запрос обращаясь к методу get из библиотеки requests. Сейчас нам необходимо отправить POST запрос, следовательно использовать будем метод post.
Первым параметром, как и ранее будет URL-адрес нашего API, можно взять его из предыдущей функции и изменить f-строку на URL для регистрации f"create-user/".
Вторым параметром будет ключевой параметр data, в котором создаём словарь с данными, где ключ - строка с названием переменной, а значение сама переменная.
def register_user(chat_id, first_name, last_name, username):
requests.post(API_URL + f"create-user/",
data={
'chat_id': chat_id,
'first_name': first_name,
'last_name': last_name if last_name else '',
'username': username if username else '',
})
Стоит учесть, что поля last_name и username могут быть пустыми, по этому при помощи тернарного оператора, мы присваиваем значение переменной или пустую строку.

Обработчик написан, перейдём к созданию команды. В пакете handlers создадим файл simple.py. В этом файле мы будем писать простые команды, не требующие логики, такие как /start, /help, /about.
В файле напишем асинхронную функцию start_command, принимающую аргумент message.
В теле функции сразу вызываем нашу функцию register_user из файла api_actions.py, передавая в неё необходимые данные из объекта message.

chat_id мы получаем обратившись к полю id метода chat - message.chat.id. Остальные переменные получаем из одноимённых полей метода from_user, например, message.from_user.first_name.
После вызова функции отправляем пользователю приветственное сообщение, предварительно создав функцию start_message с текстом в файле views.py.
from aiogram.types import Message

from botlogic import views
from botlogic.utils.api_actions import register_user


async def start_command(message: Message):
register_user(chat_id=message.chat.id,
first_name=message.from_user.first_name,
last_name=message.from_user.last_name,
username=message.from_user.username)
await message.answer(views.start_message())

Откроем файл main.py и зарегистрируем команду, добавив в функцию start после регистрации событий запуска/остановки, следующую строку:
from botlogic.handlers import send_file, simple

dp.message.register(simple.start_command, Command(commands='start'))


Теперь протестируем работу.
Запустим Django и перейдём в панель администратора и откроем страницу модели Пользователи бота. Должно быть пусто.
Теперь в отдельном окне запустим бота и выполним команду /start.
Если, всё прошло удачно, то обновив страницу в панели администратора, увидите свой профиль.

Файлы к посту, можно получить в боте по коду: 260142
Приветствую.

Многие подписчики - студенты в GeekBrains на разных этапах учёбы, а также есть и те, кому просто интересно, полезны эти курсы или нет.

С самого начала обучения, я веду на Пикабу серию постов, о том, что мы проходим, чем я сам занимаюсь и как обстоят дела в целом.

Сегодня(на самом деле завтра) ровно год, как я начал учиться в GB.
Пост про 12й месяц обучения: https://pikabu.ru/story/obuchenie_dvenadtsatyiy_mesyats_10488283

Там же в профиле можно найти посты по другим месяцам.
🔥1
AIOgram3 10. Пара простых команд

Наш бот работает! Однако, в одном из прошлых постов, мы добавляли список команд в меню и помимо /get-file и /start, там ещё была команда /about. Давайте закрепим добавление команд и добавим команду /about и заодно /help.

Начнём с текста. Перейдём в файл views.py и создадим две функции: about_message и help_message. Они ничего не принимают, а просто возвращают соответствующую строку текста.

После того, как вы напишите свой текст, переходим в файл simple.py.
Создадим две асинхронные функции: about_command и help_command.
В теле функций, выполним ответ пользователю на сообщение текстом из ранее созданных функций в файле views.py.
async def about_command(message: Message):
await message.answer(views.about_message())


async def help_command(message: Message):
await message.answer(views.help_message())
Для регистрации данных команд, перейдём в файл main.py и по аналогии с командой старт, сделаем две строки:
    dp.message.register(simple.about_command, Command(commands='about'))
dp.message.register(simple.help_command, Command(commands='help'))


Почти всё, перейдём в файл commands.py и добавим новую команду help в меню. Для этого в списке commands продублируйте любую команду начинающуюся на BotCommand( и заканчивающуюся ),, изменив команду и описание. Список должен выглядеть следующим образом:
    commands = [
BotCommand(
command='start',
description='Начало работы'
),
BotCommand(
command='get_file',
description='получение файла с материалами'
),
BotCommand(
command='help',
description='Помощь по доступным командам'
),
BotCommand(
command='about',
description='Информация о боте'
),
]


Можно запустить бота и убедиться, что команды отображаются в меню. а бот корректно на них реагирует.

На этом с ботом пока всё. Возможно в будущем появится дополнительный функционал. Если у вас есть идеи, оставляйте их в комментариях!

Файлы к посту, можно получить в боте по коду: 209200
🔥2
Приветствую.

С ботом мы пока закончили, его необходимо разместить на сервере. Но тут есть два момента: Запускать на сервере данного бота бесполезно. Но инструкция по запуску, универсальна. Следует ли сейчас делать пост по запуску бота на сервере?
Anonymous Poll
40%
Делать пост
20%
Подождать сайт
40%
Сделать посты и по боту и сайту и общий