ux scrutiny

ramblings about code and ux

March 19, 2014
by ktnode
0 comments

404 and 500 errors in django

Problem: Server Error 500. In the server log, all it mentions is a line that looks something like

"GET / HTTP/1.1" 500 27

Potential fix: There are two potential reasons for this error.

  • Ensure that ALLOWED_HOSTS is configured properly in the settings file. In the default settings file, there’s a line for ALLOWED_HOSTS=[]. In my case, I was deploying things locally, so I edited this line to be ALLOWED_HOSTS=['127.0.01','localhost']. If you’re deploying things on a specific domain, list that here. Others have suggested using ALLOWED_HOSTS=['*'], but this setting should really only be used for testing deployments, as it’s not a secure setting for production deployment scenarios.
  • Create a template for 500 errors. Note that the docs recommend you create a template that is very simple because you can never know for sure why the error was generated. In other words, you can’t rely on something that might potentially be broken; that’s why the sample one mentioned in the docs doesn’t do anything fancy and doesn’t use any template inheritance.

One quick note about creating a 500-error template: in my case, I wanted my 500 page, like my 404 page, to fit in with the same look & feel as the rest of the site. This meant utilizing template inheritance (i.e., {% extends "base.html" %}). Now, even though the docs say this is no-no, it ended up working out OK. At first, I ran into this error message:

OfflineGenerationError: You have offline compression enabled but key "SOMEKEYHERE" is missing from offline manifest. You may need to run "python manage.py compress"

Following the suggestion made here, I got things working again by using a custom class-based view. [Side note: it looks like offline generation loads the manifest once, and then remembers the result so that it doesn't have to refetch it on every request. What this means is that once I got offline compression working (by using the custom class-based view), it's possible to remove the code for the custom view (i.e., the calls in url.py and the class handler500.py) and things would still work out OK. Nonetheless, it's probably best to just keep the code there.]

Problem: You’d like to see what your 404/500 error pages look like when DEBUG=FALSE
Potential fix: One easy hack to ‘trigger’ django to show 404/500 pages is to add the routes to your `url.py`:

from django.views.generic.base import TemplateView
if settings.DEBUG:
    urlpatterns += patterns('',
        (r'^500/$', TemplateView.as_view(template_name="404.html")),
        (r'^404/$', TemplateView.as_view(template_name="404.html")),
    )

If you want to see django’s default 500 error page, you can use this instead:

from django.views.defaults import server_error as server_error_view
if settings.DEBUG:
    urlpatterns += patterns('',
        (r'^500/$', server_error_view),
    )

Now you can just navigate to /500/ or /404/ to see the respective error pages.

March 16, 2014
by ktnode
0 comments

getting DEBUG=FALSE to work correctly

Problem: Static resources (images, js, css, etc.) lead to 404 errors.
Potential fix: A similar question was posted here and here. This is actually by design, as django is not meant to server static resources when DEBUG=False.

Basically, when you’re in DEBUG mode, static files are being served via the staticfiles app (which uses settings like STATICFILES_DIRS and STATICFILES_FINDERS to properly locate your static resources). When DEBUG=FALSE, the staticfiles app doesn’t run and your static resources aren’t being referenced correctly by the django webserver. However, if you were to host the files are an actual webserver, the STATIC_URL settings should hold up.

There is a way to force the staticfiles app to run in DEBUG=FALSE mode though, which can be useful when you want to test a deployment locally with django. You just have to add an --insecure flag when you run the django webserver:

django-admin.py runserver --insecure

As noted here, the --insecure option should only be used for testing purposes.

March 15, 2014
by ktnode
0 comments

django + less, updated

In a previous post, I described how I configured the hyperkitty django project to use LESS. Briefly, my steps were:
- install django-compressor, django-less, nodejs, npm, and lessc
- update settings.py with configuration settings for django-compressor and django-less
- restart webserver

However, it turns out some of those steps are a bit outdated. First, PyPI says that django-less is not maintained and suggests using django-static-precompiler instead. Second, while LESS suggests that the easiest way to install the compiler is via npm, it is just as easy to install the LESS compiler via nodejs-less. So here are my updated steps for configuring a django project to use LESS:

pip install django-compressor
pip install django-static-precompiler
sudo yum install nodejs-less # installs lessc

I also realized that my settings.py needed to be updated too. I was previously using DEBUG=TRUE and, under that case, everything worked fine. But when I switched over to DEBUG=FALSE, I noticed a few extra settings needed to be added. So, for the sake of completeness, here are all the changes I made to settings for the hyperkitty project.

  • Add settings to INSTALLED_APPS:
    INSTALLED_APPS = (
    # other apps..
    'compressor',
    'static-precompiler',
    )
    
  • Add settings for django-static-precompiler (more details here):
    STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    # other finders..
    'static_precompiler.finders.StaticPrecompilerFinder',
    )
    STATIC_PRECOMPILER_COMPILERS = (
    'static_precompiler.compilers.LESS',
    )
    
  • Add these settings for django-compressor settings (more details here and here):
    STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    # other finders..
    'compressor.finders.CompressorFinder',
    )
    COMPRESS_PRECOMPILERS = (
    ('text/less', 'lessc {infile} {outfile}'),
    )
    INTERNAL_IPS = ('127.0.0.1',) # enables local compiling
    COMPRESS_ENABLED = True # defaults to opposite of DEBUG
    COMPRESS_OFFLINE = True # allow pre-compression of files
    

