后端代码:"""
ASGI config for DjangoProject1 project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
"""
# import os
#
# from django.core.asgi import get_asgi_application
#
# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DjangoProject1.settings')
#
# application = get_asgi_application()
# DjangoProject1/asgi.py
# import os
# from django.core.asgi import get_asgi_application
# from channels.routing import ProtocolTypeRouter, URLRouter
#
#
# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DjangoProject1.settings')
# from .routing import application # 直接导入主路由配置
# application = application
# DjangoProject1/asgi.py
# gouw/routing.py
from django.urls import path
from .consumers import OrderConsumer
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
application = ProtocolTypeRouter({
"websocket": AuthMiddlewareStack(
URLRouter([
path('ws/orders/', OrderConsumer.as_asgi()),
])
),
})
# # DjangoProject1/routing.py
# from django.urls import re_path
# from channels.routing import ProtocolTypeRouter, URLRouter
# from gouw.consumers import OrderConsumer # 替换为你的实际消费者
#
# websocket_urlpatterns = [
# re_path(r'ws/some-path/', OrderConsumer.as_asgi()),
# ]
#
# application = ProtocolTypeRouter({
# "websocket": URLRouter(websocket_urlpatterns),
# })
# gouw/routing.py
from django.urls import path
from .consumers import OrderConsumer
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
application = ProtocolTypeRouter({
"websocket": AuthMiddlewareStack(
URLRouter([
path('ws/orders/', OrderConsumer.as_asgi()),
])
),
})
# from django.apps import AppConfig
#
#
# class GouwConfig(AppConfig):
# default_auto_field = 'django.db.models.BigAutoField'
# name = 'gouw'
# gouw/apps.py
from django.apps import AppConfig
class GouwConfig(AppConfig):
name = 'gouw'
def ready(self):
# 确保信号被加载
import gouw.signals # 这行必须执行
print("信号已加载!") # 添加这行用于调试
# consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
import json
from datetime import datetime
import logging
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
logger = logging.getLogger(__name__)
# 常量定义
ORDER_GROUP_NAME = "order_updates" # 统一定义组名
def broadcast_order_update(order_data):
"""广播订单更新到所有客户端"""
try:
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
ORDER_GROUP_NAME,
{
"type": "order.update", # 注意这里使用点号
"data": { # 添加data层保持结构一致
"id": order_data["id"],
"orderNo": order_data["order_no"],
"status": order_data["status"]
}
}
)
logger.info(f"广播成功: {order_data}")
except Exception as e:
logger.error(f"广播失败: {str(e)}")
class OrderConsumer(AsyncWebsocketConsumer):
groups = [ORDER_GROUP_NAME] # 添加这行确保组名一致
async def connect(self):
"""开放连接(带基本验证)"""
try:
await self.accept()
logger.info(f"新客户端连接: {self.channel_name}")
await self.send(text_data=json.dumps({
"type": "system",
"message": "连接成功",
"timestamp": datetime.now().isoformat()
}))
except Exception as e:
logger.error(f"连接处理错误: {str(e)}")
await self.close(code=4001)
async def disconnect(self, close_code):
"""断开连接处理"""
try:
await self.channel_layer.group_discard(
ORDER_GROUP_NAME,
self.channel_name
)
logger.info(f"客户端断开: {close_code}")
except Exception as e:
logger.error(f"断开连接错误: {str(e)}")
async def receive(self, text_data=None, bytes_data=None):
"""消息处理(带错误保护)"""
try:
data = json.loads(text_data)
if data.get("type") == "join_group":
await self.channel_layer.group_add(
data["group"],
self.channel_name
)
await self.send(text_data=json.dumps({
"type": "system",
"message": f"成功加入组: {data['group']}"
}))
return
if not text_data:
logger.warning("收到空消息")
return
data = json.loads(text_data)
logger.debug(f"收到消息: {data}")
# 心跳处理
if data.get("type") == "heartbeat":
await self.send(text_data=json.dumps({
"type": "heartbeat_ack",
"timestamp": datetime.now().isoformat()
}))
return
# 处理其他消息类型
message_type = data.get("type", "unknown")
if message_type == "order_update":
order_id = data.get("id")
order_status = data.get("status")
logger.info(f"收到订单更新: ID={order_id}, 状态={order_status}")
# 可以在这里调用其他逻辑
else:
await self.send(text_data=json.dumps({
"type": "error",
"code": 4002,
"message": f"未知的消息类型: {message_type}"
}))
except json.JSONDecodeError as e:
logger.error(f"消息解析失败: {str(e)}")
await self.send(text_data=json.dumps({
"type": "error",
"code": 4001,
"message": "无效的JSON格式"
}))
except KeyError as e:
logger.error(f"缺少必要字段: {str(e)}")
await self.send(text_data=json.dumps({
"type": "error",
"code": 4003,
"message": f"缺少必要字段: {str(e)}"
}))
except Exception as e:
logger.error(f"消息处理异常: {str(e)}")
await self.send(text_data=json.dumps({
"type": "error",
"code": 5000,
"message": "服务器内部错误"
}))
async def order_update(self, event):
"""处理订单更新广播(修正字段映射)"""
await self.send(text_data=json.dumps({
"type": "order_update",
"data": {
"id": event["data"]["id"],
"orderNo": event["data"]["orderNo"], # 保持驼峰命名
"status": event["data"]["status"]
}
}))
# gouw/routing.py
from django.urls import re_path
from .consumers import OrderConsumer
websocket_urlpatterns = [
re_path(r'ws/orders/$', OrderConsumer.as_asgi()),
]
# signals.py
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from .models import Order
from .consumers import broadcast_order_update
import logging
logger = logging.getLogger(__name__)
@receiver(post_save, sender=Order)
def order_updated(sender, instance, created, **kwargs):
print(f"订单更新信号触发!订单ID: {instance.id}") # 调试日志
try:
# 构建标准化消息数据
order_data = {
"id": instance.id,
"order_no": instance.order_no,
"status": instance.status,
# "statusCode": instance.status,
"createTime": instance.create_time.isoformat(),
"totalAmount": float(instance.total_amount),
# "customerName": instance.customername,
# "customerPhone": instance.customerPhone,
# "products": [
# {
# "name": item.product.name,
# "quantity": item.quantity,
# "price": float(item.price)
# } for item in instance.items.all()
# ]
}
# 强制广播消息
broadcast_order_update(order_data)
print(f"广播订单更新: {instance.id} 状态: {instance.status}")
except Exception as e:
print(f"订单更新信号处理错误: {str(e)}")
@receiver(post_save, sender=Order)
def order_updated(sender, instance, **kwargs):
broadcast_order_update({
"id": instance.id,
"order_no": instance.order_no, # 使用下划线命名
"status": instance.status
})
@receiver(post_save, sender=Order)
def handle_order_update(sender, instance, **kwargs):
try:
broadcast_order_update({
"id": instance.id,
"orderNo": instance.order_no, # 前端使用orderNo字段
"status": instance.status
})
logger.info(f"信号处理完成 - 订单ID: {instance.id} 状态: {instance.status}")
except Exception as e:
logger.error(f"信号处理错误: {str(e)}") 后端报错:C:\Users\马加帅\PycharmProjects\PythonProject2\.venv\Scripts\python.exe D:\ajango后端项目\DjangoProject1\manage.py runserver 8000
信号已加载!
信号已加载!
Performing system checks...
System check identified no issues (0 silenced).
May 17, 2025 - 22:17:44
Django version 4.2, using settings 'DjangoProject1.settings'
Starting ASGI/Channels version 3.0.5 development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Exception in thread django-main-thread:
Traceback (most recent call last):
File "C:\Users\马加帅\PycharmProjects\PythonProject2\.venv\Lib\site-packages\channels\routing.py", line 28, in get_default_application
module = importlib.import_module(path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\马加帅\AppData\Local\Programs\Python\Python312\Lib\importlib\__init__.py", line 90, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 995, in exec_module
File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
File "D:\ajango后端项目\DjangoProject1\DjangoProject1\routing.py", line 17, in <module>
from .consumers import OrderConsumer
ModuleNotFoundError: No module named 'DjangoProject1.consumers'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\马加帅\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1073, in _bootstrap_inner
self.run()
File "C:\Users\马加帅\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 1010, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\马加帅\PycharmProjects\PythonProject2\.venv\Lib\site-packages\django\utils\autoreload.py", line 64, in wrapper
fn(*args, **kwargs)
File "C:\Users\马加帅\PycharmProjects\PythonProject2\.venv\Lib\site-packages\channels\management\commands\runserver.py", line 107, in inner_run
application=self.get_application(options),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\马加帅\PycharmProjects\PythonProject2\.venv\Lib\site-packages\channels\management\commands\runserver.py", line 132, in get_application
return StaticFilesWrapper(get_default_application())
^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\马加帅\PycharmProjects\PythonProject2\.venv\Lib\site-packages\channels\routing.py", line 30, in get_default_application
raise ImproperlyConfigured("Cannot import ASGI_APPLICATION module %r" % path)
django.core.exceptions.ImproperlyConfigured: Cannot import ASGI_APPLICATION module 'DjangoProject1.routing'