# -*- coding: utf-8 -*- # from operator import add, sub from django.conf import settings from django.db.models.signals import m2m_changed from django.dispatch import receiver from assets.models import Asset, Node from common.const.signals import PRE_CLEAR, POST_ADD, PRE_REMOVE from common.decorators import on_transaction_commit, merge_delay_run from common.signals import django_ready from common.utils import get_logger from orgs.utils import tmp_to_org, tmp_to_root_org from ..tasks import check_node_assets_amount_task logger = get_logger(__file__) @receiver(m2m_changed, sender=Asset.nodes.through) @on_transaction_commit def on_node_asset_change(sender, action, instance, reverse, pk_set, **kwargs): # 不允许 `pre_clear` ,因为该信号没有 `pk_set` # [官网](https://docs.djangoproject.com/en/3.1/ref/signals/#m2m-changed) refused = (PRE_CLEAR,) if action in refused: raise ValueError # 这里监听 post_add, pre_remove, 如果pre_add 和 post_remove, 那么 node_ids 就已经获取不到了 mapper = {POST_ADD: add, PRE_REMOVE: sub} if action not in mapper: return with tmp_to_org(instance.org): if reverse: node_ids = [instance.id] else: node_ids = list(pk_set) update_nodes_assets_amount.delay(node_ids=node_ids) @merge_delay_run(ttl=30) def update_nodes_assets_amount(node_ids=()): nodes = Node.objects.filter(id__in=node_ids) nodes = Node.get_ancestor_queryset(nodes) logger.debug('Recv asset nodes change signal, recompute node assets amount') logger.info('Update nodes assets amount: {} nodes'.format(len(node_ids))) if len(node_ids) > 100: check_node_assets_amount_task.delay() return for node in nodes: node.assets_amount = node.get_assets_amount() Node.objects.bulk_update(nodes, ['assets_amount']) @receiver(django_ready) def set_assets_size_to_setting(sender, **kwargs): from assets.models import Asset try: with tmp_to_root_org(): amount = Asset.objects.order_by().count() except: amount = 0 if amount > 20000: settings.ASSET_SIZE = 'large' elif amount > 5000: settings.ASSET_SIZE = 'medium'