You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Channels项目添加HTTP确认接口无响应问题求助

问题描述

Django新手开发预订网站,前端基于Vue3,后端用Django+Channels实现WebSocket功能。新增邮件确认的HTTP GET/POST接口(路径/api/confirm/confirm_code/)后,后端始终无法接收请求。用Postman及自有站点测试时,前端返回Cannot GET /api/confirm/1234/,后端无任何打印信息或错误提示。相关代码配置如下:

根URL配置(app_name.urls)

from django.contrib import admin
from django.urls import path, include

urlpatterns: list[path] = [
    path('admin/', admin.site.urls),
    path('api/', include('app.routing')),
]

应用路由配置(app.routing)

from django.urls import path

from app.consumers.view import ViewConsumer
from app.consumers.booking import BookingConsumer
from app.consumers.account import AccountConsumer
from app.consumers.profile import ProfileConsumer
from app.http.confirm_reservation import confirm_reservation

websocket_urlpatterns = [
    path(r"ws/view/", ViewConsumer.as_asgi()),
    path(r"ws/booking/", BookingConsumer.as_asgi()),
    path(r"ws/account/", AccountConsumer.as_asgi()),
    path(r"ws/profile/", ProfileConsumer.as_asgi()),
]

urlpatterns = [
    path(r"confirm/<str:confirm_code>/", confirm_reservation, name="confirm_reservation"),
]

视图函数(app.http.confirm_reservation)

from django.http import JsonResponse

from app.services.booking import BookingService


def confirm_reservation(request, confirm_code: str):
    print(request)
    print(confirm_code)
    return JsonResponse(BookingService().confirm_reservation(request))

ASGI配置(app_name.asgi)

from os import environ

from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application

from app.routing import websocket_urlpatterns
from app.cronjobs.cron import Cron
from app.events.event import Event

environ.setdefault("DJANGO_SETTINGS_MODULE", "nail_booking_b.settings")

application: ProtocolTypeRouter = ProtocolTypeRouter(
    {
        "http": get_asgi_application(),
        "websocket": AllowedHostsOriginValidator(
            URLRouter(
                websocket_urlpatterns
            )
        ),
    }
)

Cron.start_process()
Event.start_process()
问题排查方案
  • 验证HTTP路由加载逻辑:

    1. 先测试/admin/是否能正常访问,确认ASGI的HTTP处理模块(get_asgi_application())正常工作。如果/admin/无法访问,说明ASGI应用的HTTP部分配置有误,需检查DJANGO_SETTINGS_MODULE是否正确,或ASGI服务器启动方式是否合规。
    2. 在根URL配置中临时添加测试路由:path('api/test/', lambda r: JsonResponse({'test': 'ok'})),验证/api/前缀下的HTTP路由是否生效。
  • 检查路径匹配准确性:

    1. 移除路由中的r前缀:path函数不依赖正则表达式,无需加r,改为path("confirm/<str:confirm_code>/", ...),避免不必要的转义干扰。
    2. 确保请求路径与路由完全匹配:测试时使用/api/confirm/1234/(带末尾斜杠),若请求不带斜杠,需检查settings.py中APPEND_SLASH是否开启(默认开启)。
  • 启用日志排查:
    在settings.py中配置请求日志,查看404请求详情:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console': {'class': 'logging.StreamHandler'},
        },
        'loggers': {
            'django.request': {
                'handlers': ['console'],
                'level': 'DEBUG',
                'propagate': True,
            },
        },
    }
    

    重启服务后测试,若后端打印404日志,说明请求已到达但路由未匹配;若无日志,需检查反向代理、Nginx等中间层配置。

  • 简化视图排除干扰:
    临时修改视图为最简形式,排除业务逻辑影响:

    def confirm_reservation(request, confirm_code: str):
        print(f"Request received: {request.method}, code: {confirm_code}")
        return JsonResponse({'status': 'success', 'code': confirm_code})
    

    重新测试,若仍无打印,说明路由未匹配;若有打印,问题出在BookingService逻辑中。

代码优化建议
  • 分离HTTP与WebSocket路由:
    将HTTP路由单独放在app/urls.py,WebSocket路由放在app/websocket_routing.py,结构更清晰:

    # app/urls.py
    from django.urls import path
    from app.http.confirm_reservation import confirm_reservation
    
    urlpatterns = [
        path("confirm/<str:confirm_code>/", confirm_reservation, name="confirm_reservation"),
    ]
    
    # app/websocket_routing.py
    from django.urls import path
    from app.consumers.view import ViewConsumer
    from app.consumers.booking import BookingConsumer
    from app.consumers.account import AccountConsumer
    from app.consumers.profile import ProfileConsumer
    
    websocket_urlpatterns = [
        path("ws/view/", ViewConsumer.as_asgi()),
        path("ws/booking/", BookingConsumer.as_asgi()),
        path("ws/account/", AccountConsumer.as_asgi()),
        path("ws/profile/", ProfileConsumer.as_asgi()),
    ]
    

    根URL和ASGI配置相应修改为include('app.urls')和from app.websocket_routing import websocket_urlpatterns。

  • 使用类视图增强扩展性:
    改用Django类视图区分处理GET/POST请求:

    from django.http import JsonResponse
    from django.views import View
    from app.services.booking import BookingService
    
    class ConfirmReservationView(View):
        def get(self, request, confirm_code: str):
            result = BookingService().confirm_reservation(request)
            return JsonResponse(result)
    
        def post(self, request, confirm_code: str):
            result = BookingService().confirm_reservation(request)
            return JsonResponse(result)
    

    路由修改为path("confirm/<str:confirm_code>/", ConfirmReservationView.as_view(), name="confirm_reservation")。

  • 替换print为日志系统:
    使用Django内置logging模块代替print,便于统一管理日志:

    import logging
    from django.http import JsonResponse
    from django.views import View
    
    logger = logging.getLogger(__name__)
    
    class ConfirmReservationView(View):
        def get(self, request, confirm_code: str):
            logger.debug(f"Received GET request for confirm code: {confirm_code}")
            return JsonResponse({'status': 'success'})
    
  • 完善类型注解:
    为视图参数添加明确的类型注解,提升代码可读性:

    from django.http import HttpRequest, JsonResponse
    
    def confirm_reservation(request: HttpRequest, confirm_code: str) -> JsonResponse:
        # 逻辑代码
    
  • 优化ASGI应用初始化:
    将定时任务和事件进程的启动移至Django AppConfig中,避免ASGI文件冗余:

    # app/apps.py
    from django.apps import AppConfig
    from app.cronjobs.cron import Cron
    from app.events.event import Event
    
    class AppConfig(AppConfig):
        default_auto_field = 'django.db.models.BigAutoField'
        name = 'app'
    
        def ready(self):
            import os
            if os.environ.get('RUN_MAIN') == 'true':
                Cron.start_process()
                Event.start_process()
    

    在settings.py中配置INSTALLED_APPS为'app.apps.AppConfig'。

内容的提问来源于stack exchange,提问作者Arkhangel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 16:05:53