object.delete()
and the object was deleted with all dependencies. But over time, we had to abandon this approach, since one object could have dependencies with millions of other objects, and the cascading deletion tightly blocked the tables. And since the service performs thousands of checks every second and logs them, locking the tables led to a serious slowdown in the service, which was unacceptable for us. from django.contrib.admin.util import NestedObjects from django.db import DEFAULT_DB_ALIAS collector = NestedObjects(using=DEFAULT_DB_ALIAS) collector.collect([obj]) objects_to_delete = collector.nested() # Recursive delete objects
def exclude_objects_for_deleted_hosts(*fields): """ Decorator that adds .exclude({field__}is_deleted=True) for model_class.objects.get_queryset :param fields: fields for exclude condition """ def wrapper(model_class): def apply_filters(qs): for field in filter_fields: qs = qs.exclude(**{ '{}is_deleted'.format('{}__'.format(field) if field else ''): True, }) return qs model_class.all_objects = copy.deepcopy(model_class.objects) filter_fields = set(fields) get_queryset = model_class.objects.get_queryset model_class.objects.get_queryset = lambda: apply_filters(get_queryset()) # save info about model decorator setattr(model_class, DECORATOR_DEL_HOST_ATTRIBUTE, filter_fields) return model_class return wrapper
exclude_objects_for_deleted_hosts(fields)
decorator for the specified fields of the fields model automatically adds an exclude
filter for each request, which just removes the records that should not be displayed in the interface. @exclude_objects_for_deleted_hosts('host') class Alias(models.Model): host = models.ForeignKey(to=Host, verbose_name='Host', related_name='alias')
Host
object, it is enough to change the is_deleted
attribute: host.is_deleted = True # after this save the host and all related objects will be inaccessible host.save()
# model decorator @exclude_objects_for_deleted_hosts('checker__monhost', 'alias__host') CheckerToAlias.objects.filter( alias__hostname__in=['cloud.spb.s', 'cloud.msk.s'] ).values('id')
SELECT monitoring_checkertoalias.id FROM monitoring_checkertoalias INNER JOIN monitoring_checker ON (`monitoring_checkertoalias`.`checker_id` = monitoring_checker.`id`) INNER JOIN Hosts ON (`monitoring_checker`.`monhost_id` = Hosts.`id`) INNER JOIN dcmap_alias ON (`monitoring_checkertoalias`.`alias_id` = dcmap_alias.`id`) INNER JOIN Hosts T5 ON (`dcmap_alias`.`host_id` = T5.`id`) WHERE ( NOT (`Hosts`.`is_deleted` = TRUE) -- раз, проверка для monitoring_checker AND NOT (T5.`is_deleted` = TRUE) -- два, проверка для dcmap_alias AND dcmap_alias.name IN ('dir1.server.p', 'dir2.server.p') );
`is_deleted` = TRUE
. host.hostname = '{}_{}'.format(host.hostname, uuid.uuid4()) host.is_deleted = True host.save()
def test_deleted_host_decorator_for_models(self): def recursive_host_finder(model, cache, path, filters): # cache for skipping looked models cache.add(model) # process all related models for field in (f for f in model._meta.fields if isinstance(f, ForeignKey)): if field.related_model == Host: filters.add(path + field.name) elif field.related_model not in cache: recursive_host_finder(field.related_model, cache.copy(), path + field.name + '__', filters) # check all models for current_model in apps.get_models(): model_filters = getattr(current_model, DECORATOR_DEL_HOST_ATTRIBUTE, set()) found_filters = set() if current_model == Host: found_filters.add('') else: recursive_host_finder(current_model, set(), '', found_filters) if found_filters or model_filters: try: self.assertSetEqual(model_filters, found_filters) except AssertionError as err: err.args = ( '{}\n !!! Fix decorator "exclude_objects_for_deleted_hosts" ' 'for model {}'.format(err.args[0], current_model), ) raise err
exclude
filter. The imposition of additional conditions slows down the process of obtaining data, the degree of "complication" depends on the database structure, the number of records and the presence of indices. The proposed test will tell you which models need to add decorators, and in the future will monitor their consistency.Source: https://habr.com/ru/post/438280/