• В чем проблема с таймзоной?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    А с чего вы взяли, что время должно быть 17:54?
    2017-09-05T14:54:36+0300 стоит читать как "5 сентября 2017 года, время 14:54:36 по часовому поясу UTC+03"
    То же самое время в UTC будет выглядеть вот так: 2017-09-05T11:54:36+0000
    Ответ написан
    2 комментария
  • Как организовать схему БД?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Что является более грамотным - довольно скользкая тема.
    Более правильное академически - нормальные формы и т.п.?
    На практике частенько приходится отходить от норм реляционной теории данных. Например, дублировать данные, чтобы местами избежать джойнов в запросах, которые будут выполняться очень часто.

    Если комментарии и к вопросам и к ответам - одинаковая сущность, то я бы сделал их одной таблицей. И в ней 2 поля (помимо прочих):
    question_id - связь с вопросом; всегда существует.
    answer_id - связь с ответом; NULL если был прокомментирован именно вопрос.
    Таким образом, мы можем запрашивать комментарии без необходимости джойнить таблицы, как ко всему вопросу и его ответам, так и отдельно к вопросу, и к конкретному ответу на вопрос.
    Ответ написан
    Комментировать
  • Как в консоли передать скрипту 2 файла в качестве аргумента?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Ну, вы уже передали имена файлов в скрипт как аргументы. Осталось научиться принимать их.
    import sys
    print(sys.argv)

    sys.argv - список переданных аргументов, причём первым идёт имя самого исполняемого скрипта.
    Ответ написан
  • Что за магия в работе Celery с использованием Docker?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Воу-воу, сам на днях буду переносить celery в docker.
    Но ваш вопрос немного не о том. Он скорее о понимании, как вообще работает celery.

    Неужели все содержимое такса каким-то образом передается через брокер и ему неважно, где располагается код? Или передается только имя+сигнатура.

    Только описание, какое задание надо выполнить, с какими входными параметрами. Никакого кода не передаётся.

    Возьмём Django + Celery.
    Типичный, описанный в документации и используемым самим celery для интеграции с django, шаблон использования таков: вы создаёте в django-приложениях файл tasks.py, в котором создаются функции, декорируемые @task. В этих функциях вы описываете логику этих заданий.

    В таком случае, веб-приложение и воркеры используют один и тот же код. И в контейнеры django_web и celery_worker надо упаковывать одно и то же. Просто запускаться это будет по разным сценариям: django_web будет обрабатывать http-запросы, celery_worker будет обрабатывать поступающие задания.
    Ответ написан
  • Как ключ переместить в значение?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Не надо строить строку, передавайте данные нативным javascript-объектом. Например:
    $.ajax({
                url: url,
                type: "POST",
                data: {mail: myMail, passw: myPassword},
    ...
    Ответ написан
  • Как запускать Celery сразу с учетом виртуального окружения?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Ну так, у вас в проекте, наверное, есть файл с зависимостями. requirements.txt, например. Где помимо прочих зависимостей, также должен быть прописан сельдерей нужной версии:
    ..
    celery==X.Y.Z 
    ..

    На проде одним из шагов вашего процесса релиза, наверное, является установка/обновление этих зависимостей:
    pip install -r /path/to/requirements.txt
    Следовательно, вы имеете в вашем venv'е установленный celery. Наверное.
    Ну и просто запускайте его оттуда, и всего делов. Тем же способом можно, просто путь до исполняемого файла будет указывать внутрь вашего виртуального окружения с проектом, типа:
    /path/to/virtualenv/bin/celery --params ....
    Ответ написан
    1 комментарий
  • Как в django admin сортировать в редакторе поля в выпадающем списке?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Посмотрите 2 топовых ответа, в них описаны 2 возможных способа решения вашей задачи.
    https://stackoverflow.com/questions/18742632/how-t...
    1. Задать Meta.ordering в модели, на которую ссылается ваш внешний ключ
    2. Переопределить метод formfield_for_foreignkey в классе админки вашей модели
    Ответ написан
    Комментировать
  • Возможно ли узнать местоположение телефона без интернета?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Определить местоположение можно и без интернета - работайте с GPS.
    Передать определённое местоположение куда-либо без интернета - ну разве что SMS.
    Ответ написан
    Комментировать
  • Как правильно делать бекапы базы Postgresql на продашн сервере?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    По крону, примерно раз в день?

    Можно и чаще, смотря, насколько чувствительно будет потерять данные между бэкапами. Если совсем-совсем чувствительно, нужно задуматься о поднятии реплики или о постоянном бэкапе (используя WAL-журналы).

    И потом их закачивать на aws и dropbox?

    Хоть куда, но обязательно куда-нибудь закачивать на совершенно отдельный сервер/сервис, с проверкой, что всё успешно закачалось.
    И лучше - на 2 разных хранилища.

    Может, на мыло тоже отправлять на всякий случай?

    Ну, чисто факультативно можно, хотя смысла в этом я лично не вижу, если вы закачиваете бэкап на другие сервера/сервисы.
    Т.е. на мыло вы можете слать, а можете и не слать, но закачивать бэкап на 1-2 других сервера/сервиса - необходимо.

    Из личного опыта. Тру-админы, просьба поправить, если где-то косячу.
    Написал bash-скрипт, который запускаю по крону раз в 3 часа. Скрипт
    • делает бэкап обычным pg_dump, в несколько потоков, в формате папки (--format=d)
    • проводит тестовое восстановление бэкапа. Чисто в лоб - завершится ли pg_restore с нулевым кодом возврата
    • сжимает бэкап БД и файлов в архив
    • отправляет архив на отдельное ftp-хранилище
    • отправляет архив на ещё одно ftp-хранилище
    • отправляет краткий лог всего процесса (с метками времени) в корпоративный slack

    Пока храню всё, не вычищая старого (с местом проблем нет). В идеале, видимо, нужно хранить по схеме
    • N (где N - несколько десятков) последних
    • 4-6 последних еженедельных
    • 2-4 последних ежемесячных.
    Ответ написан
    3 комментария
  • Как в Gmail убрать тостер из спама?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    1. Заходите в папку Спам, в строке поиска добираете "тостер", в итоге получится "in:spam тостер", фильтруете
    2. Выделяете все найденные письма, если предложит выделить вообще все - ок
    3. Выбираете из панельки сверху "Ещё -> Не спам". У выбранных писем удалится ярлык "спам" и они перейдут во Входящие

    Профит. У меня с недели 2 назад, как начал активно на тостере сидеть, был такой же кейс. Гугл вроде понял меня с первого раза, помогло полностью.
    Ответ написан
    Комментировать
  • Redirect в django?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    from django.shortcuts import redirect

    у вас можно модифицировать первую строчку кода вот таким образом:
    from django.shortcuts import render_to_response, redirect
    Ответ написан
    3 комментария
  • Можно ли откатиться на python3.5 без потери установленных модулей?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Если вы про те самые модули, которые устанавливаются через pip, то:
    1. выводите список установленных модулей c их версиями, и сохраняете его в файл с именем, например, requirements.txt:
      pip freeze
    2. после установки другой версии питона устанавливаете все модули из файла со их списком:
      pip install -r path/to/requirements.txt

    Ну и, вообще хорошей практикой считается иметь файл зависимостей в проекте, чтобы можно было их все одной командой устанавливать при надобности
    Ответ написан
    6 комментариев
  • Через какой сервис лучше всего организовать рассылку по почте?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Посоветую sparkpost, полтора года назад переводил проекты на основном месте работы на него. Если ничего не изменилось за это время - то там всё ок, на бесплатном аккаунте лимитов - за глаза.
    PYPI package, есть интеграция с Django

    UPD:
    Мда, кое-что за это время всё же изменилось. Полтора года назад лимит на бесплатном аккаунте был 100к писем в месяц, сейчас 15к.
    Ответ написан
    3 комментария
  • Разлогинивание пользователя при повторном входе на другом компьютере?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    https://github.com/pcraston/django-preventconcurre...
    Мельком глянул, принцип работы: уничтожает предыдущую сессию пользователя, если она была, тем самым "разлогинивая" его на предыдущем устройстве.
    Ответ написан
    Комментировать
  • Как установить Python библиотеку для определенного интерпретатора?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Вы можете изменить путь установки пакетов PIP.
    Посмотрите здесь: https://stackoverflow.com/questions/24174821/how-t...
    Ответ написан
    1 комментарий
  • Как установить Python/Django на cPanel?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Можно потратить время более продуктивно, например, с DO

    Сам не люблю, когда вместо ответа на конкретный вопрос начинают критику и восхваление куликом своего болота, но может не стоит оно того - django + shared-хостинг с cPanel? Тем более, как вы пишете, вы уже "обшарили все сайты". Может вы и не хотите сильно углубляться в настройку и администрирование серверов - так и не надо сильно, но базовые скиллы в этом точно никому не помешают - больше и не надо для простой настройки своего дроплета/VPS по пошаговой инструкции.
    Ответ написан
    Комментировать
  • Как сделать переодичные задачи с celery, выставляемые пользователем?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    В той же документации указывается на возможность написания своих классов шедулеров вместо дефолтного PersistentScheduler
    Там же пишут о django-celery-beat - удобном решении для админки, в котором можно редактировать расписание заданий.
    Ответ написан
    Комментировать
  • Как использовать сессии на двух сайтах в django?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Два сайта на разных доменах не могут увидеть куки друг друга (браузер просто не отправит чужие куки), и соответственно - сессию тоже не удастся разделить.

    Если есть ресурсы сделать всё хорошо, то можно заморочиться с OAuth2. Этот протокол, грубо говоря, позволяет авторизоваться на одном из сайтов с помощью другого. Например, так во всём интернетике работает авторизация по соцсетям. Есть хорошая библиотека django-allauth, которая поддерживает авторизацию для очень многих провайдеров.

    Если вам использование какой-нибудь соцсети не подходит (то есть вы сами хотите выступать как провайдер), то в вашем случае я вижу 2 варианта:
    • авторизовываться на одном из этих двух сайтов с помощью второго. То есть, один из сайтов будет провайдером OAuth2
    • то же самое, но сделать для этого отдельный проект (который и будет провайдером OAuth2), чисто для авторизации на ваших двух сайтах. Так работают, например, проекты TM: для авторизации на сайтах habrahabr.ru, geektimes.tu, toster.ru и т.д. используется id.tmtm.ru
    Ответ написан
    Комментировать
  • Как изменить имена ключей в словаре python?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Возможности просто переименовать ключ в словарях питона нет.

    Пример присваивания новому ключу значение из старого ключа, с удалением старого ключа.
    dictionary[new_key] = dictionary.pop(old_key)

    Если же вопрос ваш в том, как построить сам алгоритм замены, то могу предложить следующий:

    # словарь
    d1 = {1:'a', 2:'b', 3:'c', 4:'d', 5:'e'}
    # словарь замен: ключ - исходный ключ из d1, значение - на какой ключ его меняем
    replacements = {1: 'one', 4: 'four', 5: 'five'}
    
    for i in d1:
        if i in replacements:
            d1[replacements[i]] = d1.pop(i)
    Ответ написан
    5 комментариев
  • Демон в celery для django: какнастроить?

    Assargin
    @Assargin
    Перед ответом смотрю наличие ✔ в ваших вопросах
    Прежде всего хочу обратить внимание вот на это:
    Выбрал вариант с celeryd

    Если вы "выбирали" между celeryd или celerybeat, то тут выбор бессмысленен: celeryd - демон для выполнения заданий, celerybeat - следит за расписанием заданий, отправляя их в заданное время на выполнение. Так что, если у вас есть надобность выполнять задания по расписанию, настраивать надо оба демона.

    Теперь немного ответов на вопросы.

    CELERY_APP - что сюда вписывать?

    Это экземпляр класса celery.Celery, вот путь до него и надо прописать, в формате package[.subpackages].module:variable. Например, у меня есть файл project/celery.py, в котором создаётся экземпляр таким образом:
    from celery import Celery
    
    app = Celery('project')

    И я впишу в CELERY_APP значение project.celery:app
    У вас наверняка подобный код тоже есть в проекте, если вы делали по документации

    И как создать celery-пользователя? Погуглил, но не понял ответа.

    Я для всего проекта использую одного пользователя, того, под которым django выполняется (у меня webapp)

    И почему CELERYD_CHDIR="/opt/Myproject/"? Так и не понял, зачем нужен редирект куда-то (а я так понял, это адрес, куда переместиться во время работы). Зачем это нужно и помешает ли сохранять получаемые данные (сохранять изображения в папках) по относительным адресам в django-проекте?

    Эту опцию не использую, вместо неё у меня используется WorkingDirectory на уровне systemd, но смысл абсолютно тот же.
    Это не редирект, это просто указание рабочей папки, относительно которой будет запускаться ваш демон. При правильной настройке работа проекта в режиме celery-воркера ничем не должна отличаться от работы проекта в веб-режиме. На уровне кода никаких ветвлений на тему "если я демон - то делай так, а если нет - делай эдак" быть не должно (и я даже не знаю, как их вообще делать).

    CELERY_BIN="/usr/local/bin/celery"
    Прошел по пути, никакого celery там не увидел.

    Ну блин, куда вы установите celery, там его исполняемый файл и будет. Например, у меня все python-зависимости, куда входит и celery, установлены в virtual env'е, и путь до него такой: /home/webapp/Env/project-backend-3.5/bin/celery

    2. Что делать после настройки? В документации указано что-то про django-настройки и пояснено значение переменных, прилагается несколько кусков кода, но даже с переводчиком не могу понять их назначения.

    Что делать после того, как я сделаю оба файла celeryd пригодными для работы?

    После настройки - запускать, тестировать, отлаживать. Всё как обычно.

    CELERYD_SU_ARGS="-l"
    Что это? Зачем это?

    Не знаю, и видимо, не нужно. Там даже написано, что не рекомендуется.

    Вот мои конфиги (для systemd), делал на основе конфигов из официальной репы celery.

    Файл сервиса celeryd (/etc/systemd/system/celery.service):
    [Unit]
    Description=Celery Service
    After=network.target redis.target
    
    [Service]
    Type=forking
    User=webapp
    Group=webapp
    EnvironmentFile=-/etc/systemd/celery.conf
    WorkingDirectory=/home/webapp/project_dir/project/src
    PermissionsStartOnly=true
    ExecStartPre=-/bin/mkdir -p ${CELERYD_STATE_DIR}
    ExecStartPre=/bin/chown -R ${CELERYD_USER}:${CELERYD_GROUP} ${CELERYD_STATE_DIR}
    ExecStart=/bin/sh -c '${CELERY_BIN} multi start \
        ${CELERYD_NODES} \
        -A ${CELERY_APP} \
        --pidfile=${CELERYD_PID_FILE} \
        --logfile=${CELERYD_LOG_FILE} \
        --loglevel=${CELERYD_LOG_LEVEL} \
        ${CELERYD_OPTS}'
    ExecStop=/bin/sh -c '${CELERY_BIN} multi stopwait \
        ${CELERYD_NODES} \
        --pidfile=${CELERYD_PID_FILE}'
    ExecReload=/bin/sh -c '${CELERY_BIN} multi restart \
        ${CELERYD_NODES} \
        -A ${CELERY_APP} \
        --pidfile=${CELERYD_PID_FILE} \
        --logfile=${CELERYD_LOG_FILE} \
        --loglevel=${CELERYD_LOG_LEVEL} \
        ${CELERYD_OPTS}'
    
    [Install]
    WantedBy=multi-user.target


    Файл сервиса celerybeat (/etc/systemd/system/celerybeat.service):
    [Unit]
    Description=CeleryBeat Service
    After=network.target redis.target rabbitmq.target
    
    [Service]
    Type=simple
    User=webapp
    Group=webapp
    EnvironmentFile=-/etc/systemd/celery.conf
    WorkingDirectory=/home/webapp/project_dir/project/src
    PermissionsStartOnly=true
    ExecStartPre=-/bin/mkdir -p ${CELERYBEAT_STATE_DIR}
    ExecStartPre=/bin/chown -R ${CELERYD_USER}:${CELERYD_GROUP} ${CELERYBEAT_STATE_DIR}
    ExecStartPre=/bin/rm ${CELERYBEAT_SCHEDULE}
    ExecStart=/bin/bash -c '${CELERY_BIN} beat \
        -A ${CELERY_APP} \
        --workdir=${CELERYBEAT_WORKDIR} \
        --pidfile=${CELERYBEAT_PID_FILE} \
        --logfile=${CELERYBEAT_LOG_FILE} \
        --loglevel=${CELERYBEAT_LOG_LEVEL} \
        --schedule=${CELERYBEAT_SCHEDULE}'
    ExecStop=/bin/systemctl kill celerybeat.service
    
    [Install]
    WantedBy=multi-user.target


    Файл конфигурации сервисов celeryd и celerybeat (/etc/systemd/celery.conf):
    # See
    # http://docs.celeryproject.org/en/latest/tutorials/daemonizing.html#available-options
    
    # Common Celery Settings
    CELERY_BIN="/home/webapp/Env/project-backend-3.5/bin/celery"
    CELERYD_USER="webapp"
    CELERYD_GROUP="webapp"
    CELERY_APP="project.celery:app"
    
    # Common env settings
    DJANGO_SETTINGS_MODULE=settings.production
    LC_ALL=ru_RU.UTF-8
    LC_LANG="ru_RU.UTF-8"
    LANG=ru_RU.UTF-8
    
    # Worker settings
    CELERYD_NODES="w1 w2 w3 w4 w5 w6"
    CELERYD_OPTS="-Q:w1 default --autoscale:w1=8,4 \
    -Q:w2 queue2 --autoscale:w2=6,2   \
    -Q:w3 queue3 --autoscale:w3=8,2 \
    ....................
    -Q:w6 queue6 --autoscale:w6=6,2       "
    
    CELERYD_MULTI="multi"
    CELERYD_STATE_DIR="/var/run/celery"
    CELERYD_PID_FILE="/var/run/celery/%n.pid"
    CELERYD_LOG_FILE="/var/log/celery/%n.log"
    CELERYD_LOG_LEVEL="INFO"
    
    # Beat settings
    CELERYBEAT_STATE_DIR="/var/run/celerybeat"
    CELERYBEAT_PID_FILE="/var/run/celerybeat/beat.pid"
    CELERYBEAT_LOG_FILE="/var/log/celery/beat.log"
    CELERYBEAT_LOG_LEVEL="INFO"
    CELERYBEAT_SCHEDULE="/var/run/celerybeat/schedule"
    CELERYBEAT_WORKDIR="/home/webapp/project_dir/project/src"
    Ответ написан
    5 комментариев