Django Site Works Most Places, Except the IPhone

I had a Django 1.11 site running with nginx and gunicorn. It worked on several devices, including my Ubuntu desktop, a Mac laptop, and an IPad. But it did not work on my Iphone.

On my IPhone, I got a “network connection failed” error.

On my server, there was no record of my Iphone page request in the nginx access log and there wa no record in the nginx error log either.

The clue was in the /var/log/nginx/error.log. This file had a ton of lines like:

2019/03/03 13:42:46 [alert] 4820#0: worker process 18707 exited on signal 11 (core dumped)

To fix it, I made a bunch of changes to my nginx config file. I am not sure which line was causing the crash. But it is working now.



Testing A Mobile Django Site on a Phone on a LAN

Getting a site to layout well on mobile can be tricky. Although there are some decent mobile emulators, I still frequently run into important differences when I view it on a real phone.

Web pages for the desktop are easy to test using the Django development server. This note describes how to browse the development server from a mobile device that is on the same LAN as the server.

    1. Connect to the LAN with your phone
    2. Get the local IP address of the computer that runs the development server. On Linux the command is ifconfig (that’s not a typo. It’s not ipconfig). My computer’s IP address is
    3. Start the development server as follows: python runserver 
    4. Start a browser on your phone
    5. Goto: http://<the server IP address>:8800  In my case that would be

You should see your website on your phone now.

Can’t Connect?

Is wi-fi on on your phone?




Mobile Detection on Django

Most of the Django sites I develop these days need to work on mobile. I am using Bootstrap 3 to make my pages responsive. Bootstrap’s philosophy is “mobile first”. But there are many cases where I do not want users with big screens to be penalized by a site that is optimized for a small screen.

While Bootstrap has some css classes for showing and hiding based on screen size. That approach is somewhat limited. It also slows the page down because the content still needs to be downloaded even if its not shown. A more complete solution would be to have the option of detecting the device on the server side and altering the page before its sent. This is especially easy using Django templates.

The big question is how to detect the users device and hopefully get its screen size in Django. I started with I was able to install it on Ubuntu 12.04 without any problems. I was using the “lite-pattern-wrapper” method, so I did not download the trie database. It worked fine, locally with the Django development server. However, when I tried to install it on a CentOS 5, 32-bit machine (Webfaction), it seg faulted. The folks at Webfaction suggested that I migrate to one of their CentOS 6, 64-bit machines. It installed without problems on the machine. But when I tried using the code by fetching a page from my DroidX, it seg faulted. I am not sure how to debug something like that. It works locally. And when it seg faults there are no debugging messages.

Wait. All is not lost. The middleware and context processor works with Firefox on Ubuntu. I added a bunch of print statements to the middleware. The problem occurs in the call to mobile_detector.match in _match. Up until then all the parameters look reasonable. To make matter worse, if I fire up my virtualenv and python interpreter on the server and run that command from the command line, with the params that caused the seg fault, everything works fine. It looks like this is a problem with mod_wsgi.

There is some stuff on stackoverflow related to this. I tried adding WSGIApplicationGroup %{GLOBAL} but no change. This is a mess. Moving on. I am going to try a pure python package.

django-mobile looks OK, but seems to be limited to just differentiating between mobile, tablet and full. Moble ESP looks interesting. The python code is just one file: It’s very readable and understandable. Not as many Django features as django-mobile. But most of what I want, I can roll my own. Here is quick and dirty middleware:

from xxx import mdetect

class DetectMobile:
    def process_request(self, request):
        user_agent = request.META.get("HTTP_USER_AGENT")
        http_accept = request.META.get("HTTP_ACCEPT")
        if user_agent and http_accept:
            agent = mdetect.UAgentInfo(userAgent=user_agent, httpAccept=http_accept)
            request.mobile_esp_agent = agent   # in case we want more information about the device
            if agent.detectMobileQuick():
                request.device_type = 'mobile'
            elif agent.detectTierTablet():
                request.device_type = 'tablet'
                request.device_type = 'desktop'
            request.mobile_esp_agent = None
            request.device_type = 'desktop'   # default

The careful reader will no doubt notice that after I called django-mobile limited, I set about creating those exact limits in my middleware. Ha. But an even carefuller reader will notice I include the agent in request, so I can get at the details as needed. So far this approach is working well.