Повторяющийся код в представлениях Django: как избежать повторения? - PullRequest
0 голосов
/ 20 июня 2019

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

def whatever_view_name(request, id, access_id):
    check = Access.objects.filter(user=request.user, id=access_id)
    if check:
        access_object = check[0]
    else:
        return redirect(reverse("create_new_access_object"))

    .... and now my view-specific code will follow ...

Так что мне нужно проверить, существует ли конкретная запись базы данных (доступ) для этого конкретного пользователя.Этот код многократно повторяется, что кажется неправильным.Я думал об использовании промежуточного программного обеспечения, но есть две проблемы: а) Мне нужно использовать этот объект в представлении (см. Переменную access_object, поэтому я боюсь, что мне придется запросить его дважды, если я помещу его в промежуточное программное обеспечение).) и б) мне не нужно делать это ВСЕГДА, поэтому мне интересно, как запустить его только для некоторых представлений, а не для всех, если это промежуточное программное обеспечение.

Есть мысли?

Ответы [ 2 ]

2 голосов
/ 20 июня 2019

Вы можете написать декоратор для этого:

from functools import wraps

def check_access(function):
  @wraps(function)
  def wrap(request, id, access_id, *args, **kwargs):
        check = Access.objects.filter(user=request.user, id=access_id)
        if check.exists():
             return function(request, id, access_id, *args, **kwargs)
        else:
            return redirect(reverse("create_new_access_object"))
  return wrap

# usage

@check_access
def whatever_view_name(request, id, access_id):
     return ...
2 голосов
/ 20 июня 2019

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

Примерно так:

У нас может быть супер класс, подобный этому

class AccessVerifiedView(View):
     def get(self, request, *args, **kwargs):
        check = Access.objects.filter(user=request.user, id=kwargs["access_id"])
        if check:
            access_object = check[0]
            self.verified_get(access_object)
        else:
            return redirect(reverse("create_new_access_object"))

    def verified_get(self, access_object):
        raise NotImplementedError

Тогда мы можем расширить этот класс и использование в наших представлениях.

class MyView(AccessVerifiedView):
    def verified_get(self, access_object):
        return access_object

Этот подход выглядит немного более читабельным. Любой, кто видит код, может видеть суперкласс и понимать поток кода.

Другие несколько способов сделать это

  1. Декоратор: у нас может быть декоратор, который будет делать то же самое. И тогда мы можем украсить вид, который мы хотим проверить.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...