[Python] Modifica i modelli di Django in base a User-Agent


Answers

Rileva l'agente utente nel middleware, cambia i collegamenti dell'URL, guadagna!

Come? Gli oggetti di richiesta Django hanno un attributo .urlconf, che può essere impostato dal middleware.

Da django docs:

Django determina il modulo URLconf di root da utilizzare. Normalmente, questo è il valore dell'impostazione ROOT_URLCONF, ma se l'oggetto HttpRequest in arrivo ha un attributo chiamato urlconf (impostato dall'elaborazione della richiesta del middleware), il suo valore verrà utilizzato al posto dell'impostazione ROOT_URLCONF.

  1. In yourproj / middlware.py, scrivi una classe che controlli la stringa http_user_agent:

    import re
    MOBILE_AGENT_RE=re.compile(r".*(iphone|mobile|androidtouch)",re.IGNORECASE)
    class MobileMiddleware(object):
        def process_request(self,request):
            if MOBILE_AGENT_RE.match(request.META['HTTP_USER_AGENT']):
                request.urlconf="yourproj.mobile_urls"
  2. Non dimenticare di aggiungere questo a MIDDLEWARE_CLASSES in settings.py:

    MIDDLEWARE_CLASSES= [...
        'yourproj.middleware.MobileMiddleware',
    ...]
  3. Crea un urlconf per dispositivi mobili, yourproj / mobile_urls.py:

    urlpatterns=patterns('',('r'/?$', 'mobile.index'), ...)
Question

Ho creato un sito Django, ma ho bevuto Koolaid e voglio creare una versione per iPhone . Dopo aver riflettuto molto ho trovato due opzioni:

  1. Crea un sito completamente diverso, ad esempio i.xxxx.com. Leggetelo nello stesso database usando la struttura dei siti di Django.
  2. Trova un po 'di tempo del middleware che legge l'user-agent e modifica dinamicamente le directory dei template.

Preferirei davvero l'opzione n. 2, comunque; Ho alcune riserve, principalmente perché la documentazione di Django scoraggia la modifica delle impostazioni al volo . Ho trovato un frammento che farebbe quello che mi piacerebbe. Il mio problema principale è avere il più semplice possibile, mi piacerebbe che fosse automagic e trasparente per l'utente.

Qualcun altro ha incontrato lo stesso problema? Qualcuno si preoccuperebbe di condividere su come hanno affrontato la realizzazione delle versioni IPhone dei siti Django?

Aggiornare

Sono andato con una combinazione di middleware e tweaking la chiamata modello.

Per il middleware, ho usato minidetector . Mi piace perché rileva una pletora di agenti utente mobili. Tutto quello che devo fare è controllare request.mobile nelle mie visualizzazioni.

Per il tweak di chiamata del template:

 def check_mobile(request, template_name):
     if request.mobile:
         return 'mobile-%s'%template_name
     return template_name

Lo uso per qualsiasi vista che so di avere entrambe le versioni.

FARE:

  • Scopri come accedere a request.mobile in una versione estesa di render_to_response, quindi non devo usare check_mobile ('template_name.html')
  • Utilizzando il precedente metodo di ripiego automatico al modello normale se non esiste una versione mobile.



Che ne dici di reindirizzare l'utente a i.xxx.com dopo aver analizzato la sua UA in alcuni middleware? Dubito fortemente che gli utenti di dispositivi mobili siano interessati all'aspetto dell'URL, tuttavia possono accedere al tuo sito utilizzando l'URL principale.




Una soluzione semplice è creare un wrapper attorno a django.shortcuts.render . Inserisco il mio in una libreria di utils nella radice della mia applicazione. Il wrapper funziona eseguendo il rendering automatico dei modelli in una cartella "mobile" o "desktop".

In utils.shortcuts :

from django.shortcuts import render
from user_agents import parse

def my_render(request, *args, **kwargs):
  """
  An extension of django.shortcuts.render.

  Appends 'mobile/' or 'desktop/' to a given template location
  to render the appropriate template for mobile or desktop

  depends on user_agents python library
  https://github.com/selwin/python-user-agents

  """
  template_location = args[0]
  args_list = list(args)

  ua_string = request.META['HTTP_USER_AGENT']
  user_agent = parse(ua_string)

  if user_agent.is_mobile:
      args_list[0] = 'mobile/' + template_location
      args = tuple(args_list)
      return render(request, *args, **kwargs)
  else:
      args_list[0] = 'desktop/' + template_location
      args = tuple(args_list)
      return render(request, *args, **kwargs)

In view :

from utils.shortcuts import my_render

def home(request):    return my_render(request, 'home.html')






Un altro modo sarebbe creare il proprio caricatore di template che carica modelli specifici per user agent. Questa è una tecnica abbastanza generica e può essere utilizzata per determinare dinamicamente quale modello deve essere caricato, a seconda anche di altri fattori, come la lingua richiesta (buon compagno di macchine Django i18n esistenti).

Il libro di Django ha una sezione su questo argomento .