from django.core.management.base import BaseCommand, CommandParser from django.contrib.auth import get_user_model from parts.models import Component, ComponentParameter, ComponentParameterType, PackageParameter, Package class Command(BaseCommand): help = "Remove component parameters, that are also set on the package with the same value" def add_arguments(self, parser: CommandParser): parser.add_argument('--dry-run', help='Do not perform parameter deletion. Print only', action='store_true') def handle(self, *args, **options): # Get all components with set packages. Ignore the ones without packages all_comps = Component.objects.exclude(package__isnull=True) for component in all_comps: package_parameters = PackageParameter.objects.filter(package=component.package) component_parameters = ComponentParameter.objects.filter(component=component) package_param_ids = package_parameters.values_list('parameter_type_id', flat=True) component_param_ids = component_parameters.values_list('parameter_type_id', flat=True) # Skip trivial cases if len(package_param_ids) == 0 or len(component_param_ids) == 0: continue self.stdout.write(f'Comp: {str(component)} Found {len(component_param_ids)} different parameters') self.stdout.write(f'\tPackage: {str(component.package)} Found {len(package_param_ids)} different parameters') commontypes = ctypes = ComponentParameterType.objects.filter(id__in=component_param_ids).filter(id__in=package_param_ids) self.stdout.write(f'\tCommon parameter count: {len(commontypes)}') # Check if values are the same when rendered as a string. This avoids float comparison problems for common_type in commontypes: s1 = package_parameters.filter(parameter_type=common_type).first().resolved_value_as_string() comp_param = component_parameters.filter(parameter_type=common_type).first() s2 = comp_param.resolved_value_as_string() if s1 == s2: self.stdout.write(f'\tParameter {common_type.parameter_name} is the same value for component and package: {s1}. Removing from component') if not options['dry_run']: comp_param.delete() else: self.stderr.write(f'\tParameter {common_type.parameter_name} is set on component {str(component)} and its package with different values: "{s1}" vs "{s2}"')