Modifier les modèles Django en fonction de l'agent utilisateur
-
03-07-2019 - |
Question
J'ai créé un site Django, mais j'ai bu le Koolaid et je souhaite créer une version IPhone . Après avoir bien réfléchi, j'ai proposé deux options:
- Créez un autre site, comme i.xxxx.com. Associez-le à la même base de données en utilisant le framework de sites de Django.
- Recherchez un temps de logiciel intermédiaire qui lit l'agent utilisateur et modifie les répertoires de modèles de manière dynamique.
Je préférerais vraiment l'option n ° 2, cependant; J'ai quelques réserves, principalement parce que la documentation de Django décourage de modifier les paramètres à la volée . . J'ai trouvé un extrait qui ferait ce que je voudrais. Mon problème principal est de le rendre aussi transparent que possible, j'aimerais que ce soit automatisé et transparent pour l'utilisateur.
Quelqu'un at-il rencontré le même problème? Quelqu'un voudrait-il expliquer comment il a abordé la création de versions iPhone de sites Django?
Mettre à jour
Je suis allé avec une combinaison de middleware et de peaufiner l'appel de modèle.
Pour le middleware, j'ai utilisé minidétecteur . Je l’aime bien, car il détecte une pléthore d’agents d’utilisateurs mobiles. Tout ce que je dois faire est de vérifier request.mobile dans mes vues.
Pour le tweak d’appel de modèle:
def check_mobile(request, template_name):
if request.mobile:
return 'mobile-%s'%template_name
return template_name
Je l'utilise pour toutes les vues dont je sais que j'ai les deux versions.
TODO:
- Découvrez comment accéder à request.mobile dans une version étendue de render_to_response afin d'éviter de devoir utiliser check_mobile ('template_name.html')
- Utiliser le précédent retour automatique au modèle standard si aucune version mobile n'existe.
La solution
Plutôt que de modifier dynamiquement les répertoires de modèles, vous pouvez modifier la demande et ajouter une valeur qui indique à votre vue si l'utilisateur est sur un iphone ou non. Puis, enduisez render_to_response (ou ce que vous utilisez pour créer des objets HttpResponse) afin de récupérer la version iphone du modèle à la place de la version html standard s’ils utilisent un iphone.
Autres conseils
Détectez l'agent utilisateur dans le middleware, changez les liaisons d'URL, profitez!
Comment? Les objets de demande Django ont un attribut .urlconf, qui peut être défini par le middleware.
Dans les documents Django:
Django détermine la URLconf racine module à utiliser. D'ordinaire, c'est le valeur du paramètre ROOT_URLCONF, mais si l'objet HttpRequest entrant a un attribut appelé urlconf (défini par traitement des requêtes middleware), ses la valeur sera utilisée à la place du ROOT_URLCONF paramètre.
-
Dans votreproj / middlware.py, écrivez une classe qui vérifie la chaîne http_user_agent_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"
-
N'oubliez pas d'ajouter ceci à MIDDLEWARE_CLASSES dans settings.py:
MIDDLEWARE_CLASSES= [... 'yourproj.middleware.MobileMiddleware', ...]
-
Créez une urlconf mobile, votreproj / mobile_urls.py:
urlpatterns=patterns('',('r'/?
Cet article pourrait être utile: Construire une application mobile et conviviale dans Django en 15 minutes
Je développe djangobile, une extension mobile Django: http://code.google.com / p / djangobile /
Consultez le code source django-mobileadmin , qui résolu exactement ce problème.
Vous pouvez également créer votre propre chargeur de modèles qui charge des modèles spécifiques à l’agent utilisateur. C'est une technique assez générique et peut être utilisée pour déterminer dynamiquement quel modèle doit être chargé en fonction d'autres facteurs, comme le langage demandé (bon compagnon des machines Django i18n existantes).
Django Book a une section sur ce sujet .
Un bel article explique comment rendre les mêmes données avec différents modèles. http://www.postneo.com/ 2006/07/26 / reconnaissant-le-mobile-web-avec-django
Cependant, vous devez toujours rediriger automatiquement l'utilisateur vers le site mobile. Cette opération peut être effectuée à l'aide de plusieurs méthodes (votre astuce check_mobile fonctionnera également)
Pourquoi ne pas rediriger l'utilisateur vers i.xxx.com après avoir analysé son agent utilisateur dans un middleware? Je doute fort que les utilisateurs de mobile se soucient de l'apparence de l'URL. Ils peuvent néanmoins accéder à votre site à l'aide de l'URL principale.
meilleur scénario possible: utilisez minidetector pour ajouter les informations supplémentaires à la demande, puis utilisez le contexte de demande intégré de django pour le transmettre à vos modèles de la manière suivante
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))
puis dans votre modèle, vous pouvez introduire des choses comme:
<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>
Une solution simple consiste à créer un wrapper autour de django.shortcuts.render
. Je mets la mienne dans une bibliothèque utils
à la racine de mon application. Le wrapper fonctionne en rendant automatiquement les modèles dans un fichier "mobile". ou " desktop " dossier.
Dans 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)
Dans la vue
:
from utils.shortcuts import my_render def home(request): return my_render(request, 'home.html')