• JWT, можно ли таким образом обойтись без Refresh Token?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Основная суть JWT -- обойтись вообще без обращений к БД при аутентификации и авторизации. Судя по
    они грузят API сайта и базу данных

    и
    включить в JWT токен еще хеш пароля

    это не ваш случай, вы всё равно обращаетесь к БД (или будете обращаться для сравнения хеша).

    В таком случае используйте простые токены. Просто строку случайных символов, без нагрузки. Их не надо расшифровывать, загружая CPU. Их можно использовать вечно, в случае компрометации отзывать и создавать новый вручную (конечно, придётся прописать для этого кнопки в ЛК юзера). Протухший простой токен не спалит имейл или атрибуты авторизации, не позволит подделывать токены, в отличие от JWT без рефреша.
    Ответ написан
    Комментировать
  • Как связать объекты созданные в форме Django?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Мне было сложно понять ваш вопрос, потому что в примерах кода много подробностей, не относящихся к проблеме. Попробуйте в следующий раз создать минимальный пример кода, воспроизводящий ошибку (minimal reproducible example).

    По существу вопроса, ваши действия должны быть примерно такими:
    if flatform.is_valid() and objform.is_valid():
        with transaction.atomic()
            flat = flatform.save()
            obj = objform.save(commit=False)
            obj.Flat = flat
            obj.save()
    Ответ написан
    Комментировать
  • Как сделать авторизацию через mail.ru на django?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Я так полагаю, что в вашем примере используется протокол oAuth2. (Неплохо было бы дать ссылку, где конкретно «есть такой пример».)

    В Django нет поддержки социальных логинов (oAuth, OpenID и т. д.) «из коробки». Посмотрите, какой пакет используется для этого на вашем сайте, почитайте его документацию, при необходимости конкретизируйте вопрос.

    Если пока никакого не используется, то я советую python-social-auth.
    Ответ написан
  • Прошу помощи. В каком направлении мне двигаться?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Для начала, мне непонятно, почему все части вашей программы, которые вполне могут выполняться синхронно, работают в потоках. Есть часть программы, которая выиграла бы от многопоточности − сканирование портов, где логично было бы создать по потоку на каждый порт (если портов слишком много, то создать пул потоков, определить стратегию переиспользования потоков, в общем, тут большой простор для творчества), но у вас порты сканируются в одном потоке, последовательно.

    Но давайте притворимся, что так и надо, и поговорим о других проблемах вашего кода.
    • Не стоит использовать глобальные переменные в программах длиннее одного экрана. Вместо global лучше объявить глобальный объект и спрятать flag в него:
      class PortScanner:
          
          def __init__(self):
              self.flag = 0
              
          def animate_menu_up(self):
              print("\n")
              ...
              self.flag = 1


    • Код инициализации программы тоже лучше перенести в __init__() глобального объекта. И основной цикл вынести в отдельный метод, например, run(). Тогда на нижнем уровне у нас останется что-то вроде:
      import ...
      
      class PortScanner:
          ...
      
      if __name__ == '__main__':
          main_obj = PortScanner()
          main_obj.run()

      этот идиоматичный код позволит импортировать класс PortScanner в другой скрипт, а также обеспечит плюсик на собеседовании/ревью,
    • приучайтесь использовать докстринги вместо комментариев:
      def animate_menu_up():
          """ Создание красивого меню (вверх). """

    • лишний цикл while True: в select_mode(),
    • слишком много магии. По мере роста программы становится всё тяжелее держать и сопоставлять в голове всякие абстрактные значения. Вот литералы, которые, по моему мнению, стоило бы определить как константы − или в «шапке» скрипта, или как атрибуты класса:
      MF_INITIAL = 0
      MF_MENU_CENTER = 1
      MF_MENU_DOWN = 2
      MF_SELECT = 3
      
      SCREEN_WIDTH = 50
      ALL_PORTS = [22, 80, 7777, 2516]
      SOCK_TIMEOUT = 0.5
      ANIM_SYMBOL = '~'
      ANIM_DELAY = 0.02

    • такие вещи очень больно стреляют в ногу и почти гарантированно проваливают собеседования:
      except RuntimeError:
          continue
      если вы действительно хотите продолжить выполнение программы после такой ошибки (что в обычных обстоятельствах бессмысленно и опасно), то позаботьтесь хотя бы о правильной индикации:
      import traceback
      ...
      except RuntimeError:
          traceback.print_exc(file=sys.stdout)
          continue

    • раз уж мы задержались здесь, давайте сделаем диспетчер более идиоматичным:
      while True:
          try:
              {
                  MF_MENU_CENTER: th_three.start,
                  MF_MENU_DOWN: th_two.start,
                  MF_SELECT: select_mode,
              }[flag]()
          except RuntimeError:
              traceback.print_exc(file=sys.stdout)
              continue
      Такой наивный подход выводит много шелухи на экран, но это не важно. Важно то, что такой код проще читать и дорабатывать, чем цепочку if...elif...else.

    • Работа со строками тоже напрашивается на улучшения:
      1. нет смысла разбивать строки на списки, к символам в строке можно обращаться так же, как к элементам списка − по индексу и с помощью срезов,
      2. не нужно копировать строки,
      3. не нужно печатать всю строку с начала, это делает анимацию неровной − конец строки печатается медленнее, чем начало. Достаточно допечатать один символ в строке.
      Например:
      def animate_menu_center():
          """ Создание анимации центрального меню. """
          # настройки для анимации
          output_strings = [
              '[1] scan all ports',
              '[2] scan enter port',
              '[3] exit',
              'SCANNER V1.0',
          ]
      
          # анимация названия
          for output_string in output_strings:
              print('\r\t\t', end='')
              for ch in output_string:
                  print(ch, end='')
                  time.sleep(ANIM_DELAY)
              # last string?
              if output_string != output_strings[-1]:
                  # new line
                  print()
      
          print('', flush=True)
          flag = MF_MENU_DOWN
      (Я убрал цвета для простоты.)
    • юзабилити сильно страдает из-за отсутствия нормальной функции выхода из приложения,
    • не оставляйте закомментированный код в файле, который отдаёте на ревью, это минус. Вместо этого напишите комментарий с пометкой “TODO”, например:
      # TODO: реализовать режим '2' (скан произвольного списка портов)
      Это однозначно плюс − показывает, что вы умеете работать в команде и пользоваться системами контроля версий.

    Вроде бы наиболее серьёзные проблемы я перечислил. Выложу более полный вариант кода в комментариях.
    Ответ написан
    1 комментарий
  • Куда сохранять однотипный большой набор данных в Python?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Ответ написан
    Комментировать
  • Как настроить путь к app module в django?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Такое может быть, если забыть положить файлик "__init__.py" в папку с модулем.
    Ответ написан
    2 комментария
  • Какое рабочее окружение лучше подобрать на python?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Начал всерьёз разрабатывать на Python лет 5-6 назад, и сразу в Linux. В то время многие Python-модули требовали компиляции и не запускались в Windows без установки платной и монструозной Visual Studio (причём конкретной версии, скорее всего, устаревшей), а также долгих и упорных плясок с бубном. Позже появился формат `wheel`, бесплатный набор CLI-утилит из VS, хорошо развился `mingw-w64`, и тогда биллибоям стало вроде как проще в пайтон. Но я так и остался на линуксе, что и другим рекомендую.

    Использую `virtualenv` и `pyenv`. Не использую `docker`, для разработчика это оверкилл. Пусть с ним девопс-инженеры любятся. Любимая IDE − `PyCharm`: в ней пишу, дебажу, гоняю тесты и командую гитом. В принципе, пайчармовский дебаггер имеет удалённый режим, которым можно дебажить прямо в контейнере, но пока что от этой фичи имхо больше гемора, чем пользы.
    Ответ написан
    1 комментарий
  • Многозадачный сервер на Python?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Я бы использовал Django channels.
    Ответ написан
    Комментировать
  • Как менять пути к файлам при сборке релиза?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Я не знаю насчёт bash, но вам, наверное, пора научиться делать Python-пакеты при помощи pip и setuptools. Вот хороший гайд, можете пропустить часть “Uploading the distribution archives” и далее, если не хотите делать ваши пакеты общедоступными. И не забывайте про pip install -e.
    Ответ написан
    Комментировать
  • Как это работает(python,super)?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    В данном случае это работает примерно как Car.__init__(self).

    В общем случае super() возвращет класс, ближайший к текущему согласно MRO. Вот вроде неплохая статья на русском: https://habr.com/post/62203/.
    Ответ написан
    Комментировать
  • Как в Python 3 вызвать функцию чьё название написано в строке?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Вообще, сама постановка вопроса кагбе намекает на архитектурные проблемы такого подхода. Но, если решать вопрос «в лоб», то вот самый логичный вариант:

    call_func = input("Введите название функции чтобы её вызвать: ")
    locals()[call_func]()


    Это я подразумеваю, что функции определены в том же неймспейсе, что и call_func. Если они определены в неймспейсе модуля, а call_func − глубже, в функции или методе, то поможет globals(). А если они вообще где-то в других модулях, которые могут не быть импортированы заранее, то нужно копать в сторону importlib.import_module, но это уж точно оверкилл.

    Ну и, конечно, использовать пользовательский ввод тут небезопасно. Не так опасно, как eval, но тоже нехорошо.
    Ответ написан
    Комментировать
  • Как принудительно заблокировать исполнение цикла while и всех циклов что внутри него?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Поместите внешний while в функцию; делайте return для останова всех циклов.

    Управление выполнением через исключение тоже допустимо в Python, но return лучше читается.
    Ответ написан
    Комментировать
  • Что делает фрагмент кода sum = arg[0]?(пояснение ниже)!?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Вот это место в официальных доках:

    https://docs.python.org/3/tutorial/controlflow.htm...

    Вот неплохая статья на эту тему:

    https://tproger.ru/translations/python-args-and-kwargs/
    Ответ написан
    Комментировать
  • Как реализовать парсер?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Используйте Scrapy, оно умеет в потоки.
    Ответ написан
    Комментировать
  • Звук пропадает на Linux Mint, что мне делать?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Когда в следующий раз пропадёт звук, попробуйте запустить `dmesg` в консоли − может, скажет что-нибудь интересное. А так − дело тёмное.

    Ещё можно поиграться с `pavucontrol` (уж не знаю, надо его в Минте отдельно от PulseAudio ставить или нет), запретить вывод в HDMI, например.
    Ответ написан
    Комментировать
  • Поэтапная регистрация Django?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Все этапы может делать одна и та же вьюшка, просто рендерите разный контент в зависимости от состояния данных на сервере:
    1. !user.is_authenticated()
    2. !user.has_usable_password()
    3. Ваша проверка на существование команды

    Хотя другие отвечающие тоже дело говорят: регистрация получается слишком назойливая, боюсь, многие юзеры не дойдут до конца.
    Ответ написан
    Комментировать
  • Что происходит в uWSGI с subprocess.Popen?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Будучи потомственным телепатом, предположу, что вы в файле my_worker.py делаете импорты, которые приводят к запуску встроенного веб-сервера flask. Где-то не хватает идиоматического “if __name__ == '__main__':”.
    Ответ написан
    1 комментарий
  • Как грамотно сделать выборку данных из таблиц БД со связями в Django?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Вы правильно поняли, для зависимых моделей в главной модели создаются RelatedManager'ы с именем ‘<зависимая_модель>_set’. Например, чтобы получить интересующие нас данные в консоли, мы можем сделать так:
    for project in Projects.objects.all():
        print('Title: ', project.title)
        print('Description: ', project.description)
        for preview in project.preview_set.all():
            print('\tImage title: ', preview.title)
            print('\tImage path: ', preview.image)

    Соответственно, чтобы вывести всё с помощью шаблонизатора, нам нужно переписать это на языке шаблонизатора:
    {% for project in project_list %}
        <h2>{{ project.title }}</h2>
        <p>{{ project.description }}</p>
        {% for preview in project.preview_set.all %}
        <h3>{{ preview.title }}</h3>
        <img src="{{ preview.image }}">
        {% endfor %}
    {% endfor %}

    Остаётся только передать модель в контекст шаблонизатора:
    def portfolio(arg):
        ctx = {
            'project_list': Project.objects.all(),
        }
        return render(arg, 'portfolio.html', ctx)

    С тегами всё аналогично, не стал усложнять ответ.
    Ответ написан
    1 комментарий
  • Не могу понять где ошибка?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Начиная с 3 строки:
    instance=request.user

    Но request.user не является instance модели User, это объект специального класса, представляющего анонимного пользователя. Аноним не имеет своего представления в БД.

    Для начала создадим пользователя:
    user_form = UserForm(request.POST)
    if user_form.is_valid():
        user = user_form.save()


    Вот теперь у нас есть модель пользователя в БД, и мы можем её использовать, чтобы создать профиль и т. д.
    Ответ написан
    Комментировать
  • Как определить того, кто парсит мой сайт?

    Tanner
    @Tanner
    Огромный человекоподобный боевой робот
    Лучше MySQL настройте, чтобы не падал. И сделайте облегченную версию сайта для текстовых браузеров и роботов.
    Ответ написан
    Комментировать