This commit is contained in:
anhduy-tech
2026-01-07 10:59:02 +07:00
parent b161619413
commit a1517794fd
5 changed files with 75 additions and 66 deletions

View File

@@ -54,77 +54,86 @@ class DataConsumer(AsyncJsonWebsocketConsumer):
self.subscribed_groups.add(group_name) self.subscribed_groups.add(group_name)
async def realtime_update(self, event): async def realtime_update(self, event):
# Move imports inside the method to prevent AppRegistryNotReady error on startup # Bước gỡ lỗi cuối cùng: xác nhận phương thức này được gọi và bắt bất kỳ lỗi nào
from django.db.models import Q print(f"--- CONSUMER: realtime_update invoked for event name: {event['payload']['name']} ---")
from .views import get_serializer try:
# Move imports inside the method to prevent AppRegistryNotReady error on startup
from django.db.models import Q
from .views import get_serializer
payload = event["payload"] payload = event["payload"]
change_type = payload.get("change_type") change_type = payload.get("change_type")
record_id = payload["record"].get("id") record_id = payload["record"].get("id")
if not record_id or not change_type: if not record_id or not change_type:
return return
model_name_lower = payload["name"] model_name_lower = payload["name"]
model_name_capitalized = model_name_lower.capitalize() # Chuyển đổi snake_case (từ signal) thành PascalCase với dấu gạch dưới (được sử dụng trong subscription)
# Ví dụ: 'product_note' -> 'Product_Note'
model_name_pascal_case = '_'.join(word.capitalize() for word in model_name_lower.split('_'))
# 1. Get this client's subscription parameters for the specific model # 1. Lấy các tham số đăng ký của client này cho model cụ thể
client_params = self.subscription_params.get(model_name_capitalized) client_params = self.subscription_params.get(model_name_pascal_case)
if not client_params: if not client_params:
return # This client is not subscribed to this model. return # Client này không đăng ký model này.
# 2. Handle DELETION event # 2. Xử lý sự kiện DELETION
if change_type == 'deleted': if change_type == 'deleted':
await self.send_json({
"type": "realtime_update",
"payload": {
"name": model_name_lower,
"change_type": "deleted",
"record": {"id": record_id}
}
})
return
# 3. Handle CREATION and UPDATE events
Model, _ = get_serializer(model_name_lower)
if not Model:
return
# Build a Q object from the client's filter dictionary
filter_q = Q()
filter_dict = client_params.get('filter')
if isinstance(filter_dict, dict):
filter_q = Q(**filter_dict)
# Check if the object actually exists with the combined filter
record_exists = await database_sync_to_async(
Model.objects.filter(Q(pk=record_id) & filter_q).exists
)()
if record_exists:
# If record matches filter, re-run the query to get the correctly shaped data
single_record_params = client_params.copy()
single_record_params['filter'] = {'pk': record_id}
data = await database_sync_to_async(execute_data_query)(model_name_capitalized, single_record_params)
if data and data.get('rows'):
payload_for_client = {
"name": model_name_lower,
"change_type": change_type,
"record": data['rows'][0]
}
await self.send_json({ await self.send_json({
"type": "realtime_update", "type": "realtime_update",
"payload": payload_for_client "payload": {
"name": model_name_lower,
"change_type": "deleted",
"record": {"id": record_id}
}
}) })
else: return
# If the record exists but no longer matches the filter, treat as a deletion for this client
await self.send_json({ # 3. Xử lý sự kiện CREATION và UPDATE
"type": "realtime_update", Model, _ = get_serializer(model_name_lower)
"payload": { if not Model:
"name": model_name_lower, return
"change_type": "deleted",
"record": {"id": record_id} # Xây dựng một đối tượng Q từ từ điển bộ lọc của client
} filter_q = Q()
}) filter_dict = client_params.get('filter')
if isinstance(filter_dict, dict):
filter_q = Q(**filter_dict)
# Kiểm tra xem đối tượng có thực sự tồn tại với bộ lọc kết hợp không
record_exists = await database_sync_to_async(
Model.objects.filter(Q(pk=record_id) & filter_q).exists
)()
if record_exists:
# Nếu bản ghi khớp với bộ lọc, chạy lại truy vấn để lấy dữ liệu có định dạng đúng
single_record_params = client_params.copy()
single_record_params['filter'] = {'pk': record_id}
data = await database_sync_to_async(execute_data_query)(model_name_pascal_case, single_record_params)
if data and data.get('rows'):
payload_for_client = {
"name": model_name_lower,
"change_type": change_type,
"record": data['rows'][0]
}
await self.send_json({
"type": "realtime_update",
"payload": payload_for_client
})
else:
# Nếu bản ghi tồn tại nhưng không còn khớp với bộ lọc, coi như là một thao tác xóa đối với client này
await self.send_json({
"type": "realtime_update",
"payload": {
"name": model_name_lower,
"change_type": "deleted",
"record": {"id": record_id}
}
})
except Exception as e:
import traceback
print(f"!!!!!!!!!! EXCEPTION in realtime_update: {e} !!!!!!!!!!!")
traceback.print_exc()