Problema
Temos páxinas que se leen con dificultade en dispositivos móviles, como iPhone e Android. Buscando por ahí adiante atopéi varios enfoques, e o máis extendido é analizar a petición do cliente (HTTP_USER_AGENT sobre todo) para ver si pertence a un dispositivo móvil. Unha vez determinado, aplicar a solución requeridaA base
Partín da base de Django mobile utils, que implementa unha solución robusta. Cando chega a petición (request), antes de chegar óviews.py pasa por un middleware que intenta averiguar si o USER_AGENT é móbil. A función está no __init__.py, e garda o request nunha variable local. Aquí é donde me falla, xa que non consigo recuperar as variables locais. Despóis de pasar polo middleware, o request orixinal está marcado como .is_mobile = True. Hai un código para cargar os "templates" alternativos, dentro de loaders.py; este loader mira dentro da variable local de request si ten o valor .is_mobile == True, porque non se lle pode pasar como parámetro o propio request. Así que si falla o request local, falla todo.Por sorte, o autor tamén incluiu un context_processor, que simplemente se encarga de pasarlle un diccionario de variables ós templates. Por exemplo, si activamos o context_procesor de auth, en tódolos templates teremos dispoñibles un número de variables como
user.
A solución
Utilizando o código anterior, podemos simplificalo para utilizar só o__init__.py e o context_processor.py. Os context_processors deben manterse simples según o manual oficial, así que si podemos pasar só unha variable, mellor que dúas. Dende o context_processor.py orixinal:def mobile_browser(request):
dict = {'mobile_browser': False}
if hasattr(request, 'is_mobile'):
dict['mobile_browser'] = request.is_mobile
return dict
Podemos pasar a outro context máis simple aínda, como:def mobile_browser(request):
dict = {'mobile_browser': False}
if our_server.django_mobile_utils.is_mobile(request):
dict['mobile_browser'] = True
return dict
Vemos que o autor orixinal sigue tirando de request acumulado en local, pero nós imos testear directamente o request. Modificamos tamén o código do __init__.py. Das varias liñas de tipo:
request.mobile = True return requestCambiamos a:
return TrueE a última liña que pon
return request cambiámola a return False. Ou adornamos con variables, si nos gusta máis.Si estamos pola simplificación extrema, todas as globáis deste archivo pódense eliminar, así como a configuración no
settings.py, no que chega con engadir:TEMPLATE_CONTEXT_PROCESSORS = (
"our_server.django_mobile_utils.context_processors.mobile_browser",
...
Aplicación
Agora temos no directorio django_mobile_utils os arquivos__init__.py, context_processor.py e un directorio data/mobile_agents.txt, e o settings.py modificado como corresponde. ¿Cómo ó usamos? Simplemente, nos templates utilizamos a variable booleana {{mobile_browser}} como condicional, por exemplo para cargar unha folla de estilo diferente:{% if mobile_browser %}
<link href="/media/css/mobile_style.css" rel="stylesheet" type="text/css" />
{% else %}
<link href="/media/css/style.css" rel="stylesheet" type="text/css" />
{% endif %}