# myProject\ajax\__init__.py
from dispatcher import dispatcher

# myProject\ajax\dispatcher.py
from django import http
import re

class AlreadyRegistered(Exception):
    pass

class NotCallable(Exception):
    pass

class Dispatcher(object):

    def __init__(self):
        self._funcs = {} # Reference name -> Ajax Function

    def register(self, name, func, force_override=False):
        if not callable(func):
            raise NotCallable('The supplied AJAX function %s is not a function (it is not callable).' % func.__name__)

        if name in self._funcs and not force_override:
            raise AlreadyRegistered('The AJAX function name %s is already registered' % name)

        # Instantiate the admin class to save in the registry
        self._funcs[name] = func

    def has_permission(self, request):
        """
        Returns True if the given HttpRequest has permission to view
        *at least one* page in the admin site.
        """
        return request.user.is_authenticated() and request.user.is_staff

    def urls(self, request, url):
        """
        Handles main URL routing for the admin app.

        `url` is the remainder of the URL -- e.g. 'comments/comment/'.
        """
        if request.method == 'GET' and not request.path.endswith('/'):
            return http.HttpResponseRedirect(request.path + '/')

        # Figure out the admin base URL path and stash it for later use
        self.root_path = re.sub(re.escape(url) + '$', '', request.path)

        url = url.rstrip('/') # Trim trailing slash, if it exists.

        # Check permission to continue or display login form.
        if not self.has_permission(request):
            return http.HttpResponseForbidden('You do not have permission to view the requested information.')

        if url == '':
            return http.HttpResponseForbidden('An AJAX function must be specified.')
        else:
            return self._funcs[url](request)

        raise http.Http404('The requested admin page does not exist.')

dispatcher = Dispatcher()