1

Each user in my Django application is associated with a department, and virtually every request involves some department-related processing. So I'd love to make the department object available across the entire application.

Which of these, if any, is the most appropriate approach to take:

  1. Custom middleware that simply retrieves the related department from the DB and attaches it to the request object, say as request.department, sort of like Django's AuthenticationMiddleware makes the currently logged-in user available at request.user. (See, e.g., here and here)
  2. Placing the department in the session when the user logs in, and subsequently retrieving it in views using Django's request.session interface.

I haven't had an opportunity to get familiar with Django's caching features yet, but I'd like to eventually cache the department on a per-user basis to avoid the extra DB hit on every request. I see that Django's sessions provide built-in caching support. I also imagine that caching can be implemented with the first approach as well.

Is there an advantage to using sessions (#2 above) over custom middleware (#1 above) for this kind of thing? The middleware approach seems cleaner from an internal API standpoint, but I'm guessing this is exactly the kind of thing sessions are designed for -- so perhaps this is the right opportunity to start using them?

Thanks for any guidance!

tino
  • 4,780
  • 5
  • 24
  • 30

1 Answers1

1

Basically both approaches are quite similar. request.session approach can just get eliminate an extra step with setting up a caching in middleware manually. The bad thing about session approach is that the data is not guaranteed to be available if you use cache storage out of box. For example, there can be 0.1% of users with disabled cookies, you are using memcache storage there can be a necessity to restart your memcache server on redeploy and your logged-in users will lost their data, etc. In summary, I would not use sessions with cache storage for crucial data. In my projects I prefer to use 1st option as it gives me a greater level of control.

You can set up have special middleware adding view_name variable to the request and enabling to control where and what to show:

class NameMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        # add current view
        if isinstance(view_func, str):
            request.view_name = view_func
        elif hasattr(view_func, '__name__'):
            request.view_name = view_func.__name__

Then, you will have a greater control on where to provide additional information to the request, for example in context_processors you can attach department inf only to the selected views and cache a result in an efficient way(proxing a request to the database if you want):

def department_context_processor(request):
    if hasattr(request, 'view_name'):
        if request.view_name == 'department_view1' or request.view_name == 'department_view2':
            departments = cache.get('department_'+str(request.user), None)
            if departments is None:
                departments = Department.objects.filter(user=request.user)
                cache.set('department_'+str(request.user), departments, 60*60)
            if departments:
                return {
                    'departments': departments
                }
    return {}
Dmytriy Voloshyn
  • 1,032
  • 12
  • 27
  • Thanks for the suggestions and feedback, Dmytriy! Really helpful. Is this the kind of use case where using cookie-based storage for the session data might work well? By that, I mean storing the department itself in the cookie. If I understand correctly, that would render caching of the session data unnecessary -- the data would be sent by the client (and available to the server) on every request. – tino Jan 04 '14 at 17:07
  • @tino Yes, if you data is quite simple and you do not want to mess with caching. Keep in mind that using cookie-based session has few significant limitations. For example there a 4Kb limitation for cookie size per domain, more detailed comparision can be found [here](http://stackoverflow.com/a/18240232/1255305). Anyway, if you will be using cookie based storage you should take care of use-cases when user clears cookies and they are not in the request and ensure that you do not store any private-to-department information in cookies as they can be hacked. – Dmytriy Voloshyn Jan 04 '14 at 22:16
  • Got it. Thanks again. And I appreciated the caching example as well. – tino Jan 04 '14 at 23:13