• Как в админке Django настроить codemirror на подсветку нескольких языков?

    Sergei_Erjemin
    @Sergei_Erjemin Автор вопроса
    Улыбайся, будь самураем...
    Для наложения режимов подсветки в CodeMirror нужно использовать CodeMirror.multiplexingMode. Причем последовательно для каждой пары открывающий/закрывающий тег. Таким образом для смешивания html+jinja2 в админке Django получится вот такой /static/js/codemirror/init_jinja2.js:

    // Этот файл нужен для инициализации html+jinja-редактора шаблонов codemirror в админке Django
    // рецепт написал сам: https://qna.habr.com/q/1284408
    (function () {
      var $ = django.jQuery;
      $(document).ready(function () {
        // Включаем "темную" или "светлую" тему в зависимости от настроек браузера пользователя
        var theme_is = 'idea';
        if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) theme_is = 'rubyblue';  // dark mode
    
        // Включаем подсветку jinja-тегов {{...}} внутри html
        CodeMirror.defineMode("html+jinja2{}", function (config) {
          return CodeMirror.multiplexingMode(
            CodeMirror.getMode(config, "text/html"), {
              open: "{{", close: "}}",
              mode: CodeMirror.getMode(config, "jinja2"),
              parseDelimiters: true,
            }
            );
        });
    
        // Включаем подсветку jinja2-тегов {%...%}
        CodeMirror.defineMode("html+jinja2%%", function (config) {
          return CodeMirror.multiplexingMode(
            CodeMirror.getMode(config, "html+jinja2{}"), {
              open: "{%", close: "%}",
              mode: CodeMirror.getMode(config, "jinja2"),
              parseDelimiters: true,
            }
            );
        });
    
        // Включаем подсветку jinja2-комментариев {#...#}
        CodeMirror.defineMode("html+jinja2", function (config) {
          return CodeMirror.multiplexingMode(
            CodeMirror.getMode(config, "html+jinja2%%"), {
              open: "{#", close: "#}",
              mode: CodeMirror.getMode(config, "jinja2"),
              parseDelimiters: true,
            }
            );
        });
    
        // инициализация codemirror
        $('#code_editor').each(function (idx, el) {
          var editor = CodeMirror.fromTextArea(el, {
            lineNumbers: true,
            tabSize: 2,
            mode: 'html+jinja2',
            gutters: ['CodeMirror-lint-markers'],
            theme: theme_is,
            lint: true,
            autoCloseTags: true,
            matchBrackets: true,
          });
          editor.setSize('120em', 'auto');
          editor.addKeyMap({
            'Ctrl-S': function (cm) {$(el).closest('form').submit(); },     // submit
            'Ctrl-F': 'findPersistent',       // поиск
          });
        });
      });
    })();
    Ответ написан
    Комментировать
  • Как показать определенное количество символов у ссылки а остальные скрыть?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Давайте я погуглю за вас:
    https://webref.ru/recipe/2687
    Правда это не по числу символов, а в размер блока... но тем не менее... Для обрезки по числу символов, по хорошему, для корректной орфограии надо городить скрипт расстановки переносов &shi; и вычислять на каком месте сделать "обрезание" и установку многоточия...
    Ответ написан
    Комментировать
  • Почему в PyCharm под ALT Linux в «чистое» виртуальное окружение «просачиваются» лишние пакеты?

    Sergei_Erjemin
    @Sergei_Erjemin Автор вопроса
    Улыбайся, будь самураем...
    В Alt Linux установку PyCharm (и других приложений JetBrains) можно осуществить несколькими способами. И первый из них -- установка через Flatpak. При его использовании установка и исполнение приложения происходит в некоей "изолированной среде". Таким образом, любое виртаульное кружение, созданное в PyCharm, создаётся внутри в "изолированной среды" Flatpak... При подключении существующего виртуального окружения, "изолированный" PyCharm не имеет возможности взаимодейтвовать с ним напрямую, и просто копирует его (виртуальное окружение) внутрь "изоляции" Flatpak. Виртальное окружение внутри Flatpak как раз и соодежит все эти "просочившиеся пакеты". Поэтому во "внешней среде" (системной) этих пакетов и не видно. Предположительно, это эти пакеты нужны самомому Flatpack и именно поэтому их нельзя ни удалить, ни обновить (зато можно поставить второй пакет радом, и таким образом может существовать одновременно urllib3 разных версий, lol).

    Кроме того, в изолированной среде Flatpak фиксируется внешнее состояние системных пакетоов на момент его развертывания (в данном случае -- на момент установки PyCharm). Все последующие изменения системных пакетов в изолированную среду Flatpack не попадают. И получается следующее: если, например, мы установим в Alt Linux новую версию Python, то при создании (или подключении) виртального окружения c этой версией Python средствами PyCharm, благодаря механизму virtualenv, этот новый Python будет перенесён внутрь "изоляции" Flatpack. Но если, мы доустановим в Alt Linux системные пакеты (например: mariadb-client или libmariadb3), то в изолированную среду Flatpack они уже не попадут(!). Что, например у меня, вызвало шок: в терминале Alt Linux установка pip install mysqlclient проходит, а в терминале PyCharm падает.

    Как лечить?

    В Alt Linux есть второй способ устаноки PyCharm -- c момощью пакетного менеджера snap:
    snap install --classic pycharm-professional
    Среда snap менее изолированна. Она видит (и использует) текущее состояние системных пакетов Alt Linux и ей не нужны никакие внутренние python-пакеты. Таким образом PyCharm не показывает никаких "просочившихся" батареек (их нет, т.к. среда не изолированна).

    Правда возникает другой побочный эффект -- средствами PyCharm не получается с нуля создать "чистое" виртаульное окружение. Можно только подключить существующее. Как устанавливать пакеты в это окружение -- не важно. Можно через pip (в терминале Alt Linux или PyCharm), а можно через графический интерфейс "Settings --> Project Interpeter".

    ----

    Очевидно, что самай лучший способ установки -- с помощью pycharm.sh из дистрибутива JetBrains. Но, такая установки потребует разобраться с JDK внутри Alt Linux и сделать правильные настройки переменных $pycharm_jdk, $jdk_home/$java_home. Для разных версий PyCharm они могут отличаться, так что использование snap под Alt Linux, мне кажется, -- наиболее простой путь.
    Ответ написан
    Комментировать
  • Как установить mysqlclient-коннектор для Python под Alt Linux?

    Sergei_Erjemin
    @Sergei_Erjemin Автор вопроса
    Улыбайся, будь самураем...
    Из-за, что под Alt Linix dev-пакеты имеют то пристаку -dev, то -devel, для MariaDB процесс установки получися следующий:

    sudo apt-get install mariadb-client libmariadb3 libmariadb-devel python3-dev gcc


    После этого в виртуальное окружение mysqlclient ставится штатно:

    pip install mysqlclient

    Все это сработало, для дефолтного для Alt Linux, не текущий момент, Python 3.9.16:

    Collecting mysqlclient
      Using cached mysqlclient-2.2.0.tar.gz (89 kB)
      Installing build dependencies ... done
      Getting requirements to build wheel ... done
      Installing backend dependencies ... done
      Preparing metadata (pyproject.toml) ... done
    Building wheels for collected packages: mysqlclient
      Building wheel for mysqlclient (pyproject.toml) ... done
      Created wheel for mysqlclient: filename=mysqlclient-2.2.0-cp39-cp39-linux_x86_64.whl size=132574 sha256=c166b260e0fc2a846d40df5af021b1a8bd5e5507348571c2f4df23086d01dd26
      Stored in directory: /home/___/.cache/pip/wheels/aa/58/d4/2e7a1d266508fd74887c2f74ec1ae819509bae6711480d8666
    Successfully built mysqlclient
    Installing collected packages: mysqlclient
    Successfully installed mysqlclient-2.2.0
    Ответ написан
    Комментировать
  • Как убрать ошибку при установке pip install mysqlclient?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Судя по всему у вас Windows. Нужно взять скормпилированную батарейку под ваш вариант Python тут: https://www.lfd.uci.edu/~gohlke/pythonlibs/

    После скачивания установка через pip.
    Ответ написан
    Комментировать
  • Как выбрать самую быструю оперативу?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Главное чтобы у памяти был XMP-профиль .... Совместимая память -- это те модели модулей которые были доступны на момент разработки платы (обычно самые передовые на тот момент). От разработки материнки до её продажи проходит несколько лет, появляются новые модели памяти, но их уже никто не тестирует, т.к. конструкторы заняты разработкой очередной передовой модели, для которой надо найти новые передовые и совместимые модули память.

    Скорость оперативки -- только тесты замечают. Но даже там прирост максимум 3-4%., а это специфично подготовленные тесты именно под скорость памяти. В реальных задачах вы никакой разницы не заметите. Так что убиваться за скорость не стоит. Берите рекомендованные частоты под ваш камень и чипсет.

    Еще следует учесть, что если у вас будет заняты больше двух слотов памяти, то чипсеты для Ryzen снижают скорость шины памяти (об этом мелким шрифтом в спецификациях... никто не читает). Так что даже если память оверклокать, она в лучшем случае она будет работать на паспортной скорости. Таким образом рациональнее (и по цене, и по скорости, и по потенциалу апгреда) взять два более емких модуля памяти, чем четыре поменьше.

    UPD: для ии интереснее увеличить память и уровень графической платы. Вы же используете CUDA? Объем оперативки важен только если у вас много предварительных преобразований с большим числом векторов. Скорость оперативки -- почти никак не повлияет.
    Ответ написан
    3 комментария
  • Как запустить функцию бесконечного цикла в django celery при запуске сервера?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Советую вместо Celery использовать django-background-task ... Для фонового парсера более чем достаточно, параллелится по ядрам, можно управлять фоновыми задачами из админки, работает на той-же СУБД что и основной проект (можно и разнести, при желании). Сам же процесс django-background-task запускать при старте при старте системы через systemctl или rc.local
    Ответ написан
    1 комментарий
  • При разбиении пути возникает ошибка. Как пофиксить?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Под widows путь надо записать так:
    'D:\\export\\'
    или юникс-стайл (тоже работает):
    'D:/export/'

    соответсвенно разбиваешь через:
    filename.replace('\\', '/').split('/')
    или:
    re.split( r'[\\/]', filename)
    а лучше:
    os.path.normpath(path).split(os.sep)
    и не забудь про обработку исключений, для случая если файл лежит в корне юниикс-системы.
    Ответ написан
    Комментировать
  • Как победить «Raw query must include the primary key» в Django?

    Sergei_Erjemin
    @Sergei_Erjemin Автор вопроса
    Улыбайся, будь самураем...
    Непонятно почему, но срабатывает так:
    q_filial = TbPeople.objects.raw("SELECT DISTINCT web_tbpeople.szFilial, 1 AS id "
                                    "FROM web_tbpeople ORDER BY web_tbpeople.szFilial;")


    Ну и еще, надо следить какое поле -- первичный ключ. В моем случае ключ был szID и это строковая переменная. Таким образом для моего случая рабочий код вот такой:
    q_filial = TbPeople.objects.raw("SELECT DISTINCT web_tbpeople.szFilial, '1' AS szID "
                                    "FROM web_tbpeople ORDER BY web_tbpeople.szFilial;")


    !!!ПРИ ЭТОМ, ЕСЛИ НЕ СОЗДАВАТЬ ВТОРОГО ФИКТИВНОГО ПОЛЯ С КЛЮЧОМ, ТО УЖЕ НЕРАБОТАЕТ!!! НАПРИМЕР ВОТ ТАК:
    q_filial = TbPeople.objects.raw("SELECT DISTINCT web_tbpeople.szFilial AS szID"
                                    "FROM web_tbpeople;")

    !!ПАДАЕТ!!
    Ответ написан
    2 комментария
  • Почему прирост ОЗУ в 2 раза почти ничего не дает в производительности?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Компьютер сложный аппарат. В нем куча ядер, кросс-соединений, несколько уровней кэша, куча буферов с разными простоями на доступность, несколько видов шин, и т.д. Понятно, что если ты улучшишь что-то одно -в два раза -- то вся эта сложная система в два раза не ускорится... И даже если все ключевые характеристики каждого из компонентов улучшишь в два раза, -- вся система не станет в два раза быстрее...
    Ответ написан
    Комментировать
  • Почему сетевой адаптер перестал получать ip адрес DHCP?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Если клиент (и не один) не получает(ют) адрес по DHCP, то, очевидно, что сервер DHCP, таки, не работает. Если питание "мигнуло", то мог и DHCP-сервер вылететь. Войдите в настройки роутера, посмотрите что там... отключите/включите DHCP, перегрузите "мягко"... Возможно, роутер под замену...
    Ответ написан
  • Как на MacOS правильно подключить Django к БД в Docker?

    Sergei_Erjemin
    @Sergei_Erjemin Автор вопроса
    Улыбайся, будь самураем...
    Пока разбирался, проделал несколько итерация установить/удалить/переустановить (примерно час заняло) -- поэтому не могу сказать, что конкретно сработало. Выводы такие:
    • mysql-connector-python -- не нужен. Похоже именно он вставал колом, и не давал коннекта в базу данных. Похоже, что его притащило в виртуальное окружение во время предыдущих экспериментов, и я его принял за зависимость..
    • симлинки не нужны -- mysqlclient отлично находит сокет базы.

    В результате последовательность действий:
    brew install mariadb-connector-c
    source ~/path-to-project-enveroment/bin/activate
    pip install mysqlclient
    
    # выключаем окружение отключаем системный коннектор (можно не делать)
    deactivate
    brew unlink mariadb-connector-c

    После обновления macOS до 13.0 Ventura потребуется предварительно сделать команду:
    xcode-select --install
    И повторить все еще один раз.

    P.S. Отдельную проблему создает то, что имя хоста на macOS может меняться. У меня код в Django проверяет на каком хосте запущен и подставляет соответствующие настройки в settings.py ... В моем случае, в hostname прописано m1, но проверка через Python показывает:
    import socket
    socket.gethostname()
    'm1.N1'

    Догадки, но кажется добавление N1 как-то связано с моделью домашнего интернет-роутера... Почему macOS его добавляет, а другие компы в сети нет -- загадка. Иногда hostname может становится 'm1.local' (и для этого не надо перезагружаться, достаточно просто чтоб компьютер перешел в режим сна... хотя х.з. ... в macOS гибридный режим сна, и если во время сна перегружается по питанию, внешне это никак не заметно). В общем, это странное поведение hostname тоже попортило немного крови. :)
    Ответ написан
    Комментировать
  • Как сделать анимацию перекрытия в карсели бутстрап?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Какая версия Bootstrap? В 5.1.x, например, надо добавить класс carousel-fade. В первой строчке твоего кода получится:
    <div id="carouselExampleInterval" class="carousel slide carousel-fade" data-bs-ride="carousel">
    Ответ написан
    Комментировать
  • Как в Django переопределить метод «чтение» только в/для админки?

    Sergei_Erjemin
    @Sergei_Erjemin Автор вопроса
    Улыбайся, будь самураем...
    Делается в два действия:

    Во-первых,
    в models.py переопределяем метод save() для нашей модели TbTemplate. Заодно можем переопределить метод delete(), чтобы он ничего не удалял (или наоборот удалял не только запись в БД но и соответствующий файл... или удалял запись в БД, а соответствующий файл переименовывал...). Получим такую модель:
    # -*- coding: utf-8 -*-
    from django.db import models
    from my_app.settings import *
    
    
    class TbTemplate(models.Model):
        """ Шаблоны """
        szFileName = models.CharField(
            primary_key=True,
            db_index=True,
            unique=True, 
            verbose_name="Имя шаблона"
            )
        szJinjaCode = models.TextField(
            verbose_name='Шаблон',
            help_text='Код шаблона (jinja2)'
        )
        szDescription = models.CharField(
            max_length=100,
            verbose_name='Описание'
        )
    
        def __unicode__(self):
            return f"{self.szFileName} ({self.szDescription})"
    
        def __str__(self):
            return self.__unicode__()
    
        # переопределяем save() для записи шаблонов не только в ДБ, но и в файл
        def save(self, *args, **kwargs):
            with open(TEMPLATES_DIR / self.szFileName, "w+", encoding="utf-8") as tmplt_file:
                tmplt_file.write(self.szJinjaCode)
            super(TbTemplate, self).save(*args, **kwargs)
            # TODO: для продакшн, возможно, нужно добавить "дёргание" touch_reload и "моргнуть" uWSGI
    
        # переопределяем метод delete() (пока, не удаляется)
        def delete(self, *args, **kwargs):
            pass
            # super(TbTemplate, self).delete(*args, **kwargs)
    
        class Meta:
            verbose_name = '[…Шаблон]'
            verbose_name_plural = '[…Шаблоны]'


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

    Во-вторых,
    в файле admin.py при определении класса admin.ModelAdmin для управления моделью TbTemplate нужно переопределить метод get_fields() который отвечает за получения полей в форму админки (пришлось искать метод тупо пробуя кучу схожих которые делают что-то похожее, но не то). В результате получаем примерно вот такой вот admin.py:
    # -*- coding: utf-8 -*-
    from django.contrib import admin
    from web.models import TbTemplate
    from my_app.settings import *
    
    class AdminTemplate(admin.ModelAdmin):
        search_fields = ['szFileName', 'szDescription', 'szJinjaCode']
        list_display = ('szFileName', 'szDescription')
        list_display_links = ('szFileName', 'szDescription', )
        empty_value_display = '<b style=\'color:red;\'>—//—</b>'
        actions_on_top = False
        actions_on_bottom = True
    
        def get_fields(self, request, obj=None):
            try:
                with open(Path(TEMPLATES_DIR) / obj.szFileName, "r", encoding="utf-8") as template:
                    obj.szJinjaCode = template.read()
            except (AttributeError, FileNotFoundError, TypeError):
                pass
            return ['szFileName', 'szDescription', 'szJinjaCode']
    
    admin.site.register(TbTemplate, AdminTemplate)


    Теперь, если какие-то внешние силы изменят файл шаблона (или кто-то поменяет код шаблона в БД в обход админки) , то при открытии шаблона на редактирование из админке, данные будут получены из файла.

    Все.

    UPD: в settnig.py проекта надо добавить что-то типа:
    TEMPLATES_DIR = BASE_DIR / 'templates-jinja2'
    Чтоб модель и админка знали в какой каталог лить файлы шаблонов.
    Ответ написан
    Комментировать
  • Как в Bootstrap настроить Поиск?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    ...для этого в form надо указать actionи method...
    Ответ написан
    Комментировать
  • Стоит ли вложить все рубли в покупку пк, чтобы их хоть как-то сохранить?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Сейчас уже поздно... высокая волатильность на почве неопределенности и можно с покупкой комплектующих прогадать... Да и вообще комп -- плохой инструмент инвестиций. Но если нужен комп для дела -- самое время присмотреться к БУ предложениям. На почве паники частных продавцов можно что-то весьма выгодно прикупить (не только компьютеров касается).
    Ответ написан
    Комментировать
  • Как сделать видео из тысячи картинок?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    ffmpeg -- решает почти все проблемы с видео. В случае сборки видео из картинок:

    ffmpeg -start_number 0 -i "generate%4d.png" -c:v libx264 -vf "fps=30,format=yuv420p" out1.mp4


    Соответственно входные файлы: generate0000.png, generate0001.png, generate0001.png и т.д. Выходной -- out1.mp4
    Ответ написан
    Комментировать
  • Как решить проблему с кодировкой в pycharm?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Это не с PyCharm проблема, а с Python... Скорее всего Python 2.7

    Пиши в начале питон-скрипта:
    # coding=utf-8

    Или оформляй UNICOD-строки вот так:
    words = [u'улика', u'улика1']

    Если работаешь с файлами:
    open(path_filename, "w+", encoding='utf-8')
    Ответ написан
    4 комментария
  • Какой комп взять для очень узкой задачи?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    synology ... с доступом через web... но, за 10К -- совсем скромные модели в которые один-два диска, и не более... Но если ставить по 14-16-18Tb -- хватит надолго.
    Ответ написан
    2 комментария
  • Количество фреймворков для фронта и бэка?

    Sergei_Erjemin
    @Sergei_Erjemin
    Улыбайся, будь самураем...
    Может ИТ -- вообще не твоё? Если тебя не прёт от изучения новых фрейморкрв, написания своих свистелок к ним, не чешутся руки все сделать с чистого листа самому (в 80% все эти фрейморки притянуты к проекту за уши) -- то зачем все это? Хороший токарь, сварщик, оператор башенного крана, мастер причёсок -- зарабатывает не меньше ИТ-шника.
    Ответ написан