• Можно ли писать вирусы на python?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    Можно. Но преимущественно, в учебных целях.

    1) Логичнее писать трояны для программного обеспечения на Python или использующего Python как скриптовой язык для расширений и плагинов.

    2) Написание червей теоретически возможно:
    - либо червь должен таскать с собой стандартный интерпретатор,
    - либо исходники должны быть приведены к эквивалентному коду на C/C++ и скомпилированы (см. python-компилятор Nuitka или язык программирования Cython).
    Ответ написан
    Комментировать
  • Как избавится от автоматического дописывания символов к имени изображения для уникальности?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    Был похожий вопрос:
    Почему когда в django admin в ImageField добавлю картинку то django admin создаёт новую и загружает её?

    Схожим образом проверять совпадение имён файлов, удалять старый файл и загружать новый.

    Но как быть с одноимёнными, но разными файлами? Пользователи сайта будут вольно и невольно подменять уже загруженные изображения на свои. Переносить опыт работы с файловой системой на веб-сайт можно только в случае, если Вы единственный пользователь.

    В случае многопользовательского проекта, для повторного использования изображений стоит завести под них отдельную модель. А в модели статей сделать ForeignKey на модель изображений.
    Ответ написан
  • Дерево каталог на python?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    В любом проекте на Python для работы с реляционными СУБД можно использовать ORM SQLAlchemy.

    Документация по SQLAlchemy:
    docs.sqlalchemy.org/en/latest

    Среди дополнительных пакетов SQLAlchemy сходу нагуглил SQLAlchemy-ORM-tree для организации иерархических структур данных в реляционных СУБД. Пакет реализует паттерн Nested Set.

    Документация по SQLAlchemy-ORM-tree:
    https://sqlalchemy-orm-tree.readthedocs.io/

    Установка пакетов через pip (или для Python3 в Linux -- pip3):
    pip install SQLAlchemy
    pip install sqlalchemy-orm-tree


    Ещё чуть поискал, нашёл пакет sqlamp, реализующий другой паттерн хранения иерархических структур данных -- Materialized Path -- для SQLAlchemy.

    Документация по sqlamp:
    sqlamp.readthedocs.io/en/latest

    Но я бы предпочёл SQLAlchemy-ORM-tree, паттерн Nested Set вроде имеет больше преимуществ и меньше недостатков.
    Ответ написан
    3 комментария
  • Как правильно организовать класс, для генерации методов в нем?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    Быть может лучше принимать ещё один аргумент при вызове?

    class Color:
        def __init__(self):
            self.red = '\033[91m'
            self.green = '\033[92m'
            self.blue = '\033[94m'
            self.cyan = '\033[96m'
            self.white = '\033[97m'
            self.yellow = '\033[93m'
            self.magenta = '\033[95m'
            self.grey = '\033[90m'
            self.black = '\033[90m'
            self.default = '\033[99m'
            self.end_color = '\033[0m'
    
        def color_print(self, data, color):
            print(getattr(self, color) + data + self.end_color)
    
    obj = Color()
    obj.color_print('Текст красного цвета', 'red')
    obj.color_print('Текст зелёного цвета', 'green')
    obj.color_print('Текст синего цвета', 'blue')

    Реализация очень топорная, но как вариант.

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

    Пример решения схожей задачи: https://stackoverflow.com/questions/13194180/dynam...
    Ответ написан
    Комментировать
  • Можно ли называть несколько виртуальных окружений одинаково?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    Если я правильно понял вопрос, могу ответить так.

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

    Однако, часто делают по-другому. Виртуальные окружения создают внутри папок с проектами, в таком случае все виртуальные окружения обычно "называют" env, а исходники проекта лежат рядом -- в папке src.

    Смысл подхода очевиден, в корневой папке каждого проекта у нас в 2 раза меньше папок и файлов. В общем виде так:
    - docs -- документация проекта
    - env -- виртуальное окружение
    - requirements -- папка или файл с зависимостями
    - src -- исходный код вашего проекта

    Если мы используем Git, то чтобы не включать в репозиторий файлы виртуального окружения, в .gitignore мы прописываем всего лишь одну строку:
    env/
    Вместо вот этой ереси:
    bin/
    include/
    lib/
    lib64
    share/
    pip-selfcheck.json
    pyvenv.cfg


    Как недостаток, путь до виртуального окружения на 4 символа длиннее:
    source env/bin/activate

    В остальном, не вижу особой разницы как называть и где размещать виртуальные окружения. Виртуальное окружение -- это просто папка с настраиваемой Python-песочницей.

    Делайте так, как Вам привычнее и/или удобнее.
    Ответ написан
    Комментировать
  • Как сделать кнопку наверх?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    Допустим, страница поделена на три блока: header, main и footer.

    Тогда, кнопка "наверх" должна быть последним элементом внутри main.

    <header>
        <p>Хедер</p>
    </header>
    <main>
        <p>Пример контента</p>
        <a id="page_up_down_button" href="#">Наверх</a>
    </main>
    <footer>
        <p>Футер</p>
    </footer>


    В CSS, кнопке можно прописать:
    #page_up_down_button {
        position: sticky;
        bottom: 0;
    }

    Ну и соответствующие стили, чтобы имитировать кнопку.

    Пример скрипта с использованием JQuery, чтобы кнопка могла возвращать не только наверх, но и на место откуда ею воспользовались:
    <script type="text/javascript">
        var scroll_position = null;
    
        $('#page_up_down_button').click(function(){
            if ($(document).scrollTop() > 0) {
                scroll_position = $(document).scrollTop();
                $('#page_up_down_button').html('Обратно');
                return true;
            } else if (scroll_position > $(document).scrollTop()) {
                $(document).scrollTop(scroll_position);
                $('#page_up_down_button').html('Наверх');
                return false;
            };
        });
    
        function check_status_button(){
            if ($(document).scrollTop() > 0) {
                scroll_position = null;
                $('#page_up_down_button').html('Наверх');
            };
        };
    
        $(window).resize(function() {
            check_status_button();
        });
    
        $(window).scroll(function() {
            check_status_button();
        });
    </script>

    Скрипт лучше размещать ниже кнопки.

    Для работы кнопки, естественно нужно подключить JQuery до скрипта, а лучше в head страницы.

    Например, так:
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
    Ответ написан
    Комментировать
  • Что выбрать Python(Django) или PHP(Laravel/Yii)?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    Я больше знаком с Python экосистемой, поэтому могу быть несправедлив в отношении PHP.

    PHP:
    - проще с работой
    - проще с хостингом
    - язык для веб-разработки

    Python:
    - проще с отладкой кода
    - проще с читаемостью кода
    - проще с безопасностью кода
    - язык общего назначения
    - много самых разных библиотек

    Производительность обоих языков сопоставима и заметно улучшена как в PHP 7, так и в Python 3.6.
    Ответ написан
    1 комментарий
  • Насколько реально собрать систему поиска товаров на питоне?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    Может проще написать API для интеграции сайтов-партнёров и вашего сервиса?

    При добавлении новых товаров, партнёр вручную соотносит их с товарами на вашем сервисе.

    А вот все изменения цен, наличия и пр. с сайта-партнёра должны автоматически переносится на ваш сервис. От сайта-партнёра -- запрос на обновление данных, от вашего сервиса -- ответ с подтверждением, что данные обновлены.

    Большинство интернет-магазинов используют одни и те же CMS, а значит можно написать и предложить основные плагины для интеграции.

    Разработка простого API и написание плагинов кажется более простым и разумным решением, чем собственная поисковая система.

    Я не представляю, как не будучи Google`ом или Яндексом упорядочить классический хаос товарных наименований. Разница в 1-2 символа может быть в написании одной модели товара, разных товаров одного модельного ряда и даже у товаров разных производителей (см. китайские бренды, что на 1 букву отличаются от мировых). А ведь может быть ещё проблема неполных наименований, когда остаётся только гадать какой именно товар имелся ввиду.

    В общем, я бы пошёл решать задачу с другой стороны -- со стороны партнёров.
    Ответ написан
    1 комментарий
  • Как отрдактировать форму регистрации django?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    Maxemp, вкратце.

    Объявить дочерний класс форм, унаследовавшись от UserCreationForm.

    Переопределить метод __init__ дочернего класса, в нём можно поменять что угодно.

    В данном случае, примерно так:

    class MyUserCreationForm(UserCreationForm):
        def __init__(self, *args, **kwargs):
            super(UserCreationForm, self).__init__(*args, **kwargs)
            self.fields['username'].help_text = ''
            self.fields['password'].help_text = ''


    После чего, использовать MyUserCreationForm во вьюхе вместо стандартной UserCreationForm.

    Другой возможный вариант, переопределить у дочернего класса не метод __init__, а вложенный класс Meta. Выглядит примерно так:

    class MyUserCreationForm(UserCreationForm):
        class Meta:
            model = User
            help_texts = {
                'password': '',
                'username': '',
            }


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

    ri_gilfanov
    @ri_gilfanov Автор вопроса
    Web- and desktop-developer
    Спасибо Anatoly Scherbakov, что натолкнул на решение.

    class VariantAttributeForm(ModelForm):
        def __init__(self, *args, **kwargs):
            super(VariantAttributeForm, self).__init__(*args, **kwargs)
            if 'instance' in kwargs:
                self.fields['values'].queryset = Variant.objects.filter(filter=kwargs['instance'].filter)
    
        class Meta:
            model = VariantAttribute
            fields = '__all__'
    
    class VariantAttributeInline(admin.TabularInline):
        form = VariantAttributeForm
    Ответ написан
    Комментировать
  • Как дать имена анонимным юзерам в Django?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    Как вариант -- использование сессий: https://djbook.ru/rel1.9/topics/http/sessions.html

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

    Пример кода, обрабатывающего POST-запросы для временной регистрации, а так же удаления никнейма для анонимного пользователя:
    def chat_login(request):
        # Регистрируем псевдоним для чата на 30 дней
        if 'register' in request.POST:
            request.session.set_expiry(2592000)  # устанавливаем время жизни сессии
            request.session['username'] = request.POST['username']
        # Удаляем псевдоним для чата из своей сессии
        if 'unregister' in request.POST:
            request.session['username'].pop(request.POST['username'])


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

    Недостатки:
    - сложнее проконтролировать уникальность имён пользователей,
    - у сессии должно быть время жизни (хотя его и можно продливать в любой вьюхе, обновив значение любого ключа).
    Ответ написан
    Комментировать
  • Почему когда в django admin в ImageField добавлю картинку то django admin создаёт новую и загружает её?

    ri_gilfanov
    @ri_gilfanov
    Web- and desktop-developer
    По мнению разработчиков Django -- нормально.

    Если хочется изменить такое поведение по-быстрому:
    from django.db import models
    from django.db.models.signals import post_delete
    
    
    def change_image(post_object):
        # функция удаления изображений при их замене на новые
        post_object = self
        try:
            pre_object = post_object.__class__.objects.get(id=post_object.id)
            if pre_object.image != post_object.image:
                pre_object.image.delete(save=False)
        except:
            pass
    
    
    def delete_image(sender, **kwargs):
        # функция удаления изображений при удалении объектов
        try:
            object_ = kwargs.get('instance')
            storage, path = object_.image.storage, object_.image.path
            storage.delete(path)
        except:
            pass
    
    
    class MyModel(models.Model):
        # наша модель с картинкой
        image = models.ImageField(
            upload_to='images/',
        )
    
        def save(self, *args, **kwargs):
            # вызов change_image при сохранении объекта модели
            change_image(post_object=self)
            super(Category, self).save(*args, **kwargs)
    
    
    # прикрепляем функцию delete_image к сигналу post_delete от модели MyModel
    post_delete.connect(receiver=delete_image, sender=MyModel)


    Думал доработать данный костыль в инвалидную коляску, а именно -- так чтобы название поля модели не имело значения. Например, при изменении и удалении объекта, через цикл прогонять все поля модели, чтобы применять проверки и операции ко всем FileField и ImageField в модели.

    По-хорошему же, лучше разобраться с файловыми полями моделей и сделать своё кастомное. Рассматриваемая задача конечно мелочь, но опыт может пригодится.
    Ответ написан
    Комментировать
  • Почему не срабатывает перевод verbose_name для приложений пакета django-allauth, устанавливленного через pip?

    ri_gilfanov
    @ri_gilfanov Автор вопроса
    Web- and desktop-developer
    В файлах локализации с расширением .po, часть переведённых строк имеет пометку нечёткий перевод:
    #, fuzzy
    И игнорируется при компиляции файлов с расширением .mo

    Если нечёткий перевод устраивает больше, чем английский оригинал -- русскую локализацию можно перекомпилировать и с использованием fuzzy-строк:
    python3 manage.py compilemessages --use-fuzzy --locale=ru

    или так:
    python3 manage.py compilemessages -f -l ru

    Результат:
    3de85ce26c9744b9a0de75612755eeab.png

    Благодарю sim3x за точную ссылку в документации.
    Ответ написан
    Комментировать