minor improvements + crash fix

sync_v2
Laurent 6 months ago
parent 1d8fb1b32a
commit e4beca4840
  1. 3
      sync/models/base.py
  2. 1
      sync/models/data_access.py
  3. 57
      sync/signals.py
  4. 7
      sync/utils.py
  5. 15
      sync/views.py

@ -51,7 +51,10 @@ class BaseModel(models.Model):
self.data_access_ids.append(str_id)
def remove_data_access_relation(self, data_access):
try:
self.data_access_ids.remove(str(data_access.id))
except ValueError:
pass
def get_children_by_model(self):
"""

@ -79,6 +79,7 @@ class DataAccess(BaseModel):
try:
obj = model_class.objects.get(id=self.model_id)
related_instance = obj.related_instances()
related_instance.append(obj)
for instance in related_instance:
if isinstance(instance, BaseModel):
instance.remove_data_access_relation(self)

@ -17,28 +17,23 @@ User = get_user_model()
@receiver([pre_save, pre_delete])
def presave_handler(sender, instance, **kwargs):
synchronization_prepare(sender, instance, **kwargs)
def synchronization_prepare(sender, instance, **kwargs):
# some other classes are excluded in settings_app.py: SYNC_APPS
if not isinstance(instance, (BaseModel, User)):
return
# print(f'*** synchronization_prepare for instance: {instance}')
signal = kwargs.get('signal')
# avoid crash in manage.py createsuperuser + delete user in the admin
if isinstance(instance, User) and (instance._state.db is None or signal == pre_delete):
return
# some other classes are excluded in settings_app.py: SYNC_APPS
if not isinstance(instance, BaseModel) and not isinstance(instance, User):
return
users = related_users(instance)
# print(f'* impacted users = {users}')
related_users_registry.register(instance.id, users)
# user_ids = [user.id for user in users]
if signal == pre_save:
detect_foreign_key_changes(sender, instance)
detect_foreign_key_changes_for_shared_instances(sender, instance)
@receiver([post_save, post_delete])
def synchronization_notifications(sender, instance, created=False, **kwargs):
@ -123,19 +118,35 @@ def save_model_log(users, model_operation, model_name, model_id, store_id):
# print(f'>> creating Model Log for: {model_operation} {model_name}')
logs_to_create = [
ModelLog(
user=user,
operation=model_operation,
model_name=model_name,
model_id=model_id,
store_id=store_id,
device_id=device_id
)
for user in users
# if user.should_synchronize
]
with transaction.atomic():
for user in users:
# print(f' * {user.username}')
# if user.should_synchronize:
model_log = ModelLog()
model_log.user = user
model_log.operation = model_operation
model_log.model_name = model_name
model_log.model_id = model_id
model_log.store_id = store_id
model_log.device_id = device_id
model_log.save()
ModelLog.objects.bulk_create(logs_to_create)
# with transaction.atomic():
# for user in users:
# # print(f' * {user.username}')
# # if user.should_synchronize:
# model_log = ModelLog()
# model_log.user = user
# model_log.operation = model_operation
# model_log.model_name = model_name
# model_log.model_id = model_id
# model_log.store_id = store_id
# model_log.device_id = device_id
# model_log.save()
# print(f'ML users = {len(users)}')
# existing_log = ModelLog.objects.filter(users__in=users, model_id=model_id, operation=model_operation).first()
@ -157,7 +168,7 @@ def save_model_log(users, model_operation, model_name, model_id, store_id):
# model_log.save()
# model_log.users.set(users)
def detect_foreign_key_changes(sender, instance):
def detect_foreign_key_changes_for_shared_instances(sender, instance):
if not hasattr(instance, 'pk') or not instance.pk:
return
if not isinstance(instance, BaseModel):
@ -296,7 +307,7 @@ def related_users(instance):
# look in related DataAccess
# data_access_list = instances_related_data_access(instance, related_instances)
print(f'instance = {instance.__class__.__name__}, data access count = {len(data_access_list)}')
# print(f'instance = {instance.__class__.__name__}, data access count = {len(data_access_list)}')
for data_access in data_access_list:
users.add(data_access.related_user)
users.update(data_access.shared_with.all())

@ -31,16 +31,13 @@ def get_serializer(instance, model_name):
def get_data(model_name, model_id):
model = model_registry.get_model(model_name)
# print(f'model_name = {model_name}')
# model = apps.get_model(app_label=app_label, model_name=model_name)
return model.objects.get(id=model_id)
def get_serialized_data(model_name, model_id):
def get_serialized_data_by_id(model_name, model_id):
# print(f'model_name = {model_name}')
model = model_registry.get_model(model_name)
instance = model.objects.get(id=model_id)
serializer_class = build_serializer_class(model_name)
serializer = serializer_class(instance)
serializer = get_serializer(instance, model_name)
return serializer.data
class HierarchyOrganizer:

@ -17,7 +17,7 @@ from collections import defaultdict
from urllib.parse import unquote
from .serializers import DataAccessSerializer
from .utils import get_serializer, build_serializer_class, get_data, get_serialized_data, HierarchyOrganizer
from .utils import get_serializer, build_serializer_class, get_data, get_serialized_data_by_id, HierarchyOrganizer
from .models import ModelLog, BaseModel, SideStoreModel, DataAccess
@ -212,13 +212,11 @@ class SynchronizationApi(APIView):
def get(self, request, *args, **kwargs):
last_update_str = request.query_params.get('last_update')
device_id = request.query_params.get('device_id')
decoded_last_update = unquote(last_update_str) # Decodes %2B into +
if not decoded_last_update:
if not last_update_str:
return Response({"error": "last_update parameter is required"}, status=status.HTTP_400_BAD_REQUEST)
try:
decoded_last_update = unquote(last_update_str) # Decodes %2B into +
last_update = timezone.datetime.fromisoformat(decoded_last_update)
except ValueError:
return Response({"error": f"Invalid date format for last_update: {decoded_last_update}"},
@ -226,6 +224,7 @@ class SynchronizationApi(APIView):
print(f'>>> GET last modifications since: {last_update_str} / converted = {last_update}')
device_id = request.query_params.get('device_id')
logs = self.query_model_logs(last_update, request.user, device_id)
print(f'>>> user = {request.user.username} > log count = {logs.count()}, device_id = {device_id}')
@ -262,7 +261,7 @@ class LogProcessingResult:
self.last_log_date = log.date
try:
if log.operation in ['POST', 'PUT']:
data = get_serialized_data(log.model_name, log.model_id)
data = get_serialized_data_by_id(log.model_name, log.model_id)
self.updates[log.model_name][log.model_id] = data
elif log.operation == 'DELETE':
self.deletions[log.model_name].append(log.data_identifier_dict())
@ -292,7 +291,7 @@ class LogProcessingResult:
# elif log.operation == 'RELATIONSHIP_REMOVED':
# self.relationship_removals[log.model_name].append(log.data_identifier_dict())
elif log.operation == 'SHARED_RELATIONSHIP_SET':
data = get_serialized_data(log.model_name, log.model_id)
data = get_serialized_data_by_id(log.model_name, log.model_id)
self.shared_relationship_sets[log.model_name][log.model_id] = data
elif log.operation == 'SHARED_RELATIONSHIP_REMOVED':
self.shared_relationship_removals[log.model_name].append(log.data_identifier_dict())

Loading…
Cancel
Save