inital work on autodiscover

This commit is contained in:
Craig Blaszczyk 2011-07-22 11:17:42 +01:00
parent b9fcea093c
commit 742e9289cf
3 changed files with 171 additions and 3 deletions

View File

@ -1,3 +1,74 @@
__version__ = '0.2.3'
VERSION = __version__ # synonym
from djangorestframework.builtins import DjangoRestFrameworkSite
try:
VERSION = __import__('pkg_resources') \
.get_distribution('gargoyle').version
except Exception, e:
VERSION = 'unknown'
from django.utils.importlib import import_module
import imp
__all__ = ('autodiscover','site')
api = DjangoRestFrameworkSite()
# A flag to tell us if autodiscover is running. autodiscover will set this to
# True while running, and False when it finishes.
LOADING = False
def autodiscover():
"""
Auto-discover INSTALLED_APPS api.py modules and fail silently when
not present. This forces an import on them to register any api bits they
may want.
"""
# Bail out if autodiscover didn't finish loading from a previous call so
# that we avoid running autodiscover again when the URLconf is loaded by
# the exception handler to resolve the handler500 view. This prevents an
# admin.py module with errors from re-registering models and raising a
# spurious AlreadyRegistered exception.
global LOADING
if LOADING:
return
LOADING = True
from django.conf import settings
for app in settings.INSTALLED_APPS:
# For each app, we need to look for a api.py inside that
# app's package. We can't use os.path here -- recall that modules may be
# imported different ways (think zip files) -- so we need to get
# the app's __path__ and look for api.py on that path.
# Step 1: find out the app's __path__ Import errors here will (and
# should) bubble up, but a missing __path__ (which is legal, but weird)
# fails silently -- apps that do weird things with __path__ might
# need to roll their own api registration.
try:
app_path = import_module(app).__path__
except (AttributeError, ImportError):
continue
# Step 2: use imp.find_module to find the app's gargoyle_conditions.py.
# For some # reason imp.find_module raises ImportError if the app can't
# be found # but doesn't actually try to import the module. So skip this
# app if its gargoyle.py doesn't exist
try:
imp.find_module('api', app_path)
except ImportError:
continue
import_module("%s.api" % app)
print 'aaaaaaaaaaaaa',app
# autodiscover was successful, reset loading flag.
LOADING = False

View File

@ -0,0 +1,89 @@
from djangorestframework.mixins import ListModelMixin, InstanceMixin
from django.conf.urls.defaults import patterns, url
class DjangoRestFrameworkSite(object):
app_name = 'api'
name = 'api'
def __init__(self, *args, **kwargs):
self._registry = {}
super(DjangoRestFrameworkSite, self).__init__(*args, **kwargs)
def register(self, view, resource, prefix=None, resource_name=None):
if resource_name is None:
if hasattr(resource, 'model'):
resource_name = resource.model.__name__.lower()
else:
resource_name = resource.__name__.lower()
if prefix not in self._registry:
self._registry[prefix] = {}
if resource_name not in self._registry[prefix]:
self._registry[prefix][resource_name] = []
self._registry[prefix][resource_name].append((resource, view))
# def unregister(self, prefix=None, resource_name=None, resource=None):
# """
# Unregisters a resource.
# """
# if resource_name is None and resource is not None and \
# hasattr(resource, 'model'):
# resource_name = resource.model.__name__.lower()
#
# if resource_name is None:
# # do nothing
# return
#
# prefix_registry = self._registry.get(prefix, {})
# if resource_name in prefix_registry:
# del prefix_registry[resource_name]
@property
def urls(self):
return self.get_urls(), self.app_name, self.name
def get_urls(self):
# Site-wide views.
urlpatterns = patterns('',
)
# Add in each resource's views.
for prefix in self._registry.keys():
for resource_name in self._registry[prefix].keys():
for resource, view in self._registry[prefix][resource_name]:
urlpatterns += self.__get_urlpatterns(
prefix, resource_name, resource, view
)
return urlpatterns
def __get_urlpatterns(self, prefix, resource_name, resource, view):
"""
Calculates the URL pattern for a given resource and view
"""
if prefix is None:
prefix = ''
else:
prefix += '/'
if issubclass(view, ListModelMixin):
urlpatterns = patterns('',
url(r'^%s%s/' % (prefix,resource_name),
view.as_view(resource=resource),
name=resource_name
)
)
elif issubclass(view, InstanceMixin):
urlpatterns = patterns('',
url(r'^%s%s/(?P<pk>[0-9]+)/$' % (prefix,resource_name),
view.as_view(resource=resource),
name=resource_name + '_change'
)
)
return urlpatterns

View File

@ -279,13 +279,13 @@ class ModelResource(FormResource):
include = ('url',)
def __init__(self, view=None, depth=None, stack=[], **kwargs):
def __init__(self, view):
"""
Allow :attr:`form` and :attr:`model` attributes set on the
:class:`View` to override the :attr:`form` and :attr:`model`
attributes set on the :class:`Resource`.
"""
super(ModelResource, self).__init__(view, depth, stack, **kwargs)
super(ModelResource, self).__init__(view)
self.model = getattr(view, 'model', None) or self.model
@ -355,7 +355,7 @@ class ModelResource(FormResource):
# dis does teh magicks...
urlconf = get_urlconf()
resolver = get_resolver(urlconf)
possibilities = resolver.reverse_dict.getlist(self.view_callable[0])
for tuple_item in possibilities:
possibility = tuple_item[0]
@ -379,6 +379,14 @@ class ModelResource(FormResource):
return reverse(self.view_callable[0], kwargs=instance_attrs)
except NoReverseMatch:
pass
try:
model_name = instance.__class__.__name__.split('.')[0].lower()
return reverse('%s:%s_change' % ('api', model_name), args=(instance.pk,))
except NoReverseMatch:
pass
import pdb
pdb.set_trace()
raise _SkipField