mirror of
https://github.com/inventree/InvenTree.git
synced 2026-03-15 08:33:42 +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):
|
||||
"""Data migration for making the PartParameterTemplate and PartParameter models generic.
|
||||
|
||||
@@ -126,5 +168,49 @@ class Migration(migrations.Migration):
|
||||
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