from django.db.models.signals import post_save, post_delete from django.dispatch import receiver from django.apps import apps from channels.layers import get_channel_layer from asgiref.sync import async_to_sync from django.db import transaction # Import hàm get_serializer đã có from .views import get_serializer # Danh sách các model không muốn theo dõi để tránh "nhiễu" # Ví dụ: các model của admin, session, hoặc các model log không cần real-time MODELS_TO_IGNORE = ['LogEntry', 'Session', 'ContentType', 'AdminLog', 'Permission', 'Group', 'Token', 'Phone_Otp'] def send_model_update(instance, change_type): """ Hàm chung để gửi cập nhật model qua WebSocket. """ model_class = instance.__class__ model_name = model_class._meta.model_name # Bỏ qua các model trong danh sách ignore if model_class.__name__ in MODELS_TO_IGNORE: return # Lấy serializer một cách linh động _model, serializer_class = get_serializer(model_name) if not serializer_class: print(f"Warning: No serializer found for model {model_name}. Cannot send update.") return # Serialize instance đã thay đổi # Đối với 'delete', instance vẫn còn tồn tại trong bộ nhớ tại thời điểm này serializer = serializer_class(instance) # Chuẩn bị payload để gửi đi payload = { "name": model_name, "change_type": change_type, "record": serializer.data } # Gửi tin nhắn đến group tương ứng channel_layer = get_channel_layer() group_name = f"model_{model_name}_updates" async_to_sync(channel_layer.group_send)( group_name, { "type": "realtime.update", # Khớp với tên phương thức trong DataConsumer "payload": payload } ) def generic_post_save_handler(sender, instance, created, **kwargs): """ Hàm xử lý chung cho tín hiệu post_save từ BẤT KỲ model nào. """ def send_update_after_commit(): change_type = "created" if created else "updated" try: # Re-fetch the instance to ensure we have the committed data refreshed_instance = sender.objects.get(pk=instance.pk) send_model_update(refreshed_instance, change_type) except sender.DoesNotExist: # Object đã bị xóa (ví dụ: delete_entry vừa xóa Internal_Entry) # Bỏ qua việc gửi update, hoặc gửi thông báo "deleted" nếu cần print(f"Object {sender.__name__} {instance.pk} đã bị xóa, bỏ qua gửi update.") # Optional: vẫn gửi "deleted" để frontend biết object không còn send_model_update(instance, "deleted") except Exception as exc: print(f"Lỗi trong send_update_after_commit: {exc}") transaction.on_commit(send_update_after_commit) def generic_post_delete_handler(sender, instance, **kwargs): """ Hàm xử lý chung cho tín hiệu post_delete từ BẤT KỲ model nào. """ # For delete, the action happens immediately, so on_commit is not strictly necessary # unless the delete is part of a larger transaction that could be rolled back. # It's safer to use it anyway. def send_delete_after_commit(): send_model_update(instance, "deleted") transaction.on_commit(send_delete_after_commit) def connect_signals(): """ Kết nối các hàm xử lý chung với tín hiệu post_save và post_delete. Không chỉ định `sender` để lắng nghe tất cả các model. """ post_save.connect(generic_post_save_handler, dispatch_uid="generic_post_save") post_delete.connect(generic_post_delete_handler, dispatch_uid="generic_post_delete") print("Connected generic signals for real-time updates.") # File apps.py của bạn đã gọi hàm connect_signals() này rồi, nên mọi thứ sẽ tự động hoạt động.