89 lines
3.4 KiB
Python
89 lines
3.4 KiB
Python
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"
|
|
# 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)
|
|
|
|
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. |