• В чем отличие type и interface. В каких случаях что использовать?

    @maltsever
    Привет! Грубо говоря, интерфейс лишь описывает функциональность. А класс, который реализует этот интерфейс, должен конкретно функциональность определить. Например:
    interface IVegetable {
        name: string;
        getCalories(): number;
    }

    А конкретный класс:
    class Tomato implements IVegetable {
        name: string = 'Tomato';
        getCalories() {
           return 18;
        }
    }

    Type - это лишь типизация какой-то переменной, как правило, нестандартной, Например, мы хотим определить тип, который будет описывать степень готовности стейков:
    type SteakRoast = 'medium' | 'rare' | 'welldone';
    Таким образом, мы можем присвоить переменной типа SteakRoast только эти предопределённые значения, а иначе Typescript заорёт из-за несоответствия типа.
    Ответ написан
    3 комментария
  • Как сгенерировать svg из waveform от голосового сообщения во ВКонтакте?

    @ar5
    Для начала понять как формируется путь и из каких параметров он состоит.
    https://developer.mozilla.org/ru/docs/Web/SVG/Tuto...

    Дальше можно увидеть что рисуется вертикальная линия. А после M стоит сдвиг вправо.
    Как бы я сделал. Обошел бы массив и добавлял бы в массив строковые значения, которые бы потом объединил.

    Вот код если хочешь поразбирайся. Первый параметр это waveform а второй я не понял какое-то число от 127 до 128.

    function s(e, t) {
            t = Math.round(t), e.length != t && (e = a.fastResample(e, t));
            for (var n = "", i = 0, r = 0; r < e.length; r++)
                i = Math.floor(10 * e[r] * .95), 0 == i && (i = .5), n += "M" + (3 * r + 1) + "," + (10 - i) + "v" + 2 * i + "Z";
            return '<svg class="audio-msg-track--wave" width="' + 3 * e.length + 'px"><path d="' + n + '"></path></svg>'
        }
    
    function a.fastResample(e, t) {
            var n = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : "peak";
            return new l({
                srcSampleRate: e.length,
                dstSampleRate: t,
                normalizeAlgorithm: n,
                truncateTo: 0
           }
    Ответ написан
    Комментировать
  • Какие шаблоны проектирования js применяются на практике чаще всего?

    sfi0zy
    @sfi0zy Куратор тега JavaScript
    Creative frontend developer
    какие паттерны применяются чаще всего на практике и где

    Сразу отмечу, что все это чисто мое имхо, которое может не совпадать с мнением окружающих. В контексте фронтенда обычно все довольно просто. По моим наблюдениям в среднем сайте могут иметь смысл:
    1. Модули (делим код на независимые части)
    2. Фабрики (для компонентов интерфейса)
    3. Синглтоны (для хранилищ, точек сбора полифиллов / утилит и.т.д.)
    4. Адаптеры (для зависимостей и полифилов, которые могут измениться / выпилиться)
    5. Наблюдатели (для сбора происходящих событий в одном месте)
    6. Хранители (для сохранения действий пользователя и "Ctrl-Z")
    7. Стратегии (если действуем в зависимости от прилетевших данных)

    Другим паттернам применение вижу редко, только если под какую-то замороченную бизнес-логику. Хотя кого я обманываю, на среднем сайте обычно происходит только один паттерн - доширак из костылей. Ну и стоит сказать, что SPA-фреймворки имеют свойство навязывать свои подходы к решению задач, но это отдельная тема.

    Важно понимать, что паттерны проектирования - это просто хорошие идеи по поводу того, как организовать большой объем кода в той или иной ситуации. Это не "изучи тайное знание, запомни, и делай так всегда", не "используй паттерны, потому что великие их используют", это скорее "если не уверен как организовать код, возьми готовую идею, она вроде работает". Если вы будете просто решать задачи, то через N лет практики вы сами их все "изобретете", только не будете знать, что у них есть названия. Эффективно будет организовать себе заметку о том, какие из этих идей для чего примерно применяют, а потом, в процессе работы, в нее подглядывать, если встал вопрос "как организовать этот код".
    Ответ написан
    7 комментариев
  • Насколько pushstate дружит с SEO?

    Если аналитика стоит через ГТМ, то нужно к тегу аналитики добавить триггеры all pages и history change с такими настройками.
    Ответ написан
    1 комментарий
  • Как лучше собрать и получить данные для ajax запроса из массива объектов?

    @vuldozer
    Если я верно понял, то ты обходишь ДОМ 2 раза? Один раз вставляешь сообщения, второй раз вставляешь имена юзеров?
    Я бы ждал пока все соберется, а потом один раз обошел. Разницы нет показывается ли сообщение от неизвестного юзера лишнюю секунду или нет
    Ответ написан
    1 комментарий
  • Как залить в чужой репозиторий на GIthub?

    b0nn1e
    @b0nn1e
    Alcohol & Ruby on Rails
    1. Копируете себе локально репозиторий.
    git clone url [folder]
    cd [folder]
    2. Создаете ветку [branch_name]
    git checkout -b [branch_name]
    3. Делайте изменения
    4. Делаете один коммит или несколько.
    git add . (если создавали новые файлы)
    git commit -am "Added beautiful fixes"
    5. Создаете удаленную ветку.
    git push --set-upstream origin [branch_name]
    В дальнейшем когда удаленная ветка создана то просто
    git push
    6. Создаете в интерфейсе github pull-request. Из вашей ветки в master.
    8536993405.png
    7. автор или вы сами вливаете(merge)/отклоняете(decline) pull-request.
    На этом этапе можно добавить комментарии или замечания к коду, что-то исправить.
    8.Когда пул-реквест влили, вы локально переключаетесь в master и забираете все изменения
    git checkout master
    git pull

    Если еще нужно что-то сделать повторяете шаги начиная со 2.
    Ответ написан
    Комментировать
  • Чему равен контекст в setTimeout?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега JavaScript
    Исходя из определений, при вызове функции (даже внутри метода объекта) ее this равен глобальному объекту, в данном случае window.

    Исключением является как раз стрелочная функция, которая захватывает контекст не в момент вызова, а в момент объявления.
    Ответ написан
    1 комментарий
  • Чему равен контекст в setTimeout?

    rockon404
    @rockon404
    Frontend Developer
    Стрелочные функции не создают собственный контекст this, а используют this окружающего контекста, того места где они определены. В вашем случае это контекст вызова log. setTimeout просто вызывает колбек по истечению таймера, по аналогии с вызовом f.apply(null [, args]);
    Ответ написан
    1 комментарий
  • Как правильно организовать структуру SPA + Backend?

    @wearemieta
    BEWARE HIPSTERS
    Но бесит, что там нет единого собранного файла bundle.js

    В шаблоне webpack-simple все скрипты собираются как раз в один файл build.js. Обратите внимание, он подключается в сгенерированный index.html. vuejs-templates/webpack-simple.

    Этот файл недоступен в файловой системе при запуске dev сервера, потому что в режиме разработки он находится исключительно в памяти.

    так он еще создает кучи других непонятных файлов и при режиме разработки запускает ненужный 'hot-load'.


    Давайте разберемся, для чего нужен сервер в режиме разработки для Vue. При написания SPA приложения вы используете кучу библиотек, файлов в разных форматах и возможно еще обращаетесь к стороннему API(например twitter). Плюсом, вам хотелось бы использовать транспайлер, чтобы в js можно было красиво писать стрелочные функции и использовать другие вкусняшки ES2015. А еще это здорово было бы склеивать файлы одного формата в один большой для разных оптимизаций. Плюс, после того как вы измените что-то в одном файле, не пришлось бы тыкать каждый раз на перезагрузку страницы. Примерно эти вещи делает за вас dev сервер с webpack в режиме разработки.

    — с помощью webpack вы можете собирать ваши файлы каким угодно образом и складывать их в любое удобное место в фс.
    — вы можете их склеивать, минифицировать и использовать транспайлеры, препроцессоры, постпроцессоры и прочее.
    — вы можете обращаться к стороннему API с локалхоста.
    — если вам не нужен hot-load — отключите его в конфиге.

    Оставить в покое django под портом :8000, а VueJS под :8080. И в nginx как-то слушать их обоих, раздельно, таким образом четко разделить фронт от бэка. Не будет ли проблем?


    Проблем с проксированием nginx'ом? Не очень понятно что вы имеете в виду.

    Если вам нужен кастомный шаблон vue-cli то вы можете легко его разработать один раз и в дальнейшем использовать: Vue-cli custom templates

    Как правильно организовать структуру SPA + Backend

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

    Дело в том, что возникновение таких вещей типа SPA напрямую связано с разными парадигмами разработки. Django как фреймворк позволяет вам писать монолитные приложения. Вы пишете одно большое приложение где храните бизнес-логику, фронтенд, функции-хелперы вроде уменьшения размера загруженных картинок, etc. Деплоите монолитное приложение на одном сервере, возможно на отдельный сервер выносите базу данных.

    Эта парадигма оправдана в определенных случаях, как и другие парадигмы.

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

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

    Ваше приложение схематически выглядит так:

    Клиент: хочу авторизоваться => Сервер приложения: отправлю бизнес-логике => Бизнес-логика: спросим базу (данные для авторизации) => База данных: можно => Клиент: я авторизован

    Используя другой подходе вы можете вынести ваш модуль авторизации пользователей в микросервис на отдельном сервере, уменьшив таким образом запросы к основной базе.

    Теперь, в вашем фронтенде на Vue, например, вы можете отображать нужные вам данные (а соотв. делать запросы в основную базу), только если пользователь авторизован.

    Теперь ваше приложение выглядит так:

    Клиент: хочу авторизоваться => Фронтенд-микросервис: отправляю микросервису авторизации => Микросервис авторизации: можно => Фронтенд-микросервис: я авторизован, хочу данные => Сервер приложения: отправлю бизнес-логике => Бизнес-логика: спросим базу (данные отображения авторизованному клиенту) => База данных: данные => Клиент: я получил данные

    Давайте теперь представим, что вам нужно быстро, а лучше сегодня набросать MVP для демонстрации инвестору или для проверки вашей концепции.

    Авторизация? — микросервис — auth0.com
    SQL База данных? — микросервис — Google CLOUD SQL
    Уменьшаем размер картинок? — микросервис — AWS Lambda

    Что получается в сухом остатке? Вам требуется лишь написать SPA из которого вы будете обращаться к вашим микросервисам. То есть, вы получаете приложение, которое можно хостить как статический сайт, переложив на микросервисы большинство задач, которые вам требуются в вашем приложении.

    Конечно, это решает определенные проблемы, но и создает новые, поэтому, повторюсь, все зависит от ваших задач.

    Давайте посмотрим на ваш пример с Django. Если я все правильно понимаю, то вы хотите использовать все плюсы Django, типа ORM, API доступа к БД, etc, заменив лишь систему шаблонов на Vue?

    В таком случае, на мой взгляд, вам нужно реализовать на Django классический REST API и из SPA на Vue обращаться к endpoint'ам вашего API.

    Ссылки по теме:
    Архитектура микросервисов
    SPA-архитектура для CRM-систем: часть 1
    SPA-архитектура для CRM-систем: часть 2
    AWS Lambda и никаких серверов
    Ответ написан
    Комментировать
  • Как исправить кривое отображение столбцов в Postrgresql?

    Melkij
    @Melkij
    PostgreSQL DBA
    У вас просто терминал узкий для вашей выборки.
    Широкие результаты часто удобнее читать в широком виде, который переключается с помощью команды \x в psql:

    melkij=> select generate_series(1,3);
     generate_series 
    -----------------
                   1
                   2
                   3
    (3 строки)
    
    melkij=> \x
    Расширенный вывод включён.
    melkij=> select generate_series(1,3);
    -[ RECORD 1 ]---+--
    generate_series | 1
    -[ RECORD 2 ]---+--
    generate_series | 2
    -[ RECORD 3 ]---+--
    generate_series | 3
    Ответ написан
    1 комментарий
  • Django rest framework - вложенные объекты?

    dunmaksim
    @dunmaksim
    Технический писатель
    Создайте два сериализатора - TicketReadSerializer и TicketWriteSerializer:
    class TicketWriteSerializer(serializers.ModelSerializer):
    
        author = serializers.PrimaryKeyRelatedField(
            queryset=get_user_model().objects.all(),
            default=serializers.CurrentUserDefault()
        )
    
        class Meta:
            model = TicketModel
    
    
    class TicketDetailReadSerializer(serializers.ModelSerializer):
    
        author = UserSerializer()
    
        class Meta:
            model = TicketModel

    Затем в представлении (я использую ClassBasedViews) переопределяем метод get_serializer_class:
    def get_serialaizer_class(self):
        if self.request.method == 'GET':
            return TicketReadSerializer
        return TicketWriteSerializer

    P. S. Вижу, не мне одному интересен DRF, и есть потребность в качественных статьях на русском языке.
    Ответ написан
    2 комментария
  • PyCharm не видит мои классы?

    kentuck1213
    @kentuck1213 Автор вопроса
    Вы с вами барашки )))
    Нужно было в директории где хранятся все наши модули правым кликом мыши затем -> Mark Directory As и выбрать Sources root и после этого она загорится голубым цветом :
    f0d127357a294ce1a1d263c4eb020645.png
    после чего PyCharm будет видеть свои классы как надо.
    Ответ написан
    2 комментария
  • Python back-end разработчик. Необходимый минимум технологий?

    sim3x
    @sim3x
    django
    Вначале
    + SQL / PostgreSQL
    + Celery
    + RESTful API
    + Redis / Memcached

    Потом
    RabbitMQ / ActiveMQ

    Позже
    Twisted / Tornado / Asyncio / Gevent

    Когда понадобится
    Kafka
    Ответ написан
    1 комментарий
  • Проблема в DRF при работе с dynamically modifying fields. Что можно сделать?

    @javedimka
    Хочу сока
    Оригинальный ответ
    from rest_framework.response import Response
    
    
    class TrainingDetailAPIView(RetrieveAPIView):
        queryset = Training.objects.all()
        serializer_class = TrainingSerializer
        lookup_field = 'slug'
        
        def retrieve(self, request, *args, **kwargs):
            instance = self.get_object()
            serializer = self.get_serializer(instance, fields=('title', 'description'))
            return Response(serializer.data)

    При работе с drf рекомендую на отдельной вкладке держать открытым гитхаб с сорцами.

    UPD:
    Оригинальное решение хоть и работает, но слегка кривоватое(первое что пришло в голову), правильнее будет переписать метод get_serializer():
    class TrainingDetailAPIView(RetrieveAPIView):
        queryset = Training.objects.all()
        serializer_class = TrainingSerializer
        lookup_field = 'slug'
        
        def get_serializer(self, *args, **kwargs):
            kwargs['fields'] = ('title', 'description')
            return super().get_serializer(*args, **kwargs)

    Меньше кода и не происходит его дупликации как в первом варианте при переписывании метода из retrieve миксина.
    Если такая вью не единственная, то следует пойти дальше и написать свой миксин:
    class ShowFieldsMixin:
    
        def get_serializer(self, *args, **kwargs):
            if getattr(self, 'fields_to_show', None) is not None:
                kwargs['fields'] = self.fields_to_show
            return super().get_serializer(*args, **kwargs)
    
    
    class TrainingDetailAPIView(ShowFieldsMixin, RetrieveAPIView):
        queryset = Training.objects.all()
        serializer_class = TrainingSerializer
        lookup_field = 'slug'
        fields_to_show = ('title', 'description')
    
    class TrainingListAPIView(ShowFieldsMixin, ListAPIView):
        # bla-bla-bla
        serializer_class = TrainingSerializer
        fields_to_show = ('name', 'description', 'url', 'slug')
    Ответ написан
    3 комментария
  • Как в django автоматически заполнить поле при создании объекта в форме?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Django
    Седой и строгий
    Во-первых, стоит сделать поле модели project скрытым полем формы:
    class AddResponseForm(forms.ModelForm):
        class Meta:
            model = Response
            fields = ('body', 'project')
            widgets = {'project': forms.HiddenInput()}


    А потом в views.py:
    form = AddResponseForm(request.POST)
    if form.is_valid():
        response = form.save(commit=False)
        response.user = request.user
        response.save()
    Ответ написан
    3 комментария
  • Как обуздать Django messages?

    winordie
    @winordie
    Лучшая документация -- исходники
    Давайте посмотрим как работает framework messages.

    https://github.com/django/django/blob/master/djang...
    def messages(request):
        return {
            'messages': get_messages(request),
            'DEFAULT_MESSAGE_LEVELS': DEFAULT_LEVELS,
        }
    ...
    def get_messages(request):
        if hasattr(request, '_messages'):
            return request._messages
        else:
            return []

    Так messages попадают на страницу. Т.е. они берутся из request._messages. Как же они туда попадают?

    https://github.com/django/django/blob/master/djang...
    class MessageMiddleware(MiddlewareMixin):
        def process_request(self, request):
            request._messages = default_storage(request)
    ...
    def default_storage(request):
        return import_string(settings.MESSAGE_STORAGE)(request)
    ...
    MESSAGE_STORAGE = 'django.contrib.messages.storage.fallback.FallbackStorage'

    Значит в request._messages у нас лежит FallbackStorage(request)

    Перейдем к нашему коду
    messages.error(request, 'Ваш диапазон дат занят для данного объекта.')

    Что тут происходит? Посмотрим:
    https://github.com/django/django/blob/master/djang...
    def error(request, message, extra_tags='', fail_silently=False):
        add_message(request, constants.ERROR, message, extra_tags=extra_tags,
                    fail_silently=fail_silently)
    ...
    def add_message(request, level, message, extra_tags='', fail_silently=False):
        if not isinstance(request, HttpRequest):
            raise TypeError("add_message() argument must be an HttpRequest object, "
                            "not '%s'." % request.__class__.__name__)
        if hasattr(request, '_messages'):
            return request._messages.add(level, message, extra_tags)  # *** THIS ***
        if not fail_silently:
            raise MessageFailure('You cannot add messages without installing '
                        'django.contrib.messages.middleware.MessageMiddleware')

    Ага, вызывается метод add знакомого нам объекта FallbackStorage.
    Ему передается в качестве параметров:
    - level = constants.ERROR = 40
    - message = 'Ваш диапазон дат занят для данного объекта.'
    - extra_tags = ''

    Посмотрим на этот метод
    https://github.com/django/django/blob/master/djang...
    def add(self, level, message, extra_tags=''):
            if not message:
                return
            level = int(level)
            if level < self.level:
                return
            # Add the message.
            self.added_new = True
            message = Message(level, message, extra_tags=extra_tags)
            self._queued_messages.append(message)
    ...
    def _get_level(self):
            if not hasattr(self, '_level'):
                self._level = getattr(settings, 'MESSAGE_LEVEL', constants.INFO)
            return self._level

    Из этого кода можно сделать вывод что сообщение попадает в очередь сообщений если его уровень более или равен тому который задан в settings.MESSAGE_LEVEL (по умолчанию = contants.INFO = 20)

    Таким образом чтобы добавлялись только наши сообщения необходимо:
    1) в settings.py установить
    # settings.py
    ...
    MY_SUPER_ERROR = 80
    MESSAGE_LEVEL = MY_SUPER_ERROR
    ...

    2) Во вью писать
    if not available_cars:
            carstoshow = None
            messages.add_message(request, settings.MY_SUPER_ERROR, 'Ваш диапазон дат занят для данного объекта.')
            return redirect('car_detail', pk=car_used_id)
    Ответ написан
    1 комментарий