Browse Source

POC for coin modules with pluggable URLs to avoid modifying urls.py

Jocelyn Delande 10 years ago
parent
commit
ac733fd9b0
6 changed files with 83 additions and 2 deletions
  1. 41 0
      coin/apps.py
  2. 15 2
      coin/urls.py
  3. 1 0
      simple_dsl/__init__.py
  4. 10 0
      simple_dsl/apps.py
  5. 7 0
      simple_dsl/urls.py
  6. 9 0
      simple_dsl/views.py

+ 41 - 0
coin/apps.py

@@ -0,0 +1,41 @@
+import six
+import django
+from django.apps import apps
+from os.path import basename
+
+class AppURLsMeta(type):
+    def __init__(cls, name, bases, data):
+        if len(bases) > 1: # execute only on leaf class
+            exported_urlpatterns = data.pop('exported_urlpatterns', None)
+
+            if exported_urlpatterns:
+                cls.exported_urlpatterns = exported_urlpatterns
+            else:
+                # Default : sets
+                #   exported_urlpatterns = [(<app_name>, <app_url_module>)]
+                current_path = basename(__file__).rstrip('.py')
+                url_module = cls.__module__.rstrip(current_path) + '.urls'
+                cls.exported_urlpatterns = [(data['name'], url_module)]
+
+            cls.urlprefix = data.pop('urlprefix', None)
+
+
+class AppURLs(six.with_metaclass(AppURLsMeta)):
+    """ App Mixxin to allow an application to expose pluggable urls
+
+    That's to say, URLs which will be added automatically to the projet
+    urlpatterns.
+
+    You can just make your app inherit from AppURLs, yous app urls.py will be
+    picked and wired on project urlpatterns, using the app name as prefix.
+
+    You can also customize which urlpatterns your app exposes by setting the
+    `exported_urlpattens` on your AppConfig class as list of `<prefix>,<urlpatterns>`
+
+    E.g:
+
+        class MyAppConfig(AppConfig, coin.apps.AppURLS):
+            name = 'my_app'
+            exported_urlpatterns = [('my_app', 'myapp.cool_urls')]
+    """
+    pass

+ 15 - 2
coin/urls.py

@@ -6,8 +6,9 @@ from django.conf.urls import patterns, include, url
 from django.conf.urls.static import static
 from django.contrib.staticfiles.urls import staticfiles_urlpatterns
 
-from coin import views
 
+from coin import views
+import coin.apps
 
 import autocomplete_light
 autocomplete_light.autodiscover()
@@ -17,6 +18,18 @@ admin.autodiscover()
 
 from coin.isp_database.views import isp_json
 
+
+
+from django.apps import apps
+def apps_urlpatterns():
+    """ Yields url lists ready to be appended to urlpatterns list
+    """
+    for app_config in apps.get_app_configs():
+        if isinstance(app_config, coin.apps.AppURLs):
+            for prefix, patterns in app_config.exported_urlpatterns:
+                yield url(r'^{}/'.format(prefix), include(patterns))
+
+
 urlpatterns = patterns(
     '',
     url(r'^$', 'coin.members.views.index', name='home'),
@@ -39,4 +52,4 @@ urlpatterns = patterns(
 
 urlpatterns += staticfiles_urlpatterns()
 urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
-
+urlpatterns += list(apps_urlpatterns())

+ 1 - 0
simple_dsl/__init__.py

@@ -0,0 +1 @@
+default_app_config = 'simple_dsl.apps.SimpleDSLconfig'

+ 10 - 0
simple_dsl/apps.py

@@ -0,0 +1,10 @@
+from django.apps import AppConfig
+import coin.apps
+from . import urls
+
+class SimpleDSLconfig(AppConfig, coin.apps.AppURLs):
+    name = 'simple_dsl'
+    verbose_name = 'Simple DSL Module'
+
+    # that's the default
+    #exported_urlpatterns = [('simple_dsl', urls.urlpatterns)]

+ 7 - 0
simple_dsl/urls.py

@@ -0,0 +1,7 @@
+from __future__ import unicode_literals
+
+from django.conf.urls import patterns, include, url
+
+urlpatterns = patterns('simple_dsl.views',
+    url(r'^lines/$', 'my_lines'),
+)

+ 9 - 0
simple_dsl/views.py

@@ -2,5 +2,14 @@
 from __future__ import unicode_literals
 
 from django.shortcuts import render
+from django.http import HttpResponse
+
+from .models import SimpleDSL
 
 # Create your views here.
+def my_lines(request):
+    """ Simple text response with user phone numbers
+    """
+    lines = SimpleDSL.objects.filter(
+        offersubscription__member=request.user)
+    return HttpResponse(', '.join([l.phone_number for l in lines]))