2012-05-24 2 views
0

Я создал промежуточное программное обеспечение, которое позволяет мне использовать список словарей, чтобы указать некоторые правила доступа для любого из моих представлений. Каждый из этих словарей выглядит следующим образом:В каком порядке сортировать требования к соответствию пути к промежуточному программному обеспечению?

REQUIREMENTS=(
    {'viewname':'addtag', 
    'permissions':'can_add_tags'}, 
    {'regex':re.compile(r'^somestart'), 
    'user_check':lambda request:request.user.username=='sam'} 
) 

В моем промежуточном слое я затем попытаться выяснить, какие из этих требований соответствует текущему запросу. Для этого я фильтровать полные требования, и в функции фильтра я использовать этот код, чтобы проверить, если путь соответствует:

def process_request(self,request): 

    def path_matches(self,req): 
     path_matches = False 

     if (req.has_key('url') and req['url'] == request.path) or\ 
      (req.has_key('regex') and req['regex'].search(request.path)) or\ 
      (req.has_key('viewname') and resolve(request.path).url_name==req['viewname']): 
      path_matches=True 

     return path_matches 

    requirements = filter(path_matches,REQUIREMENTS) 
    # now use the returned requirements to determine if a user 
    # matches the requirement and 

Мой вопрос теперь: в каком порядке я должен использовать чеки? Довольно ясно, что проверка URL-адреса самая быстрая, так что это должно быть первыми. Но тогда возникает вопрос, следует ли сначала искать регулярное выражение или функцию разрешения URL-адреса django.

Поскольку у меня сейчас нет проблем с производительностью, это скорее академический вопрос. И если бы у кого-то было бы лучшее решение для решения этого вопроса, это было бы еще лучше.


редактировать:

реагировать на данные ответы: то, что я пытаюсь сделать, это создать возможность ограничить вид нескольких внешних приложений в одном файле. Так декораторы не вариант, до тех пор, как я не хочу, чтобы сделать что-то вроде этого:

from ext_app1 import view1,view2 
from ext_app2 import view3 

@permission_required('can_do_stuff') 
def view1_ext(*args,**kwargs): 
    return view1(args,kwargs) 

, который приведет к перезаписи спецификации URL-адреса каждый раз, когда я изменить права доступа. Я хочу этого избежать. Кроме того, мое решение позволяет функция user_check сделать проверку на пользователях, как это:

def check_user(user): 
    if len(Item.objects.get(creator=user,datetime=today)) > 3: 
     return False 
    return True 

Это будет простым способом, т.е. ограничить количество элементов, пользователь может загрузить каждый день.. (Хорошо, это было бы возможно и с user_passes_test).

Еще одна вещь заключается в том, что я иногда хочу проверить разрешение только в том случае, если запрос является POST, или если запрос содержит определенную пару ключей: значение (например, 'action':'delete' должно требовать разрешения, а 'action':'change' должно быть разрешено для кто угодно). Это можно сделать и с помощью специального декоратора, но как только мне понадобится новая проверка, мне понадобится новый декоратор.

ответ

1

Возможно, вы ищете user_passes_test decorator.

Вы можете украсить виды, которые вам нужны, вместо использования промежуточного программного обеспечения.

код будет выглядеть следующим образом:

from django.contrib.auth.decorators import user_passes_test 

@user_passes_test(lambda user: user.has_perm('model.can_add_tags') \ 
           and user.username == 'sam') 
def my_view(request): 
    ... 
1

Если вы используете Django встроенный в user authentication and permissions system (django.contrib.auth), то вам следует рассмотреть возможность использования просмотр декораторы он предоставляет вместо промежуточного программного обеспечения. Это даст вам ряд преимуществ:

  • код, который изменяется вместе в том же самом месте, то есть это более вероятно, что вам необходимо изменить разрешения для конкретного просмотра, когда вы меняете код вида по чем когда вы изменяете другие разрешения.
  • Вам не нужно писать большую часть кода самостоятельно, что делает ваш проект меньше и проще в обслуживании.

Для простых ситуаций вы можете использовать login_required и permission_required декораторов, а для более сложного условия user_passes_test декоратора позволяет проверить, если пользователь проходит какое-либо условие, вы заботитесь указать.

код выглядит примерно так для функции вида (example is lifted from the documentation):

from django.contrib.auth.decorators import permission_required 

@permission_required('polls.can_vote') 
def my_view(request): 
    ... 

Если вы используете class-based views, то это выглядит немного по-другому (опять же, это example is lifted from the documentation):

from django.contrib.auth.decorators import login_required 
from django.utils.decorators import method_decorator 
from django.views.generic import TemplateView 

class ProtectedView(TemplateView): 
    template_name = 'secret.html' 

    @method_decorator(login_required) 
    def dispatch(self, *args, **kwargs): 
     return super(ProtectedView, self).dispatch(*args, **kwargs) 

Если у вас есть веская причина не использовать систему разрешений Django, вы все равно можете использовать аналогичный подход. code for the django.contrib.auth decorators можно легко использовать в качестве основы для ваших собственных декораторов.

+0

Спасибо за ваш обширный ответ. Я обновил свой вопрос, чтобы отреагировать на него. – marue

Смежные вопросы