1

Я разрабатываю мобильную версию своего сайта, поэтому подумал об использовании пользовательского агента в качестве критериев для обслуживания различных шаблонов для мобильной и веб-версии. Я успешно прочитал информацию пользователя-агента от nginx и передал его как заголовок серверу gunicorn.Мобильные шаблоны на основе user-agent в django, обеспечивающие безопасность потоков

Затем я создал промежуточное программное обеспечение, которое считывает этот заголовок и изменяет каталог шаблонов в файле настроек. Сначала это работало, но потом я понял, что существует условие гонки, поскольку этот метод не является потокобезопасным. (Я должен был подумать об этом раньше).

Итак, я начал думать о других альтернативах. Одним из решений было перезаписать метод рендеринга django, чтобы включить параметр «dirs» на основе заголовка запроса. Но потом я узнал, что параметр «dirs» устарел. Ниже приведена ссылочная ссылка https://docs.djangoproject.com/en/1.9/_modules/django/shortcuts/#render Так что даже это не сработает.

Другое решение состоит в том, чтобы иметь разные имена шаблонов для мобильных устройств и Интернета и загружать их соответственно. Однако я не хочу этого делать и хочу, чтобы структура каталогов шаблонов была одинаковой для веб-и мобильных.

Должен быть способ просто переписать каталог шаблонов. Это даст мне преимущество отказаться от веб-версии шаблонов, если она отсутствует в каталоге мобильных шаблонов.

Любые советы о том, как достичь этого, будут полезны.

Так организованы мои шаблоны.

App1 
    templates 
     App1 
      index.html 
      catalog.html 
App2 
    templates 
     App2 
      about.html 

И в директории проекта (не входит в папку приложения), есть папка мобильных шаблонов, который имеет следующую структуру

mobile-templates 
    App1 
     index.html 
    App2 
     about.html 

Благодаря Анураг

+0

Как насчет изменения объекта 'request' для добавления имени каталога? Затем «render» может отобразить файл, связав путь к этой переменной 'request.template_dir'. – sudshekhar

+0

@SudhanshuShekhar - Даже если я изменяю объект запроса, как функция render автоматически примет имя каталога? Я также проверил исходный код и не нашел, что request.template_dir используется функцией render. Не знаю, пропустил ли я что-то, пожалуйста, уточните. Если вы хотите предварительно добавить имя каталога в мою функцию рендеринга, то откат в веб-версии не будет работать. – Anurag

+0

Я думал о чем-то вроде: render (request, ["app/template/t_mobile.html", "app/template/t.html"], context) '. Вы можете использовать 'request.template_dir', чтобы решить, следует ли добавлять' t_mobile.html' в качестве опции или нет. – sudshekhar

ответ

1

Вот как я бы организовать мои шаблоны:

  1. сделать две директории внутри templates директории - mobile и desktop.
  2. Картинка для мобильного телефона в mobile шаблоны для рабочего стола и рабочего стола в категории desktop.

Таким образом, вам не придется переименовывать шаблоны.


А вот как я бы сделать их:

  1. Read User-Agent в ППО.
  2. Установить атрибут на request под названием template_prefix, значение которого будет либо mobile, либо desktop, в зависимости от пользователя-агента. Например:

    def process_request(self, request): 
        # read user agent and determine if 
        # request is from mobile or desktop 
        # ... 
        if mobile_user_agent: 
         request.template_prefix = 'mobile' 
        else: 
         request.template_prefix = 'desktop' 
    
  3. В своих взглядах, используйте request.template_prefix перед тем именами шаблона. Например:

    def home(request): 
        ... 
        template = request.template_prefix + '/home.html' 
        return render(request, template) 
    

Это будет оказывать шаблоны из либо mobile или desktop директорий в зависимости от значения атрибута template_prefix.


UPDATE (в соответствии с вопросом редактирования):

Глядя на то, как организованы ваши шаблоны, я бы это сделать:

  1. Middleware:

    только набор template_prefix для мобильных запросов.

    def process_request(self, request): 
        if mobile_user_agent: 
         request.template_prefix = 'mobile-templates' 
        else: 
         request.template_prefix = '' # set an empty string 
    
  2. Просмотров:

    Используйте os.path.join; catch TemplateDoesNotExist исключение.

    import os.path 
    from django.template.loader import get_template 
    from django.template.base import TemplateDoesNotExist 
    
    def index(request): 
        try: 
         template = os.path.join(request.template_prefix, 'App1/index.html') 
         get_template(template) 
        except TemplateDoesNotExist: 
         template = 'App1/index.html' 
    
        return render(request, template) 
    

Я проверил это, и это работает. Но запись блока try...except во всех представлениях кажется излишним. Если я придумаю лучшее решение, я обновлю.

+0

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

+0

@anurag В этом случае вы можете использовать 'request.template_prefix' только в тех представлениях, где вы хотите отображать разные шаблоны. Если для этого представления нет мобильного шаблона, используйте «префикс» для рабочего стола. Обновлен ответ. – xyres

+0

Да, но проблема в том, что я не буду знать, существует ли шаблон или нет. Поэтому мне придется либо проверить, присутствует ли файл, либо изменить мою функцию рендеринга всякий раз, когда создается мобильный шаблон. Я могу достичь этого, не изменяя функцию рендеринга, используя параметр «dirs», но потому, что его устарело, я ищу правильный путь. Не могу понять, почему он устарел. – Anurag

0

Кажется, это ISN прямо сейчас. Если вы действительно хотите следовать этой архитектуре, вам придется написать свой собственный пользовательский загрузчик, а также выяснить способ передачи запроса/индикатора, чтобы сообщить ему свой мобильный запрос.

Не так уж сложно написать загрузчик (просто посмотрите загрузчик файловой системы Django, если запрос отправлен из мобильного, пропустите все шаблоны_диров и добавьте в него правильный суффикс, чтобы вы также включили мобильные устройства).

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

+0

Не о том, чтобы следовать определенной архитектуре, это скорее проблема, для которой я ищу подходящее решение. Я могу создать загрузчик, но, как вы сказали, передача динамического параметра - это боль, поскольку методы загрузчика не получают доступ к объекту запроса. https://docs.djangoproject.com/en/1.9/ref/templates/api/# custom-loaders И изменяя имя шаблона перед загрузкой шаблона, а затем его чтение и отмену сделанной ранее модификации, кажется, еще более запутанной. – Anurag

+0

Похоже на общую проблему, не уверен, как люди решают эту проблему – Anurag