From 63b5b956105df731889b51ba1c6d3e00afb865c6 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 25 Mar 2022 13:43:19 +1100 Subject: [PATCH 1/4] Ensure that kwargs are correctly passed through the settings chain Problem: validate_unique fails - Otherwise, the object is not correctly passed - Then, validate_unique fails --- InvenTree/common/models.py | 46 ++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 288e3451ad..7a938735fc 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() @@ -253,13 +253,6 @@ class BaseInvenTreeSetting(models.Model): if user is not None: settings = settings.filter(user=user) - try: - setting = settings.filter(**cls.get_filters(key, **kwargs)).first() - except (ValueError, cls.DoesNotExist): - setting = None - except (IntegrityError, OperationalError): - setting = None - plugin = kwargs.pop('plugin', None) if plugin: @@ -270,6 +263,15 @@ class BaseInvenTreeSetting(models.Model): kwargs['plugin'] = plugin + settings = settings.filter(plugin=plugin) + + try: + setting = settings.filter(**cls.get_filters(key, **kwargs)).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 @@ -438,17 +440,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': 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,7 +1334,7 @@ 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 From 5ee9af7f0ebed1cb56ea488299824daf0db0afb8 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 25 Mar 2022 14:10:05 +1100 Subject: [PATCH 2/4] Remove old "get_filters" function - It was confusing! - Manually filter where required --- InvenTree/common/models.py | 49 +++++++++++++++++++++++--------------- InvenTree/plugin/models.py | 17 ------------- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index 7a938735fc..c72e9f5adb 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -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,26 +243,30 @@ 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 - plugin = kwargs.pop('plugin', None) + # Filter by plugin + plugin = kwargs.get('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 - settings = settings.filter(plugin=plugin) - try: - setting = settings.filter(**cls.get_filters(key, **kwargs)).first() + setting = settings.filter(**filters).first() except (ValueError, cls.DoesNotExist): setting = None except (IntegrityError, OperationalError): @@ -344,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: @@ -452,7 +470,7 @@ class BaseInvenTreeSetting(models.Model): super().validate_unique(exclude) filters = { - 'key': self.key, + 'key__iexact': self.key, } user = getattr(self, 'user', None) @@ -1337,13 +1355,6 @@ class InvenTreeUserSetting(BaseInvenTreeSetting): 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', From bc48a9584407a238886cddc8e23013cf84191fa0 Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 25 Mar 2022 14:13:02 +1100 Subject: [PATCH 3/4] PEP fixes --- InvenTree/common/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index c72e9f5adb..ad144cd8db 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -353,7 +353,7 @@ class BaseInvenTreeSetting(models.Model): if user is not None: filters['user'] = user - + if plugin is not None: from plugin import InvenTreePluginBase @@ -462,7 +462,7 @@ class BaseInvenTreeSetting(models.Model): 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 """ From 011d97db3da22d1ba222749683c419613214df2a Mon Sep 17 00:00:00 2001 From: Oliver Date: Fri, 25 Mar 2022 14:20:25 +1100 Subject: [PATCH 4/4] Tweak display of label printing plugins --- InvenTree/templates/js/translated/label.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 += `