docs: def get_site_decorator(site_param='site', obj_param='obj', context_param='context'):
      ''' It is a function that returns decorator factory useful for PluggableSite
          views. This decorator factory returns decorator that do some
          boilerplate work and make writing PluggableSite views easier.
          It passes PluggableSite instance to decorated view,
          retreives and passes object that site is attached to and passes
          common context. It also passes and all the decorator factory's
          keyword arguments.
  
          For example usage please check photo_albums.views.
  
          Btw, this decorator seems frightening for me. It feels that
          "views as PluggableSite methods" approach can easily make this decorator
          obsolete. But for now it just works.
      '''
      def site_method(**extra_params):
          def decorator(fn):
              @wraps(fn)
              def wrapper(request, **kwargs):
                  try:
                      site = kwargs.pop(site_param)
                  except KeyError:
                      raise ValueError("'%s' parameter must be passed to "
                                       "decorated view (%s)" % (site_param, fn))
  
                  # Pop parameters to be passed to actual view function.
                  params={}
                  for key in extra_params:
                      value = kwargs.pop(key, extra_params[key])
                      params.update({key:value})
  
                  # Now there are only site.object_getter lookup parameters in
                  # kwargs. Get the object and compute common request context.
                  try:
                      obj = site.object_getter(**kwargs)
                  except models.ObjectDoesNotExist:
                      raise Http404("Base object does not exist.")
  
                  context = site.get_common_context(obj)
                  context_instance = RequestContext(request, context,
                                         processors=site.context_processors)
  
                  # pass site name, the object and common request to decorated view
                  params.update({
                                  site_param:site,
                                  obj_param: obj,
                                  context_param: context_instance
                               })
                  return fn(request, **params)
              return wrapper
          return decorator
      return site_method