1

我正在使用Djoser创建身份验证后端。我希望发生以下情况:

  1. 用户http://localhost:8000/auth/users/使用电子邮件、用户名、密码和 re_password 注册
  2. 用户在输入的电子邮件中收到一封激活电子邮件,其中包含用于激活其帐户的 URL。URL 的格式为:(<web url>/activate/{uid}/token例如http://localhost:8000/activate/Mg/apur8c-6100390a061c5ff081235193867f943a:)
  3. 单击该 URL 会向服务器发送一个 GET 请求,其中视图 ( UserActivationView) 接收提取的 uid 和令牌并将其自己的请求发送到<web url>/users/activation/{uid}/token( http://localhost:8000/users/activation/Mg/apur8c-6100390a061c5ff081235193867f943a)。并返回它从该请求中获得的响应作为响应。
  4. 用户帐户被激活。

这是执行上述所有操作的代码:

# Djoser configuration in settings.py
DJOSER = {
    'LOGIN_FIELD': 'email',

    'PASSWORD_RESET_CONFIRM_URL': 'password-reset/{uid}/{token}',
    'USERNAME_RESET_CONFIRM_URL': 'username-reset/{uid}/{token}',

    'SEND_ACTIVATION_EMAIL': True,
    'ACTIVATION_URL': 'activate/{uid}/{token}',

    'SEND_CONFIRMATION_EMAIL': True,
    'PASSWORD_CHANGE_EMAIL_CONFIRMATION': True,
    'USERNAME_CHANGED_EMAIL_CONFIRMATION': True,

    'USER_CREATE_PASSWORD_RETYPE': True,
    'SET_PASSWORD_RETYPE': True,
}
# views.py in user app (users/views.py)
from rest_framework.views import APIView
from rest_framework.response import Response
import requests


class UserActivationView(APIView):
    def get(self, request, uid, token):
        protocol = "https://" if request.is_secure() else "http://"
        web_url = protocol + request.get_host()
        post_url = web_url + '/auth/users/activation/'
        post_data = {'uid': uid, "token": token}
        print(f"Sending request to {post_url} with {post_data}")
        result = requests.post(post_url, data=post_data)     # <<-- causes the server to hang
        return Response(result.text)
# users/urls.py
from django.urls import path, include
from .views import UserActivationView

app_name = "users"

urlpatterns = [
    path('auth/', include('djoser.urls')),
    path('auth/', include('djoser.urls.jwt')),
    path('activate/<str:uid>/<str:token>/',
         UserActivationView.as_view())
]
# MAIN project urls.py
from django.contrib import admin
from django.urls import include, path


urlpatterns = [
    path('admin/', admin.site.urls),
    path('chat/', include('frontend.urls')),
    path("chat/", include('backend.urls')),
    path('api/accounts/', include('backend.urls')),
    path('', include('users.urls'))

]

现在,问题出现在第 3 步(result = requests.post(post_url, data=post_data)在线)。当视图试图发送一个 post 请求时,服务器会挂起相当长的一段时间。CTRL在此期间,当我执行+时它甚至不会停止C。这是我得到的输出(我添加了评论):

HTTP POST /auth/users/ 201 [5.87, 127.0.0.1:56239] ## User registration was successful and email was sent
HTTP GET /activate/Mg/apuvq9-3461158f807a1e054738458bc2372486 301 [0.00, 127.0.0.1:56245] # 301 response while trying to GET the URL sent in the email
Sending request to http://localhost:8000/auth/users/activation/ with {'uid': 'Mg', 'token': 'apuvq9-3461158f807a1e054738458bc2372486'} # My print statement
# A long pause here. Server hangs and then this error appears:
Application instance <Task pending coro=<StaticFilesWrapper.__call__() running at D:\pigeon\venv\lib\site-packages\channels\staticfiles.py:44> wait_for=<Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\ProgramData\Anaconda3\lib\asyncio\futures.py:348, <TaskWakeupMethWrapper object at 0x000001E3EDE96858>()]>> for connection <WebRequest at 0x1e3edd8a788 method=GET uri=/activate/Mg/apuvq9-3461158f807a1e054738458bc2372486/ clientproto=HTTP/1.1> took too long to shut down and was killed.
Application instance <Task pending coro=<StaticFilesWrapper.__call__() running at D:\pigeon\venv\lib\site-packages\channels\staticfiles.py:44> wait_for=<Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\ProgramData\Anaconda3\lib\asyncio\futures.py:348, <TaskWakeupMethWrapper object at 0x000001E3EE1067C8>()]>> for connection <WebRequest at 0x1e3edd8a788 method=GET uri=/activate/Mg/apuvq9-3461158f807a1e054738458bc2372486/ clientproto=HTTP/1.1> took too long to shut down and was killed.
Internal Server Error: /activate/Mg/apuvq9-3461158f807a1e054738458bc2372486/
Traceback (most recent call last):
  File "D:\pigeon\venv\lib\site-packages\asgiref\sync.py", line 482, in thread_handler
    raise exc_info[1]
  File "D:\pigeon\venv\lib\site-packages\django\core\handlers\exception.py", line 38, in inner
    response = await get_response(request)
  File "D:\pigeon\venv\lib\site-packages\django\core\handlers\base.py", line 238, in _get_response_async
    )(e, request)
  File "D:\pigeon\venv\lib\site-packages\asgiref\sync.py", line 444, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "C:\ProgramData\Anaconda3\lib\asyncio\tasks.py", line 414, in wait_for
    return await fut
concurrent.futures._base.CancelledError

或者,如果我通过 Postman 或单独的 Python 脚本手动发送激活请求,则该请求可以正常工作并且用户被激活:

在此处输入图像描述 在此处输入图像描述

该问题似乎仅在从视图中向服务器发出请求时出现。我也尝试过result = requests.get('http://localhost:8000/chat')作为实验,它也导致服务器挂起,而result = requests.get('http://google.com')不会导致此类问题。

该视图的代码取自此处,答案下方的人也评论道

这会挂起我的调试 django 服务器 – Hack_Hut Apr 25 at 11:55

我该如何解决这个问题?

我在用:

  • 蟒蛇:3.7.5
  • 姜戈:3.2.5
  • 左塞尔:2.1.0
  • Django 休息框架:3.12.4
  • 请求:2.26.0
4

0 回答 0