Я создал декоратор в своем проекте Django для добавления значений параметров в параметры оформленного метода.
Я делаю это с помощью inspect.getargspec
чтобы проверить, какие параметры присутствуют в методе, и поместить их в kwargs
. В противном случае я получаю ошибку из-за неправильного количества параметров в методе.
Хотя это работает должным образом в отдельных методах представления, оно завершается ошибкой, когда дело касается представлений на основе классов Django.
Я полагаю, что это может быть потому, что декораторы применяются с помощью @method_decorator
на уровне класса к методу dispatch
а не к отдельным методам get
и post
.
Я новичок в Python и, возможно, пропускаю что-то очевидное здесь.
Есть ли лучший способ сделать то, что я делаю? Можно ли получить имена параметров метода в представлении на основе классов?
Я использую Python 2.7 и Django 1.11
Декоратор
def need_jwt_verification(decorated_function):
@wraps(decorated_function)
def decorator(*args, **kwargs):
request = args[0]
if not isinstance(request, HttpRequest):
raise RuntimeError(
"This decorator can only work with django view methods accepting a HTTPRequest as the first parameter")
if AUTHORIZATION_HEADER_NAME not in request.META:
return HttpResponse("Missing authentication header", status=401)
jwt_token = request.META[AUTHORIZATION_HEADER_NAME].replace(BEARER_METHOD_TEXT, "")
try:
decoded_payload = jwt_service.verify_token(jwt_token)
parameter_names = inspect.getargspec(decorated_function).args
if "phone_number" in parameter_names or "phone_number" in parameter_names:
kwargs["phone_number"] = decoded_payload["phone"]
if "user_id" in parameter_names:
kwargs["user_id"] = decoded_payload["user_id"]
if "email" in parameter_names:
kwargs["email"] = decoded_payload["email"]
return decorated_function(*args, **kwargs)
except JWTError as e:
return HttpResponse("Incorrect or expired authentication header", status=401)
return decorator
Представление на основе классов
@method_decorator([csrf_exempt, need_jwt_verification], name="dispatch")
class EMController(View):
def get(self, request, phone_number, event_id):
data = get_data()
return JsonResponse(data, safe=False)
def post(self, request, phone_number, event_id):
return JsonResponse("Operation successful", safe=False)
РЕДАКТИРОВАТЬ:
Очевидное решение применения декоратора на уровне метода не работает с представлениями на основе классов Django. Вам необходимо применить декоратор в конфигурации URL или применить декоратор к методу отправки.
РЕДАКТИРОВАТЬ: я опубликовал код, который был связан с обходным путем, который я изучал, передавая имена параметров в качестве аргумента в декоратор.