mirror of
https://github.com/inventree/InvenTree.git
synced 2026-04-07 20:10:58 +00:00
More migration updates:
- Create new "models" (without moving the existing tables) - Data migration for PartCataegoryParameterTemplate model - Remove PartParameterTemplate and PartParameter models
This commit is contained in:
@@ -0,0 +1,256 @@
|
|||||||
|
# Generated by Django 5.2.8 on 2025-12-03 11:51
|
||||||
|
|
||||||
|
import InvenTree.models
|
||||||
|
import InvenTree.validators
|
||||||
|
from django.conf import settings
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
"""Create new ParameterTemplate and Parameter models.
|
||||||
|
|
||||||
|
Ref: https://github.com/inventree/InvenTree/pull/10699
|
||||||
|
|
||||||
|
These models have been migrated from the following (existing) models:
|
||||||
|
- part.PartParameterTemplate -> common.ParameterTemplate
|
||||||
|
- part.PartParameter -> common.Parameter
|
||||||
|
|
||||||
|
To preserve the existing data, we will use the existing database tables.
|
||||||
|
|
||||||
|
For this to work, the existing models (part.PartParameterTemplate and part.PartParameter)
|
||||||
|
must have already had schema and migrations applied:
|
||||||
|
|
||||||
|
- part/migrations/0144_auto_20251203_1045.py
|
||||||
|
- part/migrations/0145_auto_20251203_1120.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("common", "0039_emailthread_emailmessage"),
|
||||||
|
("part", "0145_auto_20251203_1120"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="ParameterTemplate",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"metadata",
|
||||||
|
models.JSONField(
|
||||||
|
blank=True,
|
||||||
|
help_text="JSON metadata field, for use by external plugins",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Plugin Metadata",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"model_type",
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True, null=True,
|
||||||
|
help_text="Target model type for this parameter template",
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to="contenttypes.contenttype",
|
||||||
|
verbose_name="Model type",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"name",
|
||||||
|
models.CharField(
|
||||||
|
help_text="Parameter Name",
|
||||||
|
max_length=100,
|
||||||
|
unique=True,
|
||||||
|
verbose_name="Name",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"units",
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Physical units for this parameter",
|
||||||
|
max_length=25,
|
||||||
|
validators=[InvenTree.validators.validate_physical_units],
|
||||||
|
verbose_name="Units",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"description",
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Parameter description",
|
||||||
|
max_length=250,
|
||||||
|
verbose_name="Description",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"checkbox",
|
||||||
|
models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
help_text="Is this parameter a checkbox?",
|
||||||
|
verbose_name="Checkbox",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"choices",
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Valid choices for this parameter (comma-separated)",
|
||||||
|
max_length=5000,
|
||||||
|
verbose_name="Choices",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"selectionlist",
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
help_text="Selection list for this parameter",
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
related_name="templates",
|
||||||
|
to="common.selectionlist",
|
||||||
|
verbose_name="Selection List",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"enabled",
|
||||||
|
models.BooleanField(
|
||||||
|
default=True,
|
||||||
|
help_text="Is this parameter template enabled?",
|
||||||
|
verbose_name="Enabled",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Parameter Template",
|
||||||
|
"verbose_name_plural": "Parameter Templates",
|
||||||
|
"db_table": "part_partparametertemplate",
|
||||||
|
"managed": False,
|
||||||
|
},
|
||||||
|
bases=(InvenTree.models.PluginValidationMixin, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Parameter",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"metadata",
|
||||||
|
models.JSONField(
|
||||||
|
blank=True,
|
||||||
|
help_text="JSON metadata field, for use by external plugins",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Plugin Metadata",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"updated",
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
default=None,
|
||||||
|
help_text="Timestamp of last update",
|
||||||
|
null=True,
|
||||||
|
verbose_name="Updated",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"model_type",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="contenttypes.contenttype",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"model_id",
|
||||||
|
models.PositiveIntegerField(
|
||||||
|
help_text="ID of the target model for this parameter",
|
||||||
|
verbose_name="Model ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"data",
|
||||||
|
models.CharField(
|
||||||
|
help_text="Parameter Value",
|
||||||
|
max_length=500,
|
||||||
|
validators=[django.core.validators.MinLengthValidator(1)],
|
||||||
|
verbose_name="Data",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"data_numeric",
|
||||||
|
models.FloatField(blank=True, default=None, null=True),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"note",
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text="Optional note field",
|
||||||
|
max_length=500,
|
||||||
|
verbose_name="Note",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"template",
|
||||||
|
models.ForeignKey(
|
||||||
|
help_text="Parameter template",
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="parameters",
|
||||||
|
to="common.parametertemplate",
|
||||||
|
verbose_name="Template",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"updated_by",
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
help_text="User who last updated this object",
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
related_name="%(class)s_updated",
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name="Update By",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Parameter",
|
||||||
|
"verbose_name_plural": "Parameters",
|
||||||
|
"unique_together": {("model_type", "model_id", "template")},
|
||||||
|
"db_table": "part_partparameter",
|
||||||
|
"managed": False,
|
||||||
|
},
|
||||||
|
bases=(InvenTree.models.PluginValidationMixin, models.Model),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name="parameter",
|
||||||
|
index=models.Index(
|
||||||
|
fields=["model_type", "model_id"], name="common_para_model_t_244405_idx"
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="parameter",
|
||||||
|
options={"verbose_name": "Parameter", "verbose_name_plural": "Parameters"},
|
||||||
|
),
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name="parametertemplate",
|
||||||
|
options={
|
||||||
|
"verbose_name": "Parameter Template",
|
||||||
|
"verbose_name_plural": "Parameter Templates",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -61,6 +61,48 @@ def reverse_update_parameter(apps, schema_editor):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def update_category_parameters(apps, schema_editor):
|
||||||
|
"""Copy the 'part_template' field to the new 'template' field."""
|
||||||
|
|
||||||
|
PartCategoryParameterTemplate = apps.get_model("part", "PartCategoryParameterTemplate")
|
||||||
|
|
||||||
|
category_parameters_to_update = []
|
||||||
|
|
||||||
|
for cat_param in PartCategoryParameterTemplate.objects.all():
|
||||||
|
cat_param.template = cat_param.part_template
|
||||||
|
category_parameters_to_update.append(cat_param)
|
||||||
|
|
||||||
|
if len(category_parameters_to_update) > 0:
|
||||||
|
|
||||||
|
print(f"Updating {len(category_parameters_to_update)} PartCategoryParameterTemplate records.")
|
||||||
|
|
||||||
|
PartCategoryParameterTemplate.objects.bulk_update(
|
||||||
|
category_parameters_to_update,
|
||||||
|
fields=["template"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def reverse_update_category_parameters(apps, schema_editor):
|
||||||
|
"""Copy the 'template' field back to the 'part_template' field."""
|
||||||
|
|
||||||
|
PartCategoryParameterTemplate = apps.get_model("part", "PartCategoryParameterTemplate")
|
||||||
|
|
||||||
|
category_parameters_to_update = []
|
||||||
|
|
||||||
|
for cat_param in PartCategoryParameterTemplate.objects.all():
|
||||||
|
cat_param.part_template = cat_param.template
|
||||||
|
category_parameters_to_update.append(cat_param)
|
||||||
|
|
||||||
|
if len(category_parameters_to_update) > 0:
|
||||||
|
|
||||||
|
print(f"Reversing update of {len(category_parameters_to_update)} PartCategoryParameterTemplate records.")
|
||||||
|
|
||||||
|
PartCategoryParameterTemplate.objects.bulk_update(
|
||||||
|
category_parameters_to_update,
|
||||||
|
fields=["part_template"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
"""Data migration for making the PartParameterTemplate and PartParameter models generic.
|
"""Data migration for making the PartParameterTemplate and PartParameter models generic.
|
||||||
|
|
||||||
@@ -126,5 +168,49 @@ class Migration(migrations.Migration):
|
|||||||
update_parameter,
|
update_parameter,
|
||||||
reverse_code=reverse_update_parameter,
|
reverse_code=reverse_update_parameter,
|
||||||
),
|
),
|
||||||
|
# Add a new "template" field to the PartCategoryParameterTemplate model
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="partcategoryparametertemplate",
|
||||||
|
name="template",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=deletion.CASCADE,
|
||||||
|
related_name="part_categories",
|
||||||
|
to="common.parametertemplate",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
# Remove unique constraint on PartCategoryParameterTemplate model
|
||||||
|
migrations.RemoveConstraint(
|
||||||
|
model_name="partcategoryparametertemplate",
|
||||||
|
name="unique_category_parameter_template_pair",
|
||||||
|
),
|
||||||
|
# Perform data migration for the PartCategoryParameterTemplate model
|
||||||
|
migrations.RunPython(
|
||||||
|
update_category_parameters,
|
||||||
|
reverse_code=reverse_update_category_parameters,
|
||||||
|
),
|
||||||
|
# Remove the obsolete "part_template" field from the PartCategoryParameterTemplate model
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="partcategoryparametertemplate",
|
||||||
|
name="parameter_template",
|
||||||
|
),
|
||||||
|
# Remove nullable attribute from the new 'template' field
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="partcategoryparametertemplate",
|
||||||
|
name="template",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
on_delete=deletion.CASCADE,
|
||||||
|
related_name="part_categories",
|
||||||
|
to="common.parametertemplate",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
# Update uniqueness constraint on PartCategoryParameterTemplate model
|
||||||
|
migrations.AddConstraint(
|
||||||
|
model_name="partcategoryparametertemplate",
|
||||||
|
constraint=models.UniqueConstraint(
|
||||||
|
fields=("category", "template"),
|
||||||
|
name="unique_category_parameter_pair",
|
||||||
|
),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Generated by Django 5.2.8 on 2025-12-03 12:00
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("part", "0145_auto_20251203_1120"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="partparametertemplate",
|
||||||
|
name="model_type",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="partparametertemplate",
|
||||||
|
name="selectionlist",
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name="PartParameter",
|
||||||
|
options={
|
||||||
|
"managed": False,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name="PartParameterTemplate",
|
||||||
|
options={
|
||||||
|
"managed": False,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user