mirror of
https://github.com/inventree/InvenTree.git
synced 2025-12-16 09:18:10 +00:00
Add validator for ParameterTemplate model type
- Update migrations - Make Parameter class abstract (for now) - Validators
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# Generated by Django 4.2.25 on 2025-10-28 11:11
|
||||
|
||||
import common.validators
|
||||
import InvenTree.models
|
||||
import InvenTree.validators
|
||||
from django.db import migrations, models
|
||||
@@ -62,6 +63,17 @@ class Migration(migrations.Migration):
|
||||
verbose_name="Description",
|
||||
),
|
||||
),
|
||||
(
|
||||
"model_type",
|
||||
models.CharField(
|
||||
blank=True,
|
||||
default="",
|
||||
help_text="Target model type for this parameter",
|
||||
max_length=100,
|
||||
validators=[common.validators.validate_parameter_template_model_type],
|
||||
verbose_name="Model type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"checkbox",
|
||||
models.BooleanField(
|
||||
|
||||
@@ -8,6 +8,11 @@ def copy_templates(old_model, new_model):
|
||||
|
||||
templates = []
|
||||
|
||||
# Clear out all existing instances
|
||||
new_model.objects.all().delete()
|
||||
|
||||
assert new_model.objects.count() == 0
|
||||
|
||||
for template in old_model.objects.all():
|
||||
templates.append(new_model(
|
||||
name=template.name,
|
||||
@@ -23,6 +28,8 @@ def copy_templates(old_model, new_model):
|
||||
new_model.objects.bulk_create(templates)
|
||||
print(f"Migrated {len(templates)} ParameterTemplate instances.")
|
||||
|
||||
assert new_model.objects.count() == len(templates)
|
||||
|
||||
|
||||
def forward_copy_templates(apps, schema_editor):
|
||||
"""Forward migration: copy from PartParameterTemplate to ParameterTemplate."""
|
||||
@@ -43,6 +50,7 @@ def reverse_copy_templates(apps, schema_editor):
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("part", "0132_partparametertemplate_selectionlist"),
|
||||
("common", "0040_parametertemplate"),
|
||||
]
|
||||
|
||||
|
||||
@@ -72,14 +72,21 @@ class RenderMeta(enums.ChoicesMeta):
|
||||
"""Metaclass for rendering choices."""
|
||||
|
||||
choice_fnc = None
|
||||
allow_blank: bool = False
|
||||
blank_label: str = '------'
|
||||
|
||||
@property
|
||||
def choices(self):
|
||||
"""Return a list of choices for the enum class."""
|
||||
fnc = getattr(self, 'choice_fnc', None)
|
||||
if fnc:
|
||||
return fnc()
|
||||
return []
|
||||
options = fnc()
|
||||
options = []
|
||||
|
||||
if self.allow_blank:
|
||||
options.insert(0, ('', self.blank_label))
|
||||
|
||||
return options
|
||||
|
||||
|
||||
class RenderChoices(models.TextChoices, metaclass=RenderMeta): # type: ignore
|
||||
@@ -2385,6 +2392,12 @@ class ParameterTemplate(
|
||||
class Meta:
|
||||
"""Metaclass options for the ParameterTemplate model."""
|
||||
|
||||
class ModelChoices(RenderChoices):
|
||||
"""Model choices for parameter templates."""
|
||||
|
||||
allow_blank = True
|
||||
choice_fnc = common.validators.parameter_model_options
|
||||
|
||||
@staticmethod
|
||||
def get_api_url() -> str:
|
||||
"""Return the API URL associated with the ParameterTemplate model."""
|
||||
@@ -2467,6 +2480,15 @@ class ParameterTemplate(
|
||||
|
||||
return [x.strip() for x in self.choices.split(',') if x.strip()]
|
||||
|
||||
model_type = models.CharField(
|
||||
max_length=100,
|
||||
default='',
|
||||
blank=True,
|
||||
validators=[common.validators.validate_parameter_template_model_type],
|
||||
verbose_name=_('Model type'),
|
||||
help_text=_('Target model type for this parameter'),
|
||||
)
|
||||
|
||||
name = models.CharField(
|
||||
max_length=100,
|
||||
verbose_name=_('Name'),
|
||||
@@ -2532,6 +2554,9 @@ class Parameter(
|
||||
class Meta:
|
||||
"""Meta options for Parameter model."""
|
||||
|
||||
# TODO: Make this non-abstract, actually implement...
|
||||
abstract = True
|
||||
|
||||
verbose_name = _('Parameter')
|
||||
verbose_name_plural = _('Parameters')
|
||||
unique_together = [['model_type', 'model_id', 'template']]
|
||||
|
||||
@@ -711,11 +711,31 @@ class ParameterTemplateSerializer(
|
||||
'name',
|
||||
'units',
|
||||
'description',
|
||||
'model_type',
|
||||
'checkbox',
|
||||
'choices',
|
||||
'selectionlist',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""Override the model_type field to provide dynamic choices."""
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if len(self.fields['model_type'].choices) == 0:
|
||||
self.fields[
|
||||
'model_type'
|
||||
].choices = common.validators.attachment_model_options()
|
||||
|
||||
# Note: The choices are overridden at run-time on class initialization
|
||||
model_type = serializers.ChoiceField(
|
||||
label=_('Model Type'),
|
||||
default='',
|
||||
choices=common.validators.attachment_model_options(),
|
||||
required=False,
|
||||
allow_blank=True,
|
||||
allow_null=True,
|
||||
)
|
||||
|
||||
|
||||
class IconSerializer(serializers.Serializer):
|
||||
"""Serializer for an icon."""
|
||||
|
||||
@@ -10,6 +10,47 @@ import common.icons
|
||||
from common.settings import get_global_setting
|
||||
|
||||
|
||||
def parameter_model_types():
|
||||
"""Return a list of valid parameter model choices."""
|
||||
import InvenTree.models
|
||||
|
||||
return list(
|
||||
InvenTree.helpers_model.getModelsWithMixin(
|
||||
InvenTree.models.InvenTreeParameterMixin
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def parameter_model_options():
|
||||
"""Return a list of options for models which support parameters."""
|
||||
return [
|
||||
(model.__name__.lower(), model._meta.verbose_name)
|
||||
for model in parameter_model_types()
|
||||
]
|
||||
|
||||
|
||||
def validate_parameter_model_type(value: str):
|
||||
"""Ensure that the provided parameter model is valid."""
|
||||
model_names = [el[0] for el in parameter_model_options()]
|
||||
if value not in model_names:
|
||||
raise ValidationError('Model type does not support parameters')
|
||||
|
||||
|
||||
def validate_parameter_template_model_type(value: str):
|
||||
"""Ensure that the provided model type is valid.
|
||||
|
||||
Note: A ParameterTemplate may have a blank model type.
|
||||
"""
|
||||
value = str(value).strip()
|
||||
|
||||
if not value:
|
||||
# Empty values are allowed
|
||||
return
|
||||
|
||||
# Pass any other value to the Parameter model type validator
|
||||
validate_parameter_model_type(value)
|
||||
|
||||
|
||||
def attachment_model_types():
|
||||
"""Return a list of valid attachment model choices."""
|
||||
import InvenTree.models
|
||||
|
||||
Reference in New Issue
Block a user