Modifica i modelli Django in base a User-Agent
-
03-07-2019 - |
Domanda
Ho creato un sito Django, ma ho bevuto Koolaid e voglio fare una versione IPhone . Dopo aver riflettuto a fondo ho escogitato due opzioni:
- Crea un altro sito, come i.xxxx.com. Collegalo allo stesso database usando il framework dei siti di Django.
- Trova un po 'di tempo per il middleware che legge lo user-agent e modifica dinamicamente le directory dei template.
Preferirei davvero l'opzione n. 2, comunque; Ho delle riserve, principalmente perché la documentazione di Django scoraggia la modifica al volo delle impostazioni . Ho trovato un snippet che farebbe ciò che mi piacerebbe. Il mio problema principale è averlo il più semplice possibile, mi piacerebbe che fosse automagico e trasparente per l'utente.
Qualcun altro ha riscontrato lo stesso problema? Qualcuno vorrebbe condividere su come hanno affrontato la creazione di versioni IPhone dei siti Django?
Aggiorna
Sono andato con una combinazione di middleware e ottimizzando la chiamata del modello.
Per il middleware, ho usato minidetector . Mi piace perché rileva un plethora di user-agent mobili. Tutto quello che devo fare è controllare request.mobile nelle mie visualizzazioni.
Per la modifica del modello di chiamata:
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.
TODO:
- Scopri come accedere a request.mobile in una versione estesa di render_to_response, quindi non devo usare check_mobile ('template_name.html')
- Utilizzo del fallback automagicamente precedente al modello normale se non esiste una versione mobile.
Soluzione
Anziché modificare dinamicamente le directory dei modelli, è possibile modificare la richiesta e aggiungere un valore che consenta alla vista di sapere se l'utente è su un iPhone o meno. Quindi avvolgere render_to_response (o qualunque cosa tu stia usando per creare oggetti HttpResponse) per prendere la versione iphone del modello invece della versione html standard se stanno usando un iphone.
Altri suggerimenti
Rileva l'agente utente nel middleware, cambia i collegamenti url, guadagna!
Come? Gli oggetti richiesta Django hanno un attributo .urlconf, che può essere impostato dal middleware.
Dai documenti di django:
Django determina il root URLconf modulo da usare. Di solito, questo è il valore dell'impostazione ROOT_URLCONF, ma se l'oggetto HttpRequest in arrivo ha un attributo chiamato urlconf (impostato da elaborazione delle richieste del middleware), relativo il valore verrà usato al posto di Impostazione ROOT_URLCONF.
-
In yourproj / middlware.py, scrivi una classe che controlla 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"
-
Non dimenticare di aggiungere questo a MIDDLEWARE_CLASSES in settings.py:
MIDDLEWARE_CLASSES= [... 'yourproj.middleware.MobileMiddleware', ...]
-
Crea un urlconf mobile, yourproj / mobile_urls.py:
urlpatterns=patterns('',('r'/?
Questo articolo potrebbe essere utile: Crea un'applicazione mobile e desktop-friendly in Django in 15 minuti
Sto sviluppando djangobile, un'estensione mobile di django: http://code.google.com / p / djangobile /
Dovresti dare un'occhiata al django-mobileadmin , che risolto esattamente questo problema.
Un altro modo sarebbe creare il proprio caricatore di modelli che carichi modelli specifici per l'agente utente. Questa è una tecnica piuttosto generica e può essere utilizzata per determinare dinamicamente quale modello deve essere caricato in base anche ad altri fattori, come la lingua richiesta (buon compagno per i macchinari Django i18n esistenti).
Django Book ha una sezione su questo argomento .
C'è un bell'articolo che spiega come rendere gli stessi dati con modelli diversi http://www.postneo.com/ 2006/07/26 / riconoscendo-the-mobile-web-con-django
Devi comunque reindirizzare automaticamente l'utente al sito mobile e questo può essere fatto usando diversi metodi (anche il tuo trucco check_mobile funzionerà)
Che ne dici di reindirizzare l'utente a i.xxx.com dopo aver analizzato la sua UA in un middleware? Dubito fortemente che agli utenti di dispositivi mobili piaccia l'aspetto dell'URL, tuttavia possono accedere al tuo sito utilizzando l'URL principale.
miglior scenario possibile: usa minidetector per aggiungere le informazioni extra alla richiesta, quindi usa il contesto di richiesta integrato di django per passarlo ai tuoi modelli in questo modo
from django.shortcuts import render_to_response
from django.template import RequestContext
def my_view_on_mobile_and_desktop(request)
.....
render_to_response('regular_template.html',
{'my vars to template':vars},
context_instance=RequestContext(request))
quindi nel tuo modello sei in grado di introdurre cose come:
<html>
<head>
{% block head %}
<title>blah</title>
{% if request.mobile %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-mobile.css">
{% else %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-desktop.css">
{% endif %}
</head>
<body>
<div id="navigation">
{% include "_navigation.html" %}
</div>
{% if not request.mobile %}
<div id="sidebar">
<p> sidebar content not fit for mobile </p>
</div>
{% endif %>
<div id="content">
<article>
{% if not request.mobile %}
<aside>
<p> aside content </p>
</aside>
{% endif %}
<p> article content </p>
</aricle>
</div>
</body>
</html>
Una soluzione semplice è quella di creare un wrapper attorno a django.shortcuts.render
. Ho inserito il mio in una libreria utils
nella radice della mia applicazione. Il wrapper funziona eseguendo automaticamente il rendering dei modelli in uno "mobile" o " desktop " cartella.
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')