mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Refactor: BaseInvenTreeSetting (#4834)
* Added typing for settings * Refactored common.BaseInvenTreeSetting model to make it more generic * Use older syntax for union types * Added protected option to typing * Remove now unused code * Remove old 'get_kwargs' method as it is replaced by 'get_filters_for_instance' * Trigger ci
This commit is contained in:
parent
61481b4eb0
commit
cb8ae10280
@ -16,6 +16,7 @@ import uuid
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from secrets import compare_digest
|
from secrets import compare_digest
|
||||||
|
from typing import Any, Callable, Dict, List, Tuple, TypedDict, Union
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -112,10 +113,45 @@ class ProjectCode(InvenTree.models.MetadataMixin, models.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class BaseInvenTreeSetting(models.Model):
|
class SettingsKeyType(TypedDict, total=False):
|
||||||
"""An base InvenTreeSetting object is a key:value pair used for storing single values (e.g. one-off settings values)."""
|
"""Type definitions for a SettingsKeyType
|
||||||
|
|
||||||
SETTINGS = {}
|
Attributes:
|
||||||
|
name: Translatable string name of the setting (required)
|
||||||
|
description: Translatable string description of the setting (required)
|
||||||
|
units: Units of the particular setting (optional)
|
||||||
|
validator: Validation function/list of functions for the setting (optional, default: None, e.g: bool, int, str, MinValueValidator, ...)
|
||||||
|
default: Default value or function that returns default value (optional)
|
||||||
|
choices: (Function that returns) Tuple[str: key, str: display value] (optional)
|
||||||
|
hidden: Hide this setting from settings page (optional)
|
||||||
|
before_save: Function that gets called after save with *args, **kwargs (optional)
|
||||||
|
after_save: Function that gets called after save with *args, **kwargs (optional)
|
||||||
|
protected: Protected values are not returned to the client, instead "***" is returned (optional, default: False)
|
||||||
|
"""
|
||||||
|
|
||||||
|
name: str
|
||||||
|
description: str
|
||||||
|
units: str
|
||||||
|
validator: Union[Callable, List[Callable], Tuple[Callable]]
|
||||||
|
default: Union[Callable, Any]
|
||||||
|
choices: Union[Tuple[str, str], Callable[[], Tuple[str, str]]]
|
||||||
|
hidden: bool
|
||||||
|
before_save: Callable[..., None]
|
||||||
|
after_save: Callable[..., None]
|
||||||
|
protected: bool
|
||||||
|
|
||||||
|
|
||||||
|
class BaseInvenTreeSetting(models.Model):
|
||||||
|
"""An base InvenTreeSetting object is a key:value pair used for storing single values (e.g. one-off settings values).
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
SETTINGS: definition of all available settings
|
||||||
|
extra_unique_fields: List of extra fields used to be unique, e.g. for PluginConfig -> plugin
|
||||||
|
"""
|
||||||
|
|
||||||
|
SETTINGS: Dict[str, SettingsKeyType] = {}
|
||||||
|
|
||||||
|
extra_unique_fields: List[str] = []
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta options for BaseInvenTreeSetting -> abstract stops creation of database entry."""
|
"""Meta options for BaseInvenTreeSetting -> abstract stops creation of database entry."""
|
||||||
@ -129,7 +165,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
do_cache = kwargs.pop('cache', True)
|
do_cache = kwargs.pop('cache', True)
|
||||||
|
|
||||||
self.clean(**kwargs)
|
self.clean(**kwargs)
|
||||||
self.validate_unique(**kwargs)
|
self.validate_unique()
|
||||||
|
|
||||||
# Execute before_save action
|
# Execute before_save action
|
||||||
self._call_settings_function('before_save', args, kwargs)
|
self._call_settings_function('before_save', args, kwargs)
|
||||||
@ -162,7 +198,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
@property
|
@property
|
||||||
def cache_key(self):
|
def cache_key(self):
|
||||||
"""Generate a unique cache key for this settings object"""
|
"""Generate a unique cache key for this settings object"""
|
||||||
return self.__class__.create_cache_key(self.key, **self.get_kwargs())
|
return self.__class__.create_cache_key(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
def save_to_cache(self):
|
def save_to_cache(self):
|
||||||
"""Save this setting object to cache"""
|
"""Save this setting object to cache"""
|
||||||
@ -199,7 +235,16 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
return key.replace(" ", "")
|
return key.replace(" ", "")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def allValues(cls, user=None, exclude_hidden=False):
|
def get_filters(cls, **kwargs):
|
||||||
|
"""Enable to filter by other kwargs defined in cls.extra_unique_fields"""
|
||||||
|
return {key: value for key, value in kwargs.items() if key in cls.extra_unique_fields}
|
||||||
|
|
||||||
|
def get_filters_for_instance(self):
|
||||||
|
"""Enable to filter by other fields defined in self.extra_unique_fields"""
|
||||||
|
return {key: getattr(self, key, None) for key in self.extra_unique_fields if hasattr(self, key)}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def allValues(cls, exclude_hidden=False, **kwargs):
|
||||||
"""Return a dict of "all" defined global settings.
|
"""Return a dict of "all" defined global settings.
|
||||||
|
|
||||||
This performs a single database lookup,
|
This performs a single database lookup,
|
||||||
@ -212,9 +257,8 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
# Keys which start with an undersore are used for internal functionality
|
# Keys which start with an undersore are used for internal functionality
|
||||||
results = results.exclude(key__startswith='_')
|
results = results.exclude(key__startswith='_')
|
||||||
|
|
||||||
# Optionally filter by user
|
# Optionally filter by other keys
|
||||||
if user is not None:
|
results = results.filter(**cls.get_filters(**kwargs))
|
||||||
results = results.filter(user=user)
|
|
||||||
|
|
||||||
# Query the database
|
# Query the database
|
||||||
settings = {}
|
settings = {}
|
||||||
@ -253,16 +297,6 @@ 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):
|
||||||
"""Return the 'definition' of a particular settings value, as a dict object.
|
"""Return the 'definition' of a particular settings value, as a dict object.
|
||||||
@ -361,32 +395,11 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
filters = {
|
filters = {
|
||||||
'key__iexact': key,
|
'key__iexact': key,
|
||||||
|
|
||||||
|
# Optionally filter by other keys
|
||||||
|
**cls.get_filters(**kwargs),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Filter by user
|
|
||||||
user = kwargs.get('user', None)
|
|
||||||
|
|
||||||
if user is not None:
|
|
||||||
filters['user'] = user
|
|
||||||
|
|
||||||
# Filter by plugin
|
|
||||||
plugin = kwargs.get('plugin', None)
|
|
||||||
|
|
||||||
if plugin is not None:
|
|
||||||
from plugin import InvenTreePlugin
|
|
||||||
|
|
||||||
if issubclass(plugin.__class__, InvenTreePlugin):
|
|
||||||
plugin = plugin.plugin_config()
|
|
||||||
|
|
||||||
filters['plugin'] = plugin
|
|
||||||
kwargs['plugin'] = plugin
|
|
||||||
|
|
||||||
# Filter by method
|
|
||||||
method = kwargs.get('method', None)
|
|
||||||
|
|
||||||
if method is not None:
|
|
||||||
filters['method'] = method
|
|
||||||
|
|
||||||
# Perform cache lookup by default
|
# Perform cache lookup by default
|
||||||
do_cache = kwargs.pop('cache', True)
|
do_cache = kwargs.pop('cache', True)
|
||||||
|
|
||||||
@ -493,22 +506,11 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
filters = {
|
filters = {
|
||||||
'key__iexact': key,
|
'key__iexact': key,
|
||||||
|
|
||||||
|
# Optionally filter by other keys
|
||||||
|
**cls.get_filters(**kwargs),
|
||||||
}
|
}
|
||||||
|
|
||||||
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 InvenTreePlugin
|
|
||||||
|
|
||||||
if issubclass(plugin.__class__, InvenTreePlugin):
|
|
||||||
filters['plugin'] = plugin.plugin_config()
|
|
||||||
else:
|
|
||||||
filters['plugin'] = plugin
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
setting = cls.objects.get(**filters)
|
setting = cls.objects.get(**filters)
|
||||||
except cls.DoesNotExist:
|
except cls.DoesNotExist:
|
||||||
@ -532,22 +534,22 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return name for setting."""
|
"""Return name for setting."""
|
||||||
return self.__class__.get_setting_name(self.key, **self.get_kwargs())
|
return self.__class__.get_setting_name(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def default_value(self):
|
def default_value(self):
|
||||||
"""Return default_value for setting."""
|
"""Return default_value for setting."""
|
||||||
return self.__class__.get_setting_default(self.key, **self.get_kwargs())
|
return self.__class__.get_setting_default(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
"""Return description for setting."""
|
"""Return description for setting."""
|
||||||
return self.__class__.get_setting_description(self.key, **self.get_kwargs())
|
return self.__class__.get_setting_description(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def units(self):
|
def units(self):
|
||||||
"""Return units for setting."""
|
"""Return units for setting."""
|
||||||
return self.__class__.get_setting_units(self.key, **self.get_kwargs())
|
return self.__class__.get_setting_units(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
def clean(self, **kwargs):
|
def clean(self, **kwargs):
|
||||||
"""If a validator (or multiple validators) are defined for a particular setting key, run them against the 'value' field."""
|
"""If a validator (or multiple validators) are defined for a particular setting key, run them against the 'value' field."""
|
||||||
@ -615,7 +617,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
validator(value)
|
validator(value)
|
||||||
|
|
||||||
def validate_unique(self, exclude=None, **kwargs):
|
def validate_unique(self, exclude=None):
|
||||||
"""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.
|
"""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
|
Note that sub-classes (UserSetting, PluginSetting) use other filters
|
||||||
@ -625,17 +627,11 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
filters = {
|
filters = {
|
||||||
'key__iexact': self.key,
|
'key__iexact': self.key,
|
||||||
|
|
||||||
|
# Optionally filter by other keys
|
||||||
|
**self.get_filters_for_instance(),
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
try:
|
||||||
# Check if a duplicate setting already exists
|
# Check if a duplicate setting already exists
|
||||||
setting = self.__class__.objects.filter(**filters).exclude(id=self.id)
|
setting = self.__class__.objects.filter(**filters).exclude(id=self.id)
|
||||||
@ -648,7 +644,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
def choices(self):
|
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, **self.get_kwargs())
|
return self.__class__.get_setting_choices(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
def valid_options(self):
|
def valid_options(self):
|
||||||
"""Return a list of valid options for this setting."""
|
"""Return a list of valid options for this setting."""
|
||||||
@ -661,7 +657,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
def is_choice(self):
|
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, **self.get_kwargs()) is not None
|
return self.__class__.get_setting_choices(self.key, **self.get_filters_for_instance()) is not None
|
||||||
|
|
||||||
def as_choice(self):
|
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.
|
||||||
@ -671,7 +667,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
and the value is 'A4',
|
and the value is 'A4',
|
||||||
then display 'A4 paper'
|
then display 'A4 paper'
|
||||||
"""
|
"""
|
||||||
choices = self.get_setting_choices(self.key, **self.get_kwargs())
|
choices = self.get_setting_choices(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
if not choices:
|
if not choices:
|
||||||
return self.value
|
return self.value
|
||||||
@ -688,7 +684,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
def model_name(self):
|
def model_name(self):
|
||||||
"""Return the model name associated with this setting."""
|
"""Return the model name associated with this setting."""
|
||||||
setting = self.get_setting_definition(self.key, **self.get_kwargs())
|
setting = self.get_setting_definition(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
return setting.get('model', None)
|
return setting.get('model', None)
|
||||||
|
|
||||||
@ -752,7 +748,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
def is_bool(self):
|
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, **self.get_kwargs())
|
validator = self.__class__.get_setting_validator(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
return self.__class__.validator_is_bool(validator)
|
return self.__class__.validator_is_bool(validator)
|
||||||
|
|
||||||
@ -792,7 +788,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
|
|
||||||
def is_int(self,):
|
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, **self.get_kwargs())
|
validator = self.__class__.get_setting_validator(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
return self.__class__.validator_is_int(validator)
|
return self.__class__.validator_is_int(validator)
|
||||||
|
|
||||||
@ -831,7 +827,7 @@ class BaseInvenTreeSetting(models.Model):
|
|||||||
@property
|
@property
|
||||||
def protected(self):
|
def protected(self):
|
||||||
"""Returns if setting is protected from rendering."""
|
"""Returns if setting is protected from rendering."""
|
||||||
return self.__class__.is_protected(self.key, **self.get_kwargs())
|
return self.__class__.is_protected(self.key, **self.get_filters_for_instance())
|
||||||
|
|
||||||
|
|
||||||
def settings_group_options():
|
def settings_group_options():
|
||||||
@ -2105,6 +2101,7 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
|
|||||||
}
|
}
|
||||||
|
|
||||||
typ = 'user'
|
typ = 'user'
|
||||||
|
extra_unique_fields = ['user']
|
||||||
|
|
||||||
key = models.CharField(
|
key = models.CharField(
|
||||||
max_length=50,
|
max_length=50,
|
||||||
@ -2121,20 +2118,10 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
|
|||||||
help_text=_('User'),
|
help_text=_('User'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def validate_unique(self, exclude=None, **kwargs):
|
|
||||||
"""Return if the setting (including key) is unique."""
|
|
||||||
return super().validate_unique(exclude=exclude, user=self.user)
|
|
||||||
|
|
||||||
def to_native_value(self):
|
def to_native_value(self):
|
||||||
"""Return the "pythonic" value, e.g. convert "True" to True, and "1" to 1."""
|
"""Return the "pythonic" value, e.g. convert "True" to True, and "1" to 1."""
|
||||||
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(MetaMixin):
|
class PriceBreak(MetaMixin):
|
||||||
"""Represents a PriceBreak model."""
|
"""Represents a PriceBreak model."""
|
||||||
|
@ -19,6 +19,7 @@ from common.settings import currency_code_default
|
|||||||
from InvenTree import settings, version
|
from InvenTree import settings, version
|
||||||
from plugin import registry
|
from plugin import registry
|
||||||
from plugin.models import NotificationUserSetting, PluginSetting
|
from plugin.models import NotificationUserSetting, PluginSetting
|
||||||
|
from plugin.plugin import InvenTreePlugin
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
@ -325,6 +326,8 @@ def setting_object(key, *args, **kwargs):
|
|||||||
# Note, 'plugin' is an instance of an InvenTreePlugin class
|
# Note, 'plugin' is an instance of an InvenTreePlugin class
|
||||||
|
|
||||||
plugin = kwargs['plugin']
|
plugin = kwargs['plugin']
|
||||||
|
if issubclass(plugin.__class__, InvenTreePlugin):
|
||||||
|
plugin = plugin.plugin_config()
|
||||||
|
|
||||||
return PluginSetting.get_setting_object(key, plugin=plugin, cache=cache)
|
return PluginSetting.get_setting_object(key, plugin=plugin, cache=cache)
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ class PluginSettingDetail(RetrieveUpdateAPI):
|
|||||||
if key not in settings:
|
if key not in settings:
|
||||||
raise NotFound(detail=f"Plugin '{plugin.slug}' has no setting matching '{key}'")
|
raise NotFound(detail=f"Plugin '{plugin.slug}' has no setting matching '{key}'")
|
||||||
|
|
||||||
return PluginSetting.get_setting_object(key, plugin=plugin)
|
return PluginSetting.get_setting_object(key, plugin=plugin.plugin_config())
|
||||||
|
|
||||||
# Staff permission required
|
# Staff permission required
|
||||||
permission_classes = [
|
permission_classes = [
|
||||||
|
@ -1,14 +1,25 @@
|
|||||||
"""Plugin mixin class for SettingsMixin."""
|
"""Plugin mixin class for SettingsMixin."""
|
||||||
import logging
|
import logging
|
||||||
|
from typing import TYPE_CHECKING, Dict
|
||||||
|
|
||||||
from django.db.utils import OperationalError, ProgrammingError
|
from django.db.utils import OperationalError, ProgrammingError
|
||||||
|
|
||||||
logger = logging.getLogger('inventree')
|
logger = logging.getLogger('inventree')
|
||||||
|
|
||||||
|
# import only for typechecking, otherwise this throws a model is unready error
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from common.models import SettingsKeyType
|
||||||
|
else:
|
||||||
|
class SettingsKeyType:
|
||||||
|
"""Dummy class, so that python throws no error"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class SettingsMixin:
|
class SettingsMixin:
|
||||||
"""Mixin that enables global settings for the plugin."""
|
"""Mixin that enables global settings for the plugin."""
|
||||||
|
|
||||||
|
SETTINGS: Dict[str, SettingsKeyType] = {}
|
||||||
|
|
||||||
class MixinMeta:
|
class MixinMeta:
|
||||||
"""Meta for mixin."""
|
"""Meta for mixin."""
|
||||||
MIXIN_NAME = 'Settings'
|
MIXIN_NAME = 'Settings'
|
||||||
@ -56,7 +67,7 @@ class SettingsMixin:
|
|||||||
"""
|
"""
|
||||||
from plugin.models import PluginSetting
|
from plugin.models import PluginSetting
|
||||||
|
|
||||||
return PluginSetting.get_setting(key, plugin=self, cache=cache)
|
return PluginSetting.get_setting(key, plugin=self.plugin_config(), cache=cache)
|
||||||
|
|
||||||
def set_setting(self, key, value, user=None):
|
def set_setting(self, key, value, user=None):
|
||||||
"""Set plugin setting value by key."""
|
"""Set plugin setting value by key."""
|
||||||
|
@ -133,6 +133,7 @@ class PluginSetting(common.models.BaseInvenTreeSetting):
|
|||||||
"""This model represents settings for individual plugins."""
|
"""This model represents settings for individual plugins."""
|
||||||
|
|
||||||
typ = 'plugin'
|
typ = 'plugin'
|
||||||
|
extra_unique_fields = ['plugin']
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta for PluginSetting."""
|
"""Meta for PluginSetting."""
|
||||||
@ -165,27 +166,18 @@ class PluginSetting(common.models.BaseInvenTreeSetting):
|
|||||||
plugin = kwargs.pop('plugin', None)
|
plugin = kwargs.pop('plugin', None)
|
||||||
|
|
||||||
if plugin:
|
if plugin:
|
||||||
|
|
||||||
if issubclass(plugin.__class__, InvenTreePlugin):
|
|
||||||
plugin = plugin.plugin_config()
|
|
||||||
|
|
||||||
mixin_settings = getattr(registry, 'mixins_settings')
|
mixin_settings = getattr(registry, 'mixins_settings')
|
||||||
if mixin_settings:
|
if mixin_settings:
|
||||||
kwargs['settings'] = mixin_settings.get(plugin.key, {})
|
kwargs['settings'] = mixin_settings.get(plugin.key, {})
|
||||||
|
|
||||||
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 {
|
|
||||||
'plugin': self.plugin,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class NotificationUserSetting(common.models.BaseInvenTreeSetting):
|
class NotificationUserSetting(common.models.BaseInvenTreeSetting):
|
||||||
"""This model represents notification settings for a user."""
|
"""This model represents notification settings for a user."""
|
||||||
|
|
||||||
typ = 'notification'
|
typ = 'notification'
|
||||||
|
extra_unique_fields = ['method', 'user']
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta for NotificationUserSetting."""
|
"""Meta for NotificationUserSetting."""
|
||||||
@ -202,13 +194,6 @@ class NotificationUserSetting(common.models.BaseInvenTreeSetting):
|
|||||||
|
|
||||||
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'),
|
||||||
|
Loading…
Reference in New Issue
Block a user