mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-29 03:56:43 +00:00
Simplify the various settings objects, to improve retrieval of 'parameters' from the base class
- Remove the GenericReferencedSettingsClass mixin - Each subclass defines a very simple get_kwargs() method - Now, at object level *and* class level we can perform lookup of settings and actually get proper data back - Adds "model" option to setting (precursor of things to come)
This commit is contained in:
parent
56f36d4b4b
commit
e112d555d4
@ -136,6 +136,19 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
return settings
|
return settings
|
||||||
|
|
||||||
|
def get_kwargs(self):
|
||||||
|
"""
|
||||||
|
Construct kwargs for doing class-based settings lookup,
|
||||||
|
depending on *which* class we are.
|
||||||
|
|
||||||
|
This is necessary to abtract the settings object
|
||||||
|
from the implementing class (e.g plugins)
|
||||||
|
|
||||||
|
Subclasses should override this function to ensure the kwargs are correctly set.
|
||||||
|
"""
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_setting_definition(cls, key, **kwargs):
|
def get_setting_definition(cls, key, **kwargs):
|
||||||
"""
|
"""
|
||||||
@ -319,11 +332,11 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
value = setting.value
|
value = setting.value
|
||||||
|
|
||||||
# Cast to boolean if necessary
|
# Cast to boolean if necessary
|
||||||
if setting.is_bool(**kwargs):
|
if setting.is_bool():
|
||||||
value = InvenTree.helpers.str2bool(value)
|
value = InvenTree.helpers.str2bool(value)
|
||||||
|
|
||||||
# Cast to integer if necessary
|
# Cast to integer if necessary
|
||||||
if setting.is_int(**kwargs):
|
if setting.is_int():
|
||||||
try:
|
try:
|
||||||
value = int(value)
|
value = int(value)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
@ -390,19 +403,19 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.__class__.get_setting_name(self.key)
|
return self.__class__.get_setting_name(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def default_value(self):
|
def default_value(self):
|
||||||
return self.__class__.get_setting_default(self.key)
|
return self.__class__.get_setting_default(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
return self.__class__.get_setting_description(self.key)
|
return self.__class__.get_setting_description(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def units(self):
|
def units(self):
|
||||||
return self.__class__.get_setting_units(self.key)
|
return self.__class__.get_setting_units(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
def clean(self, **kwargs):
|
def clean(self, **kwargs):
|
||||||
"""
|
"""
|
||||||
@ -512,12 +525,12 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
except self.DoesNotExist:
|
except self.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def choices(self, **kwargs):
|
def choices(self):
|
||||||
"""
|
"""
|
||||||
Return the available choices for this setting (or None if no choices are defined)
|
Return the available choices for this setting (or None if no choices are defined)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self.__class__.get_setting_choices(self.key, **kwargs)
|
return self.__class__.get_setting_choices(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
def valid_options(self):
|
def valid_options(self):
|
||||||
"""
|
"""
|
||||||
@ -531,14 +544,14 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
return [opt[0] for opt in choices]
|
return [opt[0] for opt in choices]
|
||||||
|
|
||||||
def is_choice(self, **kwargs):
|
def is_choice(self):
|
||||||
"""
|
"""
|
||||||
Check if this setting is a "choice" field
|
Check if this setting is a "choice" field
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self.__class__.get_setting_choices(self.key, **kwargs) is not None
|
return self.__class__.get_setting_choices(self.key, **self.get_kwargs()) is not None
|
||||||
|
|
||||||
def as_choice(self, **kwargs):
|
def as_choice(self):
|
||||||
"""
|
"""
|
||||||
Render this setting as the "display" value of a choice field,
|
Render this setting as the "display" value of a choice field,
|
||||||
e.g. if the choices are:
|
e.g. if the choices are:
|
||||||
@ -547,7 +560,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
then display 'A4 paper'
|
then display 'A4 paper'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
choices = self.get_setting_choices(self.key, **kwargs)
|
choices = self.get_setting_choices(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
if not choices:
|
if not choices:
|
||||||
return self.value
|
return self.value
|
||||||
@ -558,12 +571,28 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
def is_bool(self, **kwargs):
|
def is_model(self):
|
||||||
|
"""
|
||||||
|
Check if this setting references a model instance in the database
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.model_name() is not None
|
||||||
|
|
||||||
|
def model_name(self):
|
||||||
|
"""
|
||||||
|
Return the model name associated with this setting
|
||||||
|
"""
|
||||||
|
|
||||||
|
setting = self.get_setting_definition(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
|
return setting.get('model', None)
|
||||||
|
|
||||||
|
def is_bool(self):
|
||||||
"""
|
"""
|
||||||
Check if this setting is required to be a boolean value
|
Check if this setting is required to be a boolean value
|
||||||
"""
|
"""
|
||||||
|
|
||||||
validator = self.__class__.get_setting_validator(self.key, **kwargs)
|
validator = self.__class__.get_setting_validator(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
return self.__class__.validator_is_bool(validator)
|
return self.__class__.validator_is_bool(validator)
|
||||||
|
|
||||||
@ -576,17 +605,20 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
return InvenTree.helpers.str2bool(self.value)
|
return InvenTree.helpers.str2bool(self.value)
|
||||||
|
|
||||||
def setting_type(self, **kwargs):
|
def setting_type(self):
|
||||||
"""
|
"""
|
||||||
Return the field type identifier for this setting object
|
Return the field type identifier for this setting object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self.is_bool(**kwargs):
|
if self.is_bool():
|
||||||
return 'boolean'
|
return 'boolean'
|
||||||
|
|
||||||
elif self.is_int(**kwargs):
|
elif self.is_int():
|
||||||
return 'integer'
|
return 'integer'
|
||||||
|
|
||||||
|
elif self.is_model():
|
||||||
|
return 'model'
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return 'string'
|
return 'string'
|
||||||
|
|
||||||
@ -603,12 +635,12 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_int(self, **kwargs):
|
def is_int(self,):
|
||||||
"""
|
"""
|
||||||
Check if the setting is required to be an integer value:
|
Check if the setting is required to be an integer value:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
validator = self.__class__.get_setting_validator(self.key, **kwargs)
|
validator = self.__class__.get_setting_validator(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
return self.__class__.validator_is_int(validator)
|
return self.__class__.validator_is_int(validator)
|
||||||
|
|
||||||
@ -651,88 +683,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def protected(self):
|
def protected(self):
|
||||||
return self.__class__.is_protected(self.key)
|
return self.__class__.is_protected(self.key, **self.get_kwargs())
|
||||||
|
|
||||||
|
|
||||||
class GenericReferencedSettingClass:
|
|
||||||
"""
|
|
||||||
This mixin can be used to add reference keys to static properties
|
|
||||||
|
|
||||||
Sample:
|
|
||||||
```python
|
|
||||||
class SampleSetting(GenericReferencedSettingClass, common.models.BaseInvenTreeSetting):
|
|
||||||
class Meta:
|
|
||||||
unique_together = [
|
|
||||||
('sample', 'key'),
|
|
||||||
]
|
|
||||||
|
|
||||||
REFERENCE_NAME = 'sample'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_setting_definition(cls, key, **kwargs):
|
|
||||||
# mysampledict contains the dict with all settings for this SettingClass - this could also be a dynamic lookup
|
|
||||||
|
|
||||||
kwargs['settings'] = mysampledict
|
|
||||||
return super().get_setting_definition(key, **kwargs)
|
|
||||||
|
|
||||||
sample = models.charKey( # the name for this field is the additonal key and must be set in the Meta class an REFERENCE_NAME
|
|
||||||
max_length=256,
|
|
||||||
verbose_name=_('sample')
|
|
||||||
)
|
|
||||||
```
|
|
||||||
"""
|
|
||||||
|
|
||||||
REFERENCE_NAME = None
|
|
||||||
|
|
||||||
def _get_reference(self):
|
|
||||||
"""
|
|
||||||
Returns dict that can be used as an argument for kwargs calls.
|
|
||||||
Helps to make overriden calls generic for simple reuse.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
```python
|
|
||||||
some_random_function(argument0, kwarg1=value1, **self._get_reference())
|
|
||||||
```
|
|
||||||
"""
|
|
||||||
return {
|
|
||||||
self.REFERENCE_NAME: getattr(self, self.REFERENCE_NAME)
|
|
||||||
}
|
|
||||||
|
|
||||||
"""
|
|
||||||
We override the following class methods,
|
|
||||||
so that we can pass the modified key instance as an additional argument
|
|
||||||
"""
|
|
||||||
|
|
||||||
def clean(self, **kwargs):
|
|
||||||
|
|
||||||
kwargs[self.REFERENCE_NAME] = getattr(self, self.REFERENCE_NAME)
|
|
||||||
|
|
||||||
super().clean(**kwargs)
|
|
||||||
|
|
||||||
def is_bool(self, **kwargs):
|
|
||||||
|
|
||||||
kwargs[self.REFERENCE_NAME] = getattr(self, self.REFERENCE_NAME)
|
|
||||||
|
|
||||||
return super().is_bool(**kwargs)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
return self.__class__.get_setting_name(self.key, **self._get_reference())
|
|
||||||
|
|
||||||
@property
|
|
||||||
def default_value(self):
|
|
||||||
return self.__class__.get_setting_default(self.key, **self._get_reference())
|
|
||||||
|
|
||||||
@property
|
|
||||||
def description(self):
|
|
||||||
return self.__class__.get_setting_description(self.key, **self._get_reference())
|
|
||||||
|
|
||||||
@property
|
|
||||||
def units(self):
|
|
||||||
return self.__class__.get_setting_units(self.key, **self._get_reference())
|
|
||||||
|
|
||||||
def choices(self):
|
|
||||||
return self.__class__.get_setting_choices(self.key, **self._get_reference())
|
|
||||||
|
|
||||||
|
|
||||||
def settings_group_options():
|
def settings_group_options():
|
||||||
@ -1558,6 +1509,16 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
|
|||||||
|
|
||||||
return self.__class__.get_setting(self.key, user=self.user)
|
return self.__class__.get_setting(self.key, user=self.user)
|
||||||
|
|
||||||
|
def get_kwargs(self):
|
||||||
|
"""
|
||||||
|
Explicit kwargs required to uniquely identify a particular setting object,
|
||||||
|
in addition to the 'key' parameter
|
||||||
|
"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
'user': self.user,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class PriceBreak(models.Model):
|
class PriceBreak(models.Model):
|
||||||
"""
|
"""
|
||||||
|
@ -28,6 +28,8 @@ class SettingsSerializer(InvenTreeModelSerializer):
|
|||||||
|
|
||||||
choices = serializers.SerializerMethodField()
|
choices = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
model_name = serializers.CharField(read_only=True)
|
||||||
|
|
||||||
def get_choices(self, obj):
|
def get_choices(self, obj):
|
||||||
"""
|
"""
|
||||||
Returns the choices available for a given item
|
Returns the choices available for a given item
|
||||||
@ -75,6 +77,7 @@ class GlobalSettingsSerializer(SettingsSerializer):
|
|||||||
'description',
|
'description',
|
||||||
'type',
|
'type',
|
||||||
'choices',
|
'choices',
|
||||||
|
'model_name',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -96,6 +99,7 @@ class UserSettingsSerializer(SettingsSerializer):
|
|||||||
'user',
|
'user',
|
||||||
'type',
|
'type',
|
||||||
'choices',
|
'choices',
|
||||||
|
'model_name',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -124,6 +128,7 @@ class GenericReferencedSettingSerializer(SettingsSerializer):
|
|||||||
'description',
|
'description',
|
||||||
'type',
|
'type',
|
||||||
'choices',
|
'choices',
|
||||||
|
'model_name',
|
||||||
]
|
]
|
||||||
|
|
||||||
# set Meta class
|
# set Meta class
|
||||||
|
@ -102,7 +102,7 @@ class PluginConfig(models.Model):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class PluginSetting(common.models.GenericReferencedSettingClass, common.models.BaseInvenTreeSetting):
|
class PluginSetting(common.models.BaseInvenTreeSetting):
|
||||||
"""
|
"""
|
||||||
This model represents settings for individual plugins
|
This model represents settings for individual plugins
|
||||||
"""
|
"""
|
||||||
@ -112,7 +112,13 @@ class PluginSetting(common.models.GenericReferencedSettingClass, common.models.B
|
|||||||
('plugin', 'key'),
|
('plugin', 'key'),
|
||||||
]
|
]
|
||||||
|
|
||||||
REFERENCE_NAME = 'plugin'
|
plugin = models.ForeignKey(
|
||||||
|
PluginConfig,
|
||||||
|
related_name='settings',
|
||||||
|
null=False,
|
||||||
|
verbose_name=_('Plugin'),
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_setting_definition(cls, key, **kwargs):
|
def get_setting_definition(cls, key, **kwargs):
|
||||||
@ -131,7 +137,7 @@ class PluginSetting(common.models.GenericReferencedSettingClass, common.models.B
|
|||||||
|
|
||||||
if 'settings' not in kwargs:
|
if 'settings' not in kwargs:
|
||||||
|
|
||||||
plugin = kwargs.pop('plugin', None)
|
plugin = kwargs.pop('plugin')
|
||||||
|
|
||||||
if plugin:
|
if plugin:
|
||||||
|
|
||||||
@ -142,16 +148,18 @@ class PluginSetting(common.models.GenericReferencedSettingClass, common.models.B
|
|||||||
|
|
||||||
return super().get_setting_definition(key, **kwargs)
|
return super().get_setting_definition(key, **kwargs)
|
||||||
|
|
||||||
plugin = models.ForeignKey(
|
def get_kwargs(self):
|
||||||
PluginConfig,
|
"""
|
||||||
related_name='settings',
|
Explicit kwargs required to uniquely identify a particular setting object,
|
||||||
null=False,
|
in addition to the 'key' parameter
|
||||||
verbose_name=_('Plugin'),
|
"""
|
||||||
on_delete=models.CASCADE,
|
|
||||||
)
|
return {
|
||||||
|
'plugin': self.plugin,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class NotificationUserSetting(common.models.GenericReferencedSettingClass, common.models.BaseInvenTreeSetting):
|
class NotificationUserSetting(common.models.BaseInvenTreeSetting):
|
||||||
"""
|
"""
|
||||||
This model represents notification settings for a user
|
This model represents notification settings for a user
|
||||||
"""
|
"""
|
||||||
@ -161,8 +169,6 @@ class NotificationUserSetting(common.models.GenericReferencedSettingClass, commo
|
|||||||
('method', 'user', 'key'),
|
('method', 'user', 'key'),
|
||||||
]
|
]
|
||||||
|
|
||||||
REFERENCE_NAME = 'method'
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_setting_definition(cls, key, **kwargs):
|
def get_setting_definition(cls, key, **kwargs):
|
||||||
from common.notifications import storage
|
from common.notifications import storage
|
||||||
@ -171,6 +177,17 @@ class NotificationUserSetting(common.models.GenericReferencedSettingClass, commo
|
|||||||
|
|
||||||
return super().get_setting_definition(key, **kwargs)
|
return super().get_setting_definition(key, **kwargs)
|
||||||
|
|
||||||
|
def get_kwargs(self):
|
||||||
|
"""
|
||||||
|
Explicit kwargs required to uniquely identify a particular setting object,
|
||||||
|
in addition to the 'key' parameter
|
||||||
|
"""
|
||||||
|
|
||||||
|
return {
|
||||||
|
'method': self.method,
|
||||||
|
'user': self.user,
|
||||||
|
}
|
||||||
|
|
||||||
method = models.CharField(
|
method = models.CharField(
|
||||||
max_length=255,
|
max_length=255,
|
||||||
verbose_name=_('Method'),
|
verbose_name=_('Method'),
|
||||||
|
@ -65,6 +65,11 @@ class SampleIntegrationPlugin(AppMixin, SettingsMixin, UrlsMixin, NavigationMixi
|
|||||||
],
|
],
|
||||||
'default': 'A',
|
'default': 'A',
|
||||||
},
|
},
|
||||||
|
'SELECT_COMPANY': {
|
||||||
|
'name': 'Company',
|
||||||
|
'description': 'Select a company object from the database',
|
||||||
|
'model': 'company.Company',
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
NAVIGATION = [
|
NAVIGATION = [
|
||||||
|
@ -22,6 +22,9 @@
|
|||||||
{{ setting.description }}
|
{{ setting.description }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
{% if setting.model_name %}
|
||||||
|
<b>Model name: {{ setting.model_name }}</b>
|
||||||
|
{% endif %}
|
||||||
{% if setting.is_bool %}
|
{% if setting.is_bool %}
|
||||||
<div class='form-check form-switch'>
|
<div class='form-check form-switch'>
|
||||||
<input class='form-check-input boolean-setting' fieldname='{{ setting.key.upper }}' pk='{{ setting.pk }}' setting='{{ setting.key.upper }}' id='setting-value-{{ setting.key.upper }}' type='checkbox' {% if setting.as_bool %}checked=''{% endif %} {% if plugin %}plugin='{{ plugin.slug }}'{% endif %}{% if user_setting %}user='{{request.user.id}}'{% endif %}{% if notification_setting %}notification='{{request.user.id}}'{% endif %}>
|
<input class='form-check-input boolean-setting' fieldname='{{ setting.key.upper }}' pk='{{ setting.pk }}' setting='{{ setting.key.upper }}' id='setting-value-{{ setting.key.upper }}' type='checkbox' {% if setting.as_bool %}checked=''{% endif %} {% if plugin %}plugin='{{ plugin.slug }}'{% endif %}{% if user_setting %}user='{{request.user.id}}'{% endif %}{% if notification_setting %}notification='{{request.user.id}}'{% endif %}>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user