mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-10-31 16:07:38 +03:00 
			
		
		
		
	initial work on autodiscover
This commit is contained in:
		
							parent
							
								
									b71a24437a
								
							
						
					
					
						commit
						9f6d104dad
					
				|  | @ -1,3 +1,33 @@ | |||
| __version__ = '0.2.3' | ||||
| 
 | ||||
| VERSION = __version__  # synonym | ||||
| 
 | ||||
| from djangorestframework.builtins import DjangoRestFrameworkApi | ||||
| from django.utils.importlib import import_module | ||||
| 
 | ||||
| import imp | ||||
| 
 | ||||
| __all__ = ('autodiscover','api', '__version__', 'VERSION') | ||||
| 
 | ||||
| api = DjangoRestFrameworkApi() | ||||
| 
 | ||||
| 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 entries they | ||||
|     may want. | ||||
|     """ | ||||
|     import copy | ||||
|     from django.conf import settings | ||||
|     from django.utils.importlib import import_module | ||||
| 
 | ||||
|     for app in settings.INSTALLED_APPS: | ||||
|         # Attempt to import the app's gargoyle module. | ||||
|         before_import_registry = copy.copy(api._registry) | ||||
|         try: | ||||
|             import_module('%s.api' % app) | ||||
|         except: | ||||
|             # Reset the model registry to the state before the last import as | ||||
|             # this import will have to reoccur on the next request and this | ||||
|             # could raise NotRegistered and AlreadyRegistered exceptions | ||||
|             api._registry = before_import_registry | ||||
|  |  | |||
							
								
								
									
										95
									
								
								djangorestframework/builtins.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								djangorestframework/builtins.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,95 @@ | |||
| from django.conf.urls.defaults import patterns, url, include | ||||
| 
 | ||||
| class ApiEntry(object): | ||||
|     """ | ||||
|     Hold information about a Resource in the api | ||||
|     """ | ||||
|      | ||||
|     def __init__(self, resource, view, name, namespace=None): | ||||
|         self.resource, self.view, self.name = resource, view, name | ||||
|         self.namespace = namespace is not None and namespace or '' | ||||
|          | ||||
|     def get_urls(self): | ||||
|         """ | ||||
|         Create the URLs corresponding to this view. | ||||
|         """ | ||||
|         from djangorestframework.mixins import ListModelMixin, InstanceMixin | ||||
|         if self.namespace == '': | ||||
|             namespaced_name = self.name | ||||
|         else: | ||||
|             namespaced_name = '%s/%s' % (self.namespace, self.name) | ||||
| 
 | ||||
|         if issubclass(self.view, ListModelMixin): | ||||
|             urlpatterns = patterns('', | ||||
|                 url(r'^%s/$' % (namespaced_name), | ||||
|                     self.view.as_view(resource=self.resource), | ||||
|                     name=self.name, | ||||
|                     ) | ||||
|             ) | ||||
|         elif issubclass(self.view, InstanceMixin): | ||||
|             urlpatterns = patterns('', | ||||
|                 url(r'^%s/(?P<pk>[0-9a-zA-Z]+)/$' % (namespaced_name), | ||||
|                     self.view.as_view(resource=self.resource), | ||||
|                     name=self.name + '_change', | ||||
|                     ) | ||||
|             ) | ||||
|         return urlpatterns | ||||
|      | ||||
| 
 | ||||
|     def urls(self): | ||||
|         return self.get_urls(), 'api', self.namespace | ||||
|     urls = property(urls) | ||||
| 
 | ||||
| class DjangoRestFrameworkApi(object): | ||||
|     app_name = 'api' | ||||
|     namespace = 'api' | ||||
| 
 | ||||
|     def __init__(self, *args, **kwargs): | ||||
|         self._registry = {} | ||||
|         super(DjangoRestFrameworkApi, self).__init__(*args, **kwargs) | ||||
| 
 | ||||
|     def register(self, view, resource, namespace=None, name=None): | ||||
|         """ | ||||
|         Register a resource and a view into the API, optionally giving an  | ||||
|         override for the resource's name and a namespace for the URLs. | ||||
|         """ | ||||
|         if name is None: | ||||
|             if hasattr(resource, 'model'): | ||||
|                 # Use the model's name as the resource_name | ||||
|                 name = resource.model.__name__.lower() | ||||
|             else: | ||||
|                 # Use the Resource's name as the resource_name | ||||
|                 name = resource.__name__.lower() | ||||
|          | ||||
|         resource.api_name = name | ||||
|          | ||||
|         if namespace not in self._registry: | ||||
|             self._registry[namespace] = {} | ||||
|              | ||||
|         if name not in self._registry[namespace]: | ||||
|             self._registry[namespace][name] = [] | ||||
|              | ||||
|         api_entry = ApiEntry(resource, view, name, namespace) | ||||
|         self._registry[namespace][name].append(api_entry) | ||||
| 
 | ||||
|     @property | ||||
|     def urls(self): | ||||
|         return self.get_urls(), self.app_name, self.namespace | ||||
|      | ||||
|     def get_urls(self): | ||||
|         """ | ||||
|         Return all of the urls for this API | ||||
|         """ | ||||
| 
 | ||||
|         # Site-wide views. | ||||
|         urlpatterns = patterns('',) | ||||
| 
 | ||||
|         # Add in each resource's views. | ||||
|         for namespace in self._registry.keys(): | ||||
|             for resource_name in self._registry[namespace].keys(): | ||||
|                 for api_entry in self._registry[namespace][resource_name]: | ||||
|                     urlpatterns += patterns('', | ||||
|                         url(r'^', include(api_entry.urls)) | ||||
|                     ) | ||||
|              | ||||
|         return urlpatterns | ||||
|  | @ -379,6 +379,16 @@ class ModelResource(FormResource): | |||
|                     return reverse(self.view_callable[0], kwargs=instance_attrs) | ||||
|                 except NoReverseMatch: | ||||
|                     pass | ||||
|                  | ||||
|         if hasattr(self, 'api_name'): | ||||
|             # Get the URL from the API | ||||
|             try: | ||||
|                 return reverse( | ||||
|                     '%s:%s_change' % ('api', self.api_name), args=(instance.pk,) | ||||
|                 ) | ||||
|             except NoReverseMatch: | ||||
|                 pass | ||||
|                          | ||||
|         raise _SkipField | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										85
									
								
								djangorestframework/tests/api.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								djangorestframework/tests/api.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,85 @@ | |||
| from django.test.testcases import TestCase | ||||
| from djangorestframework.builtins import DjangoRestFrameworkApi | ||||
| from djangorestframework.resources import Resource, ModelResource | ||||
| from djangorestframework.tests.models import Company, Employee | ||||
| from django.conf.urls.defaults import patterns, url, include | ||||
| from djangorestframework.views import ListOrCreateModelView, InstanceModelView,\ | ||||
|     ListModelView | ||||
| from django.core.urlresolvers import reverse | ||||
| 
 | ||||
| __all__ = ('ApiTestCase',) | ||||
| 
 | ||||
| class CompanyResource(ModelResource): | ||||
|     model = Company | ||||
|      | ||||
| class EmployeeResource(ModelResource): | ||||
|     model = Employee | ||||
|      | ||||
| class UrlConfModule(object): | ||||
|      | ||||
|     def __init__(self, api): | ||||
|         self.api = api | ||||
|          | ||||
|     def _get_urlpatterns(self): | ||||
|         return patterns('',  | ||||
|             url(r'^', include(self.api.urls)), | ||||
|         ) | ||||
|          | ||||
|     urlpatterns = property(_get_urlpatterns) | ||||
| 
 | ||||
| 
 | ||||
| class ApiTestCase(TestCase): | ||||
|      | ||||
|     def setUp(self): | ||||
|         self.api = DjangoRestFrameworkApi() | ||||
|         self.urlconfmodule = UrlConfModule(self.api) | ||||
|          | ||||
|     def test_list_view(self): | ||||
|         # Check that the URL gets registered | ||||
|         self.api.register(ListModelView, CompanyResource) | ||||
|         reverse('api:company', urlconf=self.urlconfmodule) | ||||
|                  | ||||
|     def test_instance_view(self): | ||||
|         self.api.register(InstanceModelView, CompanyResource) | ||||
|         company = Company(name='Acme Ltd') | ||||
|         company.save() | ||||
|         # Check that the URL gets registered | ||||
|         reverse( | ||||
|             'api:company_change', urlconf=self.urlconfmodule, | ||||
|             kwargs={'pk':company.id},  | ||||
|         ) | ||||
|          | ||||
|     def test_instance_view_with_nonumeric_primary_key(self): | ||||
|         """ | ||||
|         Check that the api can properly reverse urls for models with | ||||
|         non-numeric primary keys  | ||||
|         """ | ||||
|         self.api.register(InstanceModelView, EmployeeResource) | ||||
|         employee = Employee(employee_id='EMP001') | ||||
|         employee.save() | ||||
|         reverse( | ||||
|             'api:employee_change', urlconf=self.urlconfmodule, | ||||
|             kwargs={'pk':employee.employee_id} | ||||
|         ) | ||||
|          | ||||
|     def test_with_different_name(self): | ||||
|         self.api.register(InstanceModelView, CompanyResource, name='abcdef') | ||||
|         company = Company(name='Acme Ltd') | ||||
|         company.save() | ||||
|         # Check that the URL gets registered | ||||
|         reverse( | ||||
|             'api:abcdef_change', urlconf=self.urlconfmodule, | ||||
|             kwargs={'pk':company.id},  | ||||
|         ) | ||||
|          | ||||
|     def test_with_prefix(self): | ||||
|         self.api.register( | ||||
|             InstanceModelView, CompanyResource, namespace='abcdef' | ||||
|         ) | ||||
|         company = Company(name='Acme Ltd') | ||||
|         company.save() | ||||
|         # Check that the URL gets registered | ||||
|         reverse( | ||||
|             'api:abcdef:company_change', urlconf=self.urlconfmodule, | ||||
|             kwargs={'pk':company.id},  | ||||
|         ) | ||||
|  | @ -26,3 +26,9 @@ class UserGroupMap(models.Model): | |||
|         return ('user_group_map', (), { | ||||
|             'pk': self.id | ||||
|         })           | ||||
|          | ||||
| class Company(models.Model): | ||||
|     name = models.CharField(max_length=20)   | ||||
|          | ||||
| class Employee(models.Model): | ||||
|     employee_id = models.CharField(max_length=20, primary_key=True)   | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user