February 23, 2014
by ktnode
1 Comment

list overview: other potential features?

I’m wondering if there are other worthwhile personalization features that could be added to the list overview page? For example, I’ve added personalized groups of discussions (bookmarked discussions, discussion you’ve posted to), which contrasts with the general groups of discussions (most recent discussions, most active discussions, etc.). Could we do something similar with the section for list stats? Right now, there’s only general list stats – overall posting frequencies and a leader board of the top posters. Would it be meaningful to add personalized stats? Some ideas I had for this might be:

  • timestamp of when you subscribed to the list
  • timestamp of the last message you posted to that list
  • number of messages you’ve posted to the list
  • number of people who’ve bookmarked/following your discussion/posts
  • average votes for the posts you’ve contributed for that list

What do you think – would you be interested in seeing these personalized list stats? What other personal list stats might be helpful and/or meaningful to add?

Speaking of list stats, I’m also wondering how useful the general stats are, as they are currently designed. Specifically, the chart showing the posting frequency for the last 30 days is definitely informative in that it shows short-term trends. For example, perhaps a big milestone/release is coming up, so you’ll see a big spike in the chart because more people are posting messages. However, long-term trends are not really evident in the current design.

Given that, I’m wondering whether if it would be meaningful to add details like:

  • timestamp of when the list started – is this a relatively new list or one of the older, more established lists?
  • how representative is the chart – by adding a small visual cue (perhaps an up/down arrow), we could indicate whether the posting frequency in the last 30 days is higher/the same/lower than the average posting frequency across the list’s entire lifetime
  • how recent is the activity from the folks on the leader board – is the poster someone who’s still actively posting, or from someone who used to post a lot but is no longer around? We could add a simple timestamp of their last activity to provide a cue for this type of information
  • total number of subscribers to the list – this could be helpful in indicating how popular the list to others
  • categories aren’t implemented yet, but the interface does have a section for listing discussions by category – would it perhaps be more meaningful to have a simple infographic (like a pie chart) in lieu of a listing by category, which gives an overview of what kinds of labels are used in this list? The downside to this idea is that it would be easy to skew the data. For example, if only 1% of the threads in the list are labeled and the entire 1% are put into the flame category, then the pie chart would show a category distribution that makes the list look like it contains an overwhelming number of flame messages.

What do you think – would adding these details be helpful? Are there other list stats that you’d be interested in having on the list overview page?

February 23, 2014
by ktnode
2 Comments

list overview: user scenarios

As described in my previous post, I’ve added a “personalized” section to the list overview page. This hasn’t been implemented on the backend yet, but the intention is to provide extra details for users who have logged in. The difference is just an extra group of discussion threads at the top of the page:

when you’re not logged in: when you’re logged in:
listoverview-nopersonal.1024px listsoverview-personal.1024px

I added this section based on typical day-to-day scenarios of interacting with a mailing list. Typical scenarios for sending messages include: 1) starting a new thread, 2) replying to a discussion that you’ve previously joined, and/or 3) replying to a new/recent thread sent to the list. As such, these sections should be placed near the top of the design. When you’re not logged in, scenario #3 is emphasized by placing the most recent discussions at the top of the page. If you are logged in, then scenario #2 is emphasized a bit more than scenario #3. Scenario #1 is always easily accessible, as the ‘New’ button always appears near the top of the page, regardless of whether you’re logged in or not.

For reading messages, typical scenarios include: 1) reading discussions that contain particularly useful information/links/posts, 2) reading the latest posts to the list, and 3) verifying/correcting previous posts that you’ve sent out to others. Scenarios #2 and #3 are supported in a similar manner as I described in the scenarios for sending messages. When you’re logged in, scenario #1 is supported as there is an extra section for discussions that you’ve bookmarked (referred to as ‘flagged’ in the interface; the wording can be charged, if it’s confusing).

Hopefully these scenarios capture most folk’s typical usage behaviors, though if there’s an important use case that I haven’t covered, I’m all ears!