class RestMiddleware(object): """ generic middleware that looks up model ids specified on the url path and stores it in a ``models'' dictionary in the request object. Accepts a ``model_map'' dictionary that specifies the mapping between path variable names ``(?P)'' and corresponding model managers. Example: -------- model_map = { 'session': models.GameSession.objects, } url(r'^session/(?P)/operation$) will lookup the appropriate `` GameSession'' object using the ``GameSession'''s model manager and stores it at ``request.models['session']''. A ``None'' object will be stored if the model lookup was not successful. """ def __init__(self, model_map=None, require_login=True, prefetch_related=None, select_related=None): self.model_map = model_map if model_map else {} self.prefetch_related = prefetch_related if prefetch_related else {} self.select_related = select_related if select_related else {} self.require_login = bool(require_login) def process_view(self, request, view_func, view_args, view_kwargs): if self.require_login and (not hasattr(request, 'user') or not request.user.is_authenticated()): return redirect_to_login(request.get_full_path()) else: if not hasattr(request, 'models'): request.models = {} for view_arg, pk in view_kwargs.iteritems(): manager = self.model_map.get(view_arg) prefetch_related = self.prefetch_related.get(view_arg) if prefetch_related: manager = manager.prefetch_related(*prefetch_related) select_related = self.select_related.get(view_arg) if select_related: manager = manager.select_related(*select_related) if manager: try: obj = manager.get(pk=pk) request.models[view_arg] = obj except ObjectDoesNotExist: pass class Game1RestMiddleware(RestMiddleware): def __init__(self, require_login=True, prefetch_related=None, select_related=None): model_map = { 'session': models.GameSession.objects, 'collectible': models.Collectible.objects.select_subclasses(), 'category': models.Category.objects, 'chest': models.TreasureChest.objects, 'message': models.Message.objects, 'image': models.Image.objects, } super(Game1RestMiddleware, self).__init__( model_map=model_map, require_login=require_login, prefetch_related=prefetch_related, select_related=select_related ) def process_view(self, request, view_func, view_args, view_kwargs): result = super(Game1RestMiddleware, self).process_view(request, view_func, view_args, view_kwargs) try: rmodels = request.models except AttributeError: request.models = {} rmodels = request.models # pull the game session from # the chest or collectible if possible # # do not do this for other models, i.e. do not pull the chest from # a deposited collectible if not 'session' in rmodels: chest = rmodels.get('chest') if chest and chest.session: rmodels['session'] = chest.session if not 'session' in rmodels: collectible = rmodels.get('collectible') if collectible and collectible.session: rmodels['session'] = collectible.session return result