InternetMaster, это потому что библиотека тупо его в запрос подставляет, а могла бы проверять тип. Но вот сравнивать строковый id с полученным от Телеграма уже не получится.
Артём Смирнов, если хочется роли словами писать, тогда надо varchar(#), где # - максимальная длина. Ну и вообще почитать о том, какие типы бывают в используемой базе данных (у некоторых бывают разные типы: char, varchar, varchar2, nvarchar итд, они могут оказаться где-то одинаковыми, а где-то нет, например, могут быть строго однобайтными или поддерживать юникоды с эмодзями).
int - это целоче число (скорее всего, 4 байта, то есть от -2^31 до 2^31-1), bigint - "большое" целое (скорее всего, 8 байт), но каждая конкретная база может иметь свою систему типов, могут быть типы с разным именем и одинаковой имплементацией или типы с одним именем в разных базах иметь разные особенности...
InternetMaster, с чего бы это удобней? Если их в базу положить, то даже просто на объёме экономишь. Да и при работе с ними всё равно их к int приводить, это лишние вычислительные наносекунды на пустом месте, не надо к такому себя приучать.
OperLop, если я ловлю exception, то конкретный, и как правило делаю что-то связанное именно с ним. Например, у меня тут есть код, который читает бинарный файл, и если прочитано меньше байт, чем ожидалось (к сожалению, в питоне нет нормального способа получить EOF), то кидает кастомное исключение, по которому вызывающая функция прерывает итерацию цикла.
Ловить любые ошибки без разбору и даже не выводить их пользователю уж точно не надо привыкать.
Роман Гончаров, вроде я испытывал проблемы где-то с доступом к полю content - он мог быть пустым, пока не сделаешь read. Не помню обстоятельств. Возможно, от версии библиотеки зависит.
Артём Смирнов, не varchat, а varchar. Не думаю, что там будут миллионы пользователей и тысячи запросов в секунду, так что конкретный тип не столь важен.
Ну, ctx.send обычно в дискорд-ботах, нетрудно ошибиться.
Артём Смирнов, ну если там одно из трёх чисел, то просто числовое поле.
А так вообще зависит от текущей сложности и дальнейших перспектив. Сейчас я вижу, что adm это не признак админа (у которого по логике только два возможных значения "админ" и "не админ"), это скорее группа, статус, уровень или роль пользователя. Если всё идёт к тому, что нужно будет создавать другие "группы" и как-то управлять их уровнем доступа, то может быть даже смысл сразу закладывать для них отдельную таблицу, типа
groups:
- id
- level - уровень группы, чем выше, тем больше прав
- name
- role_id - соответствующая роль дискорда, которую назначать пользователям
При этом если бот будет для разных серверов предназначен, то всё ещё усложняется тем, что роли у каждого сервера свои.
Но нужно ли делать так сложно?
я так понял всё таким можно сделать в отдельном классе все переменные?
Класс с точки зрения синтаксиса языка вполне получится использовать как хранилище переменных (и так иногда даже делают), но это, вообще говоря, не то, для чего они задумывались.
Например, если мы в каком-то классе будем хранить db_name, db_user, db_password и обращаться из разных мест своего кода для получении информации для коннекта к базе, то это плохое решение. В итоге у нас работа с базой размазана по коду, во множестве мест делается коннект к ней, а если, например, мы захотим при коннекте к базе вызывать какой-то запрос (типа set names utf8;), то нам придётся добавлять это в куче мест.
Вместо этого мы можем сдеалать некий класс DB, который принимает параметры базы в конструкторе, а потом в self.connection записывает объект соединения, а запросы передавать в методе execute. Пример такого класса (там Oracle, да и сделано не очень хорошо, например, курсор надо для каждого запроса создавать новый, а не как сейчас сделано, но для понимания идеи сойдёт) https://pastebin.com/y2VLN8Tm
Далее, вместо того, чтобы информацию по пользователям из базы дёргать запросами в разных частях кода, можно сделать отдельный класс User, у которого конструктор умеет загружать данные из базы и записывать в поля класса. Соответственно, можно реализовать, чтобы метод save() этого класса записывал данные обратно в базу. Работа с данными пользователя станет намного нагляднее и удобнее.
Наконец, вместо того, чтобы самому строить красиво организованную работу с базой, можно просто взять готовую реализацию ORM (object-relational model), типа sqlalchemy или peewee, где уже многое сделано заранее, можно просто описать структуру своих объектов и всё остальное доверить ORM. Будет примерно как я описал выше, но намного меньше кода.
Для того и делят логику, чтобы информация о пользователях была не куча переменных из разных кусков кода, а вот такой один объект, в котором есть все данные и реализована какая-то логика. Кстати, о логике: у классов, как правило, должны быть какие-то методы, это не просто мешочек с данными, это некая логическая единица с какой-то функциональностью.
Можно посмотреть для сравнения, как всё устроено в самом discord.py: вот пользователь (User), вот сервер (Guild), вот член гильдии (Member), он же одновременно и пользователь, но не совсем, так как пользователь на каждом сервере имеет свой объект Member. Возможности и назначение каждого класса свои. Например, если нам надо послать пользователю личное сообщение, то его надо слать User, а если упомянуть его в чате конкретного сервера - то Member. И у всех этих объектов есть не только поля (переменные), но и методы (функции).
Вот самое неправильное что надо делать с ошибкой - это заметать её под ковёр. А вдруг в итоге через год обнаружится, что ошибка-то означала неправильность программы вообще и считала она погоду на Марсе?
Ornitier, нет, но можно, например, реакцию на /start вынести в отдельную функцию, которую вызывать и из обработчика /start, и из обработчика кнопки "вернуться в самое начало времён".
Делить надо не на "категории и файлы", а логику и функциональность. Например, вот интерфейс к базе, вот реестр пользователей (может использовать базу через первый модуль), а вот логика самого бота (её тоже можно делить на части: тут считаем статистику, там обрабатываем команды показа рандомного котика...).