Реализуем last visited/recent pages в Django

    У меня часто бывает так, что на новом ресурсе я теряюсь в море разных функций и настроек, и для того, чтобы не потерять из виду что-то интересное, открываю/дублирую вкладку. Это не всегда удобно, да и кнопка «назад» иногда работает непредсказуемо, например, в связи с push history, или из-за «сломавшегося» на редиректе обработчика POST (не зла, а эксперимента ради). Поэтому, чтобы не нервировать пользователя, я решил сделать recent pages. История об этом под катом.


    Вариант первый


    Изначально я хотел реализовать эту функцию через Middleware, но столкнулся с проблемой: запомнить url и положить в кэш — не проблема, а вот получить текущий title страницы — да. И я до сих пор думаю, что единственный правильный способ реализовать это — использовать middleware. Дурацкие решения: использовать process_response() и парсить title; использовать для получения title ajax-скрипт на стороне клиента и все аналогичное этому. Поэтому, нужно как-то добраться до шаблонизатора из middleware и получить там корневой {% block title %}. Буду рад, если поделитесь идеей на этот счет.

    Вариант второй


    Использовать templatetag. Именно так я это и сделал, но существенный минус этого варианта в том, что нужно руками править шаблоны, либо думать, как встроить этот tag в base.html.

    Вариант третий


    Использовать ajax-скрипт а-ля трекер статистики. Плюс этого варианта в том, что результаты можно использовать для разных нужд, например, для статистики. Минусы — лишний скрипт, лишние обработчики, лишние данные.




    Тэг для сохранения title

    Если вы используете ajax-запросы к тем же view, то стоит добавить проверку request.is_ajax(), чтобы не сохранять юзеру битые ссылки.

    @register.simple_tag(takes_context=True, name='save_visited')
    def save_visited(context, title, **kwargs):
        request = context['request']
    
        # store last five pages
        identify_by = get_user_identification(request)
        visited_pages = cache.get('visited_pages_%s' % identify_by, [])[:4]
    
        # context.use_tz - why None if set True in settings?
        # may be we should save datetime.now() and convert it in getter?
        now = timezone.now()
    
        bundle = force_unicode(title), request.get_full_path()[:255], now
        visited_pages.insert(0, bundle)
    
        cache.set('visited_pages_%s' % identify_by, visited_pages, 60*60*24)
        return title
    


    Использование:
    {% extends 'forum/themes/default/edit_profile.html' %}
    {% load last_visited i18n %}
    {% block title %}{% save_visited _("Profile setup") %}{% endblock %}
    


    Тэг-геттер, выгружает список в указанную переменную контекста


    @register.simple_tag(takes_context=True, name='load_visited')
    def load_visited(context, variable, **kwargs):
        identify_by = get_user_identification(context['request'])
        context[variable] = cache.get('visited_pages_%s' % identify_by, [])
        return u''
    


    Использование:
    {% load_visited 'visited' %}
    {% for title, uri, dt in visited %}
        <a href="{{ uri }}">{{ title }} {% trans "at" %} {{ dt }}</a><br/>
    {% endfor %}
    


    Для экспериментов gist. И все же, не дает покоя мне middleware-вариант.
    Метки:
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 3
    • 0
      Я бы все-таки сделал через аякс.
      С текущим подходом хрен вам а не кеш.
      • 0
        В каком смысле, хрен, а не кэш?
        • 0
          В смысле что если у вас что-то происходит на бекенде использовать nginx для кеширования не получится.

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