diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 288e3451ad..ad144cd8db 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -79,7 +79,7 @@ class BaseInvenTreeSetting(models.Model): self.key = str(self.key).upper() self.clean(**kwargs) - self.validate_unique() + self.validate_unique(**kwargs) super().save() @@ -230,10 +230,6 @@ class BaseInvenTreeSetting(models.Model): return choices - @classmethod - def get_filters(cls, key, **kwargs): - return {'key__iexact': key} - @classmethod def get_setting_object(cls, key, **kwargs): """ @@ -247,29 +243,35 @@ class BaseInvenTreeSetting(models.Model): settings = cls.objects.all() + filters = { + 'key__iexact': key, + } + # Filter by user user = kwargs.get('user', None) if user is not None: - settings = settings.filter(user=user) + filters['user'] = user - try: - setting = settings.filter(**cls.get_filters(key, **kwargs)).first() - except (ValueError, cls.DoesNotExist): - setting = None - except (IntegrityError, OperationalError): - setting = None + # Filter by plugin + plugin = kwargs.get('plugin', None) - plugin = kwargs.pop('plugin', None) - - if plugin: + if plugin is not None: from plugin import InvenTreePluginBase if issubclass(plugin.__class__, InvenTreePluginBase): plugin = plugin.plugin_config() + filters['plugin'] = plugin kwargs['plugin'] = plugin + try: + setting = settings.filter(**filters).first() + except (ValueError, cls.DoesNotExist): + setting = None + except (IntegrityError, OperationalError): + setting = None + # Setting does not exist! (Try to create it) if not setting: @@ -287,7 +289,7 @@ class BaseInvenTreeSetting(models.Model): try: # Wrap this statement in "atomic", so it can be rolled back if it fails with transaction.atomic(): - setting.save() + setting.save(**kwargs) except (IntegrityError, OperationalError): # It might be the case that the database isn't created yet pass @@ -342,8 +344,26 @@ class BaseInvenTreeSetting(models.Model): if change_user is not None and not change_user.is_staff: return + filters = { + 'key__iexact': key, + } + + user = kwargs.get('user', None) + plugin = kwargs.get('plugin', None) + + if user is not None: + filters['user'] = user + + if plugin is not None: + from plugin import InvenTreePluginBase + + if issubclass(plugin.__class__, InvenTreePluginBase): + filters['plugin'] = plugin.plugin_config() + else: + filters['plugin'] = plugin + try: - setting = cls.objects.get(**cls.get_filters(key, **kwargs)) + setting = cls.objects.get(**filters) except cls.DoesNotExist: if create: @@ -438,17 +458,37 @@ class BaseInvenTreeSetting(models.Model): validator(self.value) def validate_unique(self, exclude=None, **kwargs): - """ Ensure that the key:value pair is unique. + """ + Ensure that the key:value pair is unique. In addition to the base validators, this ensures that the 'key' is unique, using a case-insensitive comparison. + + Note that sub-classes (UserSetting, PluginSetting) use other filters + to determine if the setting is 'unique' or not """ super().validate_unique(exclude) + filters = { + 'key__iexact': self.key, + } + + user = getattr(self, 'user', None) + plugin = getattr(self, 'plugin', None) + + if user is not None: + filters['user'] = user + + if plugin is not None: + filters['plugin'] = plugin + try: - setting = self.__class__.objects.exclude(id=self.id).filter(**self.get_filters(self.key, **kwargs)) + # Check if a duplicate setting already exists + setting = self.__class__.objects.filter(**filters).exclude(id=self.id) + if setting.exists(): raise ValidationError({'key': _('Key string must be unique')}) + except self.DoesNotExist: pass @@ -1312,16 +1352,9 @@ class InvenTreeUserSetting(BaseInvenTreeSetting): def get_setting_object(cls, key, user): return super().get_setting_object(key, user=user) - def validate_unique(self, exclude=None): + def validate_unique(self, exclude=None, **kwargs): return super().validate_unique(exclude=exclude, user=self.user) - @classmethod - def get_filters(cls, key, **kwargs): - return { - 'key__iexact': key, - 'user__id': kwargs['user'].id - } - def to_native_value(self): """ Return the "pythonic" value, diff --git a/InvenTree/plugin/models.py b/InvenTree/plugin/models.py index e33d452e0a..44eeafd012 100644 --- a/InvenTree/plugin/models.py +++ b/InvenTree/plugin/models.py @@ -175,23 +175,6 @@ class PluginSetting(common.models.BaseInvenTreeSetting): return super().get_setting_definition(key, **kwargs) - @classmethod - def get_filters(cls, key, **kwargs): - """ - Override filters method to ensure settings are filtered by plugin id - """ - - filters = super().get_filters(key, **kwargs) - - plugin = kwargs.get('plugin', None) - - if plugin: - if issubclass(plugin.__class__, InvenTreePluginBase): - plugin = plugin.plugin_config() - filters['plugin'] = plugin - - return filters - plugin = models.ForeignKey( PluginConfig, related_name='settings', diff --git a/InvenTree/templates/js/translated/label.js b/InvenTree/templates/js/translated/label.js index 5215ce9d28..c0f4c2f735 100644 --- a/InvenTree/templates/js/translated/label.js +++ b/InvenTree/templates/js/translated/label.js @@ -263,7 +263,7 @@ function selectLabel(labels, items, options={}) { `; plugins.forEach(function(plugin) { - plugin_selection += ``; + plugin_selection += ``; }); plugin_selection += `