Mobile Template Loader – Django
The web is moving towards the mobile world faster and faster. The number of people using mobile browsers are keeping on increasing. The current emergence of the devices like the iPad and other Tablets are increasing the pace of adoption of mobile browsers.
You mostly might have seen m.abc.com or touch.xyz.com etc under certain domains where the mobile browsers are redirected. But, I wanted the mobile browser not to redirect to the a separate domain. I wanted to UI to change itself on the same domain for a mobile browser.
So here is a small snippet I wrote with the little help from here.
The set contains:
- A new middleware to identify the browser and mark the mobile flag in thread_locals.
- A template loader to take the mobile template in the folder mobile_templates if present. ie: if you specify a template directory and then add a new file under the directory mobile_templates in the app template directory, it picks up that template than the normal template.
The Middleware:
import re
try:
from threading import local
except ImportError:
from django.utils._threading_local import local
_thread_locals = local()
reg_b = re.compile(r"android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino", re.I|re.M)
reg_v = re.compile(r"1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|e\\-|e\\/|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\\-|2|g)|yas\\-|your|zeto|zte\\-", re.I|re.M)
def get_mobile_request():
return getattr(_thread_locals, 'mobile', None)
def set_mobile_request(mobile):
setattr(_thread_locals,'mobile',mobile)
def unset_mobile_request():
setattr(_thread_locals,'mobile',None)
class MobileMiddleware():
def process_request(self, request):
request.is_mobile = False
if request.META.has_key('HTTP_USER_AGENT'):
user_agent = request.META['HTTP_USER_AGENT']
b = reg_b.search(user_agent)
v = reg_v.search(user_agent[0:4])
if b or v:
request.is_mobile = True
if request.is_mobile:
set_mobile_request(request.is_mobile)
def process_response(self, request, response):
unset_mobile_request()
return response
Now add the below template loaders to the beginning of your template loader list:
from django.conf import settings
from django.template import TemplateDoesNotExist
from django.utils._os import safe_join
from django.utils.encoding import smart_str
import os
from custom_middlware import get_mobile_request
def get_template_sources(template_name,template_dirs = None):
"""
Returns the absolute path of the template names when appended to the template_dirs.
If there is a browser is a mobile browser, the MobileMiddleware sets the mobile flag.
This function checks for a directory named mobile_templates and finds the template.
"""
mobile = get_mobile_request()
#mobile = True
if mobile is not None and mobile is True:
try:
for template_dir in template_dirs:
parts = template_name.split("/")
parts.insert(len(parts)-1,"mobile_templates")
appDirName = smart_str(parts[0])
parts.insert(0,"templates")
if appDirName != "tagglecom":
parts.insert(0,appDirName)
mobileTemplatePath = os.sep.join(smart_str(n) for n in parts)
yield safe_join(template_dir, mobileTemplatePath)
except UnicodeDecodeError,e:
# The template dir name was a bytestring that wasn't valid UTF-8.
raise
except ValueError,e:
# The joined path was located outside of this particular
# template_dir (it might be inside another one, so this isn't
# fatal).
pass
except Exception,e:
pass
def load_template_source(template_name, template_dirs=None):
tried = []
template_dirs = settings.TEMPLATE_DIRS
for filepath in get_template_sources(template_name, template_dirs):
try:
return (open(filepath).read().decode(settings.FILE_CHARSET), filepath)
except IOError,e:
exp = "Error:%s, FilePath:%s" %(e,filepath)
tried.append(exp)
if tried:
error_msg = "Tried %s" % tried
else:
error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
raise TemplateDoesNotExist, error_msg
load_template_source.is_usable = True
That’s it. This must help you load mobile templates if specified for the template. Else will load the normal template specified by your project.
Advertisement



No trackbacks yet.