关于路径和自定义装饰器的 Python3 Django 问题

Posted

技术标签:

【中文标题】关于路径和自定义装饰器的 Python3 Django 问题【英文标题】:Python3 Django issues regarding paths and custom decorators 【发布时间】:2020-03-13 10:30:02 【问题描述】:

第一次使用Django 时比较陌生。 Python 不是我在网络环境中的强项——我制作的自定义装饰器存在问题,它会从所有请求中解码 jwt,但不确定它在寻找什么。

可以在最底部找到错误消息。下面是我的文件的样子,我只是尝试使用verify_token() 作为装饰器,在接收 HTTP 请求时包含我的自定义令牌检查器(请不要推荐 simple-jwt 或 django 会话令牌)最终不是我们想要做,因为我们正在处理来自其他 DBS 的遗留表,并且不想要任何抽象)

decorators.py

from django.core.exceptions import PermissionDenied
import jwt


def verify_token(function):
    def wrap(request, *args, **kwargs):
        if request:
            print('========='.format(request))
            jwt.decode(request, 'secret', algorithms=['HS256'])

        else:
            raise PermissionDenied
        wrap.__doc__ = function.__doc__
        wrap.__name__ = function.__name__
        return wrap

views.py

from .User_Predictions.PredictionService import PredicitonController
from django.http import JsonResponse
from rest_framework.views import APIView
from .decorators import verify_token


class UserPredictions(APIView):
    @verify_token
    def generate_full_report(request):
        _predction = PredicitonController()
        results = _predction.compile_complete_predition()
        return JsonResponse(results, safe=False)

urls.py

from django.urls import path
from .views import UserPredictions


urlpatterns = [
    path('compilePredictions/', UserPredictions.generate_full_report, name='generate_full_report')
]

.

├── Analytics
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-37.pyc
│   │   ├── settings.cpython-37.pyc
│   │   ├── urls.cpython-37.pyc
│   │   └── wsgi.cpython-37.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── authentication
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── biometrics
│   ├── admin.py
│   ├── apps.py
│   ├── bodyfatPrediciton.py
│   ├── Config.py
│   ├── __init__.py
│   ├── models.py
│   ├── templates
│   │   ├── bodyfat.html
│   │   ├── github.html
│   │   └── upload_bodyfat.html
│   ├── tests.py
│   ├── TorsoDimensions.py
│   ├── urls.py
│   └── views.py
├── db.sqlite3
├── dump.rdb
├── extraction
│   ├── admin.py
│   ├── apps.py
│   ├── ExtractionQueryService.py
│   ├── ExtractionServices.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-37.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-37.pyc
│   │   ├── ExtractionQueryService.cpython-37.pyc
│   │   ├── ExtractionServices.cpython-37.pyc
│   │   ├── __init__.cpython-37.pyc
│   │   ├── models.cpython-37.pyc
│   │   ├── urls.cpython-37.pyc
│   │   └── views.cpython-37.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── loginServices
│   ├── admin.py
│   ├── apps.py
│   ├── Authentication.py
│   ├── decorators.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-37.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-37.pyc
│   │   ├── Authentication.cpython-37.pyc
│   │   ├── __init__.cpython-37.pyc
│   │   ├── models.cpython-37.pyc
│   │   ├── urls.cpython-37.pyc
│   │   └── views.cpython-37.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── models.py
├── nutrition
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── 0002_auto_20191007_0323.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-37.pyc
│   │       ├── 0002_auto_20191007_0323.cpython-37.pyc
│   │       └── __init__.cpython-37.pyc
│   ├── models.py
│   ├── PredictFood.py
│   ├── __pycache__
│   │   ├── admin.cpython-37.pyc
│   │   ├── __init__.cpython-37.pyc
│   │   ├── models.cpython-37.pyc
│   │   ├── PredictFood.cpython-37.pyc
│   │   ├── serializers.cpython-37.pyc
│   │   ├── urls.cpython-37.pyc
│   │   └── views.cpython-37.pyc
│   ├── serializers.py
│   ├── TempImages
│   ├── templates
│   │   └── food.html
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── output
**├── predictions**
│   ├── admin.py
│   ├── apps.py
*│   ├── decorators.py*
│   ├── __init__.py
│   ├── migrations
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-37.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-37.pyc
│   │   ├── decorators.cpython-37.pyc
│   │   ├── __init__.cpython-37.pyc
│   │   ├── models.cpython-37.pyc
│   │   ├── urls.cpython-37.pyc
│   │   └── views.cpython-37.pyc
│   ├── tests.py
*│   ├── urls.py*
│   ├── User_Predictions
*│   └── views.py*
├── README.txt
└── TempImages

错误消息

/Development/Backends_HealthApp/mainBackend/ModelBackend/Analytics/predictions/urls.py", line 6, in <module>
    path('compilePredictions/', UserPredictions.generate_full_report, name='generate_full_report')
  File "/home/travjav/.local/lib/python3.7/site-packages/django/urls/conf.py", line 73, in _path
    raise TypeError('view must be a callable or a list/tuple in the case of include().')
TypeError: view must be a callable or a list/tuple in the case of include().

不太确定这里发生了什么 - 我可以毫无问题地使用其他非自定义装饰器

【问题讨论】:

我认为错误一定是由于您的 urls.py。基于类的视图在定义 url 时被引用时使用约定 as_view()。请查看 django 文档:docs.djangoproject.com/en/2.2/topics/class-based-views/… 当您使用 DRF 文档中详细介绍的 ApiView 时,请查看是否正确:django-rest-framework.org/tutorial/3-class-based-views 装饰器不正确。首先,您不会从中返回任何内容(至少,现在是如何编写的),其次,它根本不调用装饰函数 【参考方案1】:

这是装饰器的创建方式。

我更改了函数名称,但您可以看到区别。

from django.core.exceptions import PermissionDenied
import jwt
from functools import wraps
from django.http import HttpResponseRedirect, HttpResponse

def protected_endpoint(function):
    @wraps(function)
    def wrap(request, *args, **kwargs):
        auth = request.headers.get('Authorization').split()[1]
        if auth is None:
            return PermissionDenied
        elif auth is not None:
            try:
                session_token = jwt.decode(auth, '', 'utf-8')
            except jwt.DecodeError:
                return HttpResponse('Invalid Token')
        if session_token:
            return function(request, *args, **kwargs)
        else:
            return HttpResponseRedirect('/')
    return wrap

【讨论】:

以上是关于关于路径和自定义装饰器的 Python3 Django 问题的主要内容,如果未能解决你的问题,请参考以下文章

python3--装饰器

python3 装饰器

python3基础09(装饰器的使用)

python3-多装饰器的执行顺序

Python3.5:装饰器的使用

python3装饰器的简单解释