По сути мы к урлам привязываем функции, а значит получается мы используем простое функциональное программирование, и не очевидно, как в такой ситуации воспользоваться всем обилием объектно-ориентированого программирования, которое предоставляет Python.
Также, Django, продвигает полезную фикчу, которое должно подтолкнуть пользователей всего мира делится своим джанговским кордом, это инклюд одного приложения в другого. И все было бы очень просто и радужно, если б не несколько небольших «но». Это «MIDDLEWARE_CLASSES». Как правило, приложениям, которые вы хотите подключить, необходимо с собой тянуть эти классы. Тем, кто не в курсе, объясню, в них собран функционал, который будет запускатся до и после вызова функции, которая закрепленная за урлом. Но иногда этот функционал необходим только этому апликейшену, а для остальных это просто лишний и не нужный своп. Нет возможности привязать миддл только к определенному апликейшену.
Вопросы расширяемости. Это вопрос объектно-орентированого программирования, о котором я говорил выше. Его по сути нет. Вам дали апликейшен – пользуйтесь. Все, что можно менять в его работе – лежит в настройках ВСЕГО проекта, либо в параметрах передаваемых самому инклюду. А хотите больше? Копайтесь в моих исходниках и пишите то, что вам надо.
Вот мое решение.
-
-
from django.conf.urls.defaults import url
-
-
class AddNewUrl(object):
-
def __init__(self,prefix,view,*t):
-
self.prefix = prefix
-
self.view = view
-
self.t = t
-
def __call__(self,*t,**k):
-
if 'before' in self.prefix :
-
self.prefix['before'](*t,**k)
-
return self.view(*t,**k)
-
-
def newpatterns(prefix, *args):
-
pattern_list = []
-
for t in args:
-
pattern_list.append(newurl(prefix, *t))
-
return pattern_list
-
-
def newurl(prefix,regex,view,*t):
-
return url(regex,AddNewUrl(prefix,view,*t),*t)
-
-
-
def classpatterns(cp):
-
o_cp = cp()
-
cp_prefix = {}
-
if hasattr(o_cp,'before_cp'):
-
before_cp = getattr(o_cp,'before_cp')
-
if callable(before_cp):
-
cp_prefix['before'] = before_cp
-
func_list = ()
-
for item in dir(o_cp):
-
if item.startswith('cp__'):
-
item_func = getattr(o_cp,item)
-
if callable(item_func):
-
func_list = func_list + ((r'^'+item[4:]+'/$',item_func),)
-
#raise str(func_list)
-
return newpatterns(cp_prefix,*func_list)
Теперь урлы и вьювы – объединены в одном классе.
Если вы хотите написать обработчик урла «^home/$» , то вам можно просто написать функцию cp_home в которой и будет вестись обработка вашего запроса.
Если у вас есть функция, которую необходимо дергать перед запускам каждого обработчика, то назовите ее before_cp
Но есть и ограничения, которые я еще не преодолевал, т.к. они пока особо меня не касались:
Нельзя в полной мере воспользоваться регекспами в урлах.
Нельзя использовать инклюды внутри такого аппликейшена. А вы думаете они правда нужны при таком построении приложения?
Приложения такого типа типа лучше не использовать на «первом уровне» а только инклюдить в основное.
Но как мне кажется, такие ограничения можно не сложно побороть. Например, регекспы в урлах можно побороть декораторами.
Вот пример использования:
файл ajax/vurl.py
-
-
from newpatern.defaults import newpatterns, classpatterns
-
django.http import HttpResponse
-
class Views(BaseViews):
-
def cp__connect(self,request):
-
return HttpResponse('HI ALL')
-
def cp__NO(self,request):
-
return HttpResponse(reqest.GET.get('n'))
-
-
urlpatterns = classpatterns(Views)
Обратите внимание, что в этих урлах первым парамером передается self. Да, это экземпляр класса, который создается один раз
В Ваш файл с урлами просто вставте:
-
(r'^flashajax/',include('ajax.vurls')),
Теперь по запросу flashajax/connect/
в ответ получить “HI ALL”
Согласен, сам класс newpaterns еще не идеален, но он, как мне кажется, показывает качественно новый подход, который можно расширять и использовать.
Что касается меня, то я его уже юзаю в одном из своих проектов, пока успешно. Хотя проект еще не в продакшене, поэтому однозначно судить нельзя
Recent Comments