mirror of
https://github.com/inventree/InvenTree.git
synced 2026-03-16 00:50:56 +00:00
Overhaul of migration strategy
- New models simply point to the old database tables - Perform schema and data migrations on the old models first (in the part app) - Swap model references in correct order
This commit is contained in:
@@ -1,256 +0,0 @@
|
||||
# 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",
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,226 +1,248 @@
|
||||
# Generated by Django 4.2.25 on 2025-11-10 10:51
|
||||
# Generated by Django 5.2.8 on 2025-12-03 12:39
|
||||
|
||||
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
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("common", "0039_emailthread_emailmessage"),
|
||||
("part", "0143_alter_part_image")
|
||||
("contenttypes", "0002_remove_content_type_name"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("part", "0144_auto_20251203_1045")
|
||||
]
|
||||
|
||||
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",
|
||||
},
|
||||
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",
|
||||
migrations.SeparateDatabaseAndState(
|
||||
state_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",
|
||||
),
|
||||
),
|
||||
(
|
||||
"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",
|
||||
),
|
||||
),
|
||||
(
|
||||
"enabled",
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
help_text="Is this parameter template enabled?",
|
||||
verbose_name="Enabled",
|
||||
),
|
||||
),
|
||||
(
|
||||
"model_type",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
help_text="Target model type for this parameter template",
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="contenttypes.contenttype",
|
||||
verbose_name="Model type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"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",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Parameter Template",
|
||||
"verbose_name_plural": "Parameter Templates",
|
||||
"db_table": "part_partparametertemplate",
|
||||
},
|
||||
bases=(
|
||||
InvenTree.models.ContentTypeMixin,
|
||||
InvenTree.models.PluginValidationMixin,
|
||||
models.Model,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Parameter",
|
||||
"verbose_name_plural": "Parameters",
|
||||
"unique_together": {("model_type", "model_id", "template")},
|
||||
},
|
||||
bases=(InvenTree.models.PluginValidationMixin, models.Model),
|
||||
database_operations=[],
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name="parameter",
|
||||
index=models.Index(
|
||||
fields=["model_type", "model_id"], name="common_para_model_t_244405_idx"
|
||||
),
|
||||
migrations.SeparateDatabaseAndState(
|
||||
state_operations=[
|
||||
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_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",
|
||||
),
|
||||
),
|
||||
(
|
||||
"model_type",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="contenttypes.contenttype",
|
||||
),
|
||||
),
|
||||
(
|
||||
"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",
|
||||
),
|
||||
),
|
||||
(
|
||||
"template",
|
||||
models.ForeignKey(
|
||||
help_text="Parameter template",
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="parameters",
|
||||
to="common.parametertemplate",
|
||||
verbose_name="Template",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Parameter",
|
||||
"verbose_name_plural": "Parameters",
|
||||
"db_table": "part_partparameter",
|
||||
"indexes": [
|
||||
models.Index(
|
||||
fields=["model_type", "model_id"],
|
||||
name="part_partpa_model_t_198c9d_idx",
|
||||
)
|
||||
],
|
||||
"unique_together": {("model_type", "model_id", "template")},
|
||||
},
|
||||
bases=(
|
||||
InvenTree.models.ContentTypeMixin,
|
||||
InvenTree.models.PluginValidationMixin,
|
||||
models.Model,
|
||||
),
|
||||
),
|
||||
],
|
||||
database_operations=[],
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
# Generated by Django 4.2.25 on 2025-10-28 11:12
|
||||
|
||||
import structlog
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
logger = structlog.get_logger('inventree')
|
||||
|
||||
|
||||
def convert_to_numeric_value(value: str, units: str):
|
||||
"""Convert a value (with units) to a numeric value.
|
||||
|
||||
Defaults to zero if the value cannot be converted.
|
||||
"""
|
||||
|
||||
import InvenTree.conversion
|
||||
|
||||
# Default value is null
|
||||
result = None
|
||||
|
||||
if units:
|
||||
try:
|
||||
result = InvenTree.conversion.convert_physical_value(value, units)
|
||||
result = float(result.magnitude)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
result = float(value)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def update_global_setting(apps, schema_editor):
|
||||
"""Update global setting key from PART_PARAMETER_ENFORCE_UNITS to PARAMETER_ENFORCE_UNITS."""
|
||||
GlobalSetting = apps.get_model("common", "InvenTreeSetting")
|
||||
|
||||
OLD_KEY = 'PART_PARAMETER_ENFORCE_UNITS'
|
||||
NEW_KEY = 'PARAMETER_ENFORCE_UNITS'
|
||||
|
||||
try:
|
||||
setting = GlobalSetting.objects.get(key=OLD_KEY)
|
||||
|
||||
if setting is not None:
|
||||
# Remove any existing new key
|
||||
GlobalSetting.objects.filter(key=NEW_KEY).delete()
|
||||
setting.key = NEW_KEY
|
||||
setting.save()
|
||||
logger.info(f"Updated global setting key from {OLD_KEY} to {NEW_KEY}.")
|
||||
except GlobalSetting.DoesNotExist:
|
||||
logger.info(f"Global setting {OLD_KEY} does not exist; no update needed.")
|
||||
|
||||
|
||||
def remove_existing_parameters(apps, schema_editor):
|
||||
"""Remove any existing Parameter or ParameterTemplate objects from the database."""
|
||||
|
||||
Parameter = apps.get_model("common", "Parameter")
|
||||
ParameterTemplate = apps.get_model("common", "ParameterTemplate")
|
||||
|
||||
n_params = Parameter.objects.count()
|
||||
n_templates = ParameterTemplate.objects.count()
|
||||
|
||||
Parameter.objects.all().delete()
|
||||
ParameterTemplate.objects.all().delete()
|
||||
|
||||
if n_params > 0:
|
||||
logger.info(f"Removed {n_params} existing Parameter instances.")
|
||||
|
||||
if n_templates > 0:
|
||||
logger.info(f"Removed {n_templates} existing ParameterTemplate instances.")
|
||||
|
||||
assert Parameter.objects.count() == 0
|
||||
assert ParameterTemplate.objects.count() == 0
|
||||
|
||||
|
||||
def copy_part_parameters(apps, schema_editor):
|
||||
"""Forward migration: copy from PartParameterTemplate to ParameterTemplate."""
|
||||
|
||||
ContentType = apps.get_model("contenttypes", "ContentType")
|
||||
PartParameterTemplate = apps.get_model("part", "PartParameterTemplate")
|
||||
ParameterTemplate = apps.get_model("common", "ParameterTemplate")
|
||||
PartParameter = apps.get_model("part", "PartParameter")
|
||||
Parameter = apps.get_model("common", "Parameter")
|
||||
|
||||
# First, create a ParameterTemplate instance for each PartParameterTemplate
|
||||
templates = []
|
||||
|
||||
for template in PartParameterTemplate.objects.all():
|
||||
templates.append(ParameterTemplate(
|
||||
name=template.name,
|
||||
description=template.description,
|
||||
units=template.units or '',
|
||||
checkbox=template.checkbox,
|
||||
choices=template.choices,
|
||||
selectionlist=template.selectionlist,
|
||||
model_type=None
|
||||
))
|
||||
|
||||
if len(templates) > 0:
|
||||
ParameterTemplate.objects.bulk_create(templates)
|
||||
logger.info(f"\nMigrated {len(templates)} PartParameterTemplate instances.")
|
||||
|
||||
assert ParameterTemplate.objects.all().count() == len(templates)
|
||||
|
||||
# Next, copy PartParameter instances to Parameter instances
|
||||
parameters = []
|
||||
|
||||
content_type, _created = ContentType.objects.get_or_create(app_label='part', model='part')
|
||||
|
||||
for parameter in PartParameter.objects.all():
|
||||
# Find the corresponding ParameterTemplate
|
||||
template = ParameterTemplate.objects.get(name=parameter.template.name)
|
||||
|
||||
parameters.append(Parameter(
|
||||
template=template,
|
||||
model_type=content_type,
|
||||
model_id=parameter.part.id,
|
||||
data=parameter.data,
|
||||
data_numeric=parameter.data_numeric,
|
||||
note=parameter.note,
|
||||
metadata=parameter.metadata,
|
||||
updated=parameter.updated,
|
||||
updated_by=parameter.updated_by
|
||||
))
|
||||
|
||||
if len(parameters) > 0:
|
||||
Parameter.objects.bulk_create(parameters)
|
||||
logger.info(f"\nMigrated {len(parameters)} PartParameter instances.")
|
||||
|
||||
assert Parameter.objects.filter(model_type=content_type).count() == len(parameters)
|
||||
|
||||
|
||||
def copy_manufacturer_part_parameters(apps, schema_editor):
|
||||
"""Copy ManufacturerPartParameter to Parameter."""
|
||||
|
||||
ManufacturerPartParameter = apps.get_model("company", "ManufacturerPartParameter")
|
||||
Parameter = apps.get_model("common", "Parameter")
|
||||
ParameterTemplate = apps.get_model("common", "ParameterTemplate")
|
||||
ContentType = apps.get_model("contenttypes", "ContentType")
|
||||
parameters = []
|
||||
|
||||
content_type, _created = ContentType.objects.get_or_create(app_label='company', model='manufacturerpart')
|
||||
|
||||
for parameter in ManufacturerPartParameter.objects.all():
|
||||
# Find the corresponding ParameterTemplate
|
||||
template = ParameterTemplate.objects.filter(name=parameter.name).first()
|
||||
|
||||
if not template:
|
||||
# A matching template does not exist - let's create one
|
||||
template = ParameterTemplate.objects.create(
|
||||
name=parameter.name,
|
||||
description='',
|
||||
units=parameter.units or '',
|
||||
model_type=None,
|
||||
checkbox=False
|
||||
)
|
||||
|
||||
parameters.append(Parameter(
|
||||
template=template,
|
||||
model_type=content_type,
|
||||
model_id=parameter.manufacturer_part.id,
|
||||
data=parameter.value,
|
||||
data_numeric=convert_to_numeric_value(parameter.value, parameter.units),
|
||||
))
|
||||
|
||||
if len(parameters) > 0:
|
||||
Parameter.objects.bulk_create(parameters)
|
||||
logger.info(f"\nMigrated {len(parameters)} ManufacturerPartParameter instances.")
|
||||
|
||||
assert Parameter.objects.filter(model_type=content_type).count() == len(parameters)
|
||||
|
||||
|
||||
def update_category_parameters(apps, schema_editor):
|
||||
"""Migration for PartCategoryParameterTemplate.
|
||||
|
||||
Copies the contents of the 'parameter_template' field to the new 'template' field
|
||||
"""
|
||||
|
||||
PartCategoryParameterTemplate = apps.get_model("part", "partcategoryparametertemplate")
|
||||
ParameterTemplate = apps.get_model("common", "parametertemplate")
|
||||
|
||||
to_update = []
|
||||
|
||||
for item in PartCategoryParameterTemplate.objects.all():
|
||||
# Find a matching template
|
||||
item.template = ParameterTemplate.objects.get(
|
||||
name=item.parameter_template.name
|
||||
)
|
||||
|
||||
to_update.append(item)
|
||||
|
||||
if len(to_update) > 0:
|
||||
PartCategoryParameterTemplate.objects.bulk_update(to_update, ['template'])
|
||||
logger.info(f"Updated {len(to_update)} PartCategoryParameterTemplate instances.")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('contenttypes', '__latest__'),
|
||||
("part", "0144_partcategoryparametertemplate_template"),
|
||||
("company", "0076_alter_company_image"),
|
||||
("common", "0040_parametertemplate_parameter"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
update_global_setting,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
migrations.RunPython(
|
||||
remove_existing_parameters,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
migrations.RunPython(
|
||||
copy_part_parameters,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
migrations.RunPython(
|
||||
copy_manufacturer_part_parameters,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
migrations.RunPython(
|
||||
update_category_parameters,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
)
|
||||
]
|
||||
@@ -0,0 +1,107 @@
|
||||
# Generated by Django 5.2.8 on 2025-12-03 12:44
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
def convert_to_numeric_value(value: str, units: str):
|
||||
"""Convert a value (with units) to a numeric value.
|
||||
|
||||
Defaults to zero if the value cannot be converted.
|
||||
"""
|
||||
|
||||
import InvenTree.conversion
|
||||
|
||||
# Default value is null
|
||||
result = None
|
||||
|
||||
if units:
|
||||
try:
|
||||
result = InvenTree.conversion.convert_physical_value(value, units)
|
||||
result = float(result.magnitude)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
result = float(value)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def copy_manufacturer_part_parameters(apps, schema_editor):
|
||||
"""Copy ManufacturerPartParameter to Parameter."""
|
||||
|
||||
ManufacturerPartParameter = apps.get_model("company", "ManufacturerPartParameter")
|
||||
Parameter = apps.get_model("common", "Parameter")
|
||||
ParameterTemplate = apps.get_model("common", "ParameterTemplate")
|
||||
ContentType = apps.get_model("contenttypes", "ContentType")
|
||||
parameters = []
|
||||
|
||||
content_type, _created = ContentType.objects.get_or_create(app_label='company', model='manufacturerpart')
|
||||
|
||||
for parameter in ManufacturerPartParameter.objects.all():
|
||||
# Find the corresponding ParameterTemplate
|
||||
template = ParameterTemplate.objects.filter(name=parameter.name).first()
|
||||
|
||||
if not template:
|
||||
# A matching template does not exist - let's create one
|
||||
template = ParameterTemplate.objects.create(
|
||||
name=parameter.name,
|
||||
description='',
|
||||
units=parameter.units or '',
|
||||
model_type=None,
|
||||
checkbox=False
|
||||
)
|
||||
|
||||
parameters.append(Parameter(
|
||||
template=template,
|
||||
model_type=content_type,
|
||||
model_id=parameter.manufacturer_part.id,
|
||||
data=parameter.value,
|
||||
data_numeric=convert_to_numeric_value(parameter.value, parameter.units),
|
||||
))
|
||||
|
||||
if len(parameters) > 0:
|
||||
Parameter.objects.bulk_create(parameters)
|
||||
print(f"\nMigrated {len(parameters)} ManufacturerPartParameter instances.")
|
||||
|
||||
assert Parameter.objects.filter(model_type=content_type).count() == len(parameters)
|
||||
|
||||
|
||||
def update_global_setting(apps, schema_editor):
|
||||
"""Update global setting key from PART_PARAMETER_ENFORCE_UNITS to PARAMETER_ENFORCE_UNITS."""
|
||||
GlobalSetting = apps.get_model("common", "InvenTreeSetting")
|
||||
|
||||
OLD_KEY = 'PART_PARAMETER_ENFORCE_UNITS'
|
||||
NEW_KEY = 'PARAMETER_ENFORCE_UNITS'
|
||||
|
||||
try:
|
||||
setting = GlobalSetting.objects.get(key=OLD_KEY)
|
||||
|
||||
if setting is not None:
|
||||
# Remove any existing new key
|
||||
GlobalSetting.objects.filter(key=NEW_KEY).delete()
|
||||
setting.key = NEW_KEY
|
||||
setting.save()
|
||||
print(f"Updated global setting key from {OLD_KEY} to {NEW_KEY}.")
|
||||
except GlobalSetting.DoesNotExist:
|
||||
print(f"Global setting {OLD_KEY} does not exist; no update needed.")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
"""Perform data migration for the ManufacturerPartParameter model."""
|
||||
|
||||
dependencies = [
|
||||
("common", "0040_parametertemplate_parameter"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
update_global_setting,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
migrations.RunPython(
|
||||
copy_manufacturer_part_parameters,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
||||
@@ -2387,6 +2387,11 @@ class ParameterTemplate(
|
||||
verbose_name = _('Parameter Template')
|
||||
verbose_name_plural = _('Parameter Templates')
|
||||
|
||||
# Note: Data was migrated from the existing 'part_partparametertemplate' table
|
||||
# Ref: https://github.com/inventree/InvenTree/pull/10699
|
||||
# To avoid data loss, we retain the existing table name
|
||||
db_table = 'part_partparametertemplate'
|
||||
|
||||
class ModelChoices(RenderChoices):
|
||||
"""Model choices for parameters."""
|
||||
|
||||
@@ -2576,9 +2581,13 @@ class Parameter(
|
||||
verbose_name = _('Parameter')
|
||||
verbose_name_plural = _('Parameters')
|
||||
unique_together = [['model_type', 'model_id', 'template']]
|
||||
|
||||
indexes = [models.Index(fields=['model_type', 'model_id'])]
|
||||
|
||||
# Note: Data was migrated from the existing 'part_partparameter' table
|
||||
# Ref: https://github.com/inventree/InvenTree/pull/10699
|
||||
# To avoid data loss, we retain the existing table name
|
||||
db_table = 'part_partparameter'
|
||||
|
||||
class ModelChoices(RenderChoices):
|
||||
"""Model choices for parameters."""
|
||||
|
||||
|
||||
@@ -4,10 +4,15 @@ from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
"""Remove the ManufacturerPartParameter model.
|
||||
|
||||
The data has been migrated to the common.Parameter model in a previous migration.
|
||||
"""
|
||||
|
||||
dependencies = [
|
||||
("company", "0076_alter_company_image"),
|
||||
("common", "0041_auto_20251028_1112"),
|
||||
("common", "0041_auto_20251203_1244"),
|
||||
("part", "0146_auto_20251203_1241")
|
||||
]
|
||||
|
||||
operations = [
|
||||
|
||||
@@ -61,48 +61,6 @@ 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.
|
||||
|
||||
@@ -168,49 +126,32 @@ 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
|
||||
# Update the "model_type" field on the PartParameter model to be non-nullable
|
||||
migrations.AlterField(
|
||||
model_name="partcategoryparametertemplate",
|
||||
name="template",
|
||||
model_name="partparameter",
|
||||
name="model_type",
|
||||
field=models.ForeignKey(
|
||||
on_delete=deletion.CASCADE,
|
||||
related_name="part_categories",
|
||||
to="common.parametertemplate",
|
||||
to="contenttypes.contenttype",
|
||||
),
|
||||
),
|
||||
# Update uniqueness constraint on PartCategoryParameterTemplate model
|
||||
migrations.AddConstraint(
|
||||
model_name="partcategoryparametertemplate",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("category", "template"),
|
||||
name="unique_category_parameter_pair",
|
||||
),
|
||||
# Update the "model_id" field on the PartParameter model to be non-nullable
|
||||
migrations.AlterField(
|
||||
model_name="partparameter",
|
||||
name="model_id",
|
||||
field=models.PositiveIntegerField(
|
||||
help_text="ID of the target model for this parameter",
|
||||
verbose_name="Model ID",
|
||||
)
|
||||
),
|
||||
# Remove the "unique_together" constraint on the PartParameter model
|
||||
migrations.AlterUniqueTogether(
|
||||
name="partparameter",
|
||||
unique_together={('model_type', 'model_id', 'template')},
|
||||
),
|
||||
# Remove the obsolete "part" field from the PartParameter model
|
||||
migrations.RemoveField(
|
||||
model_name="partparameter",
|
||||
name="part",
|
||||
),
|
||||
]
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# Generated by Django 5.2.8 on 2025-11-25 06:19
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("part", "0143_alter_part_image"),
|
||||
("common", "0040_parametertemplate_parameter"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="partcategoryparametertemplate",
|
||||
name="template",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="part_categories",
|
||||
to="common.parametertemplate",
|
||||
),
|
||||
),
|
||||
migrations.RemoveConstraint(
|
||||
model_name="partcategoryparametertemplate",
|
||||
name="unique_category_parameter_template_pair",
|
||||
),
|
||||
]
|
||||
@@ -1,42 +0,0 @@
|
||||
# Generated by Django 5.2.8 on 2025-12-03 11:20
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.db.models import deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("part", "0144_auto_20251203_1045"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
# Update the "model_type" field on the PartParameter model to be non-nullable
|
||||
migrations.AlterField(
|
||||
model_name="partparameter",
|
||||
name="model_type",
|
||||
field=models.ForeignKey(
|
||||
on_delete=deletion.CASCADE,
|
||||
to="contenttypes.contenttype",
|
||||
),
|
||||
),
|
||||
# Update the "model_id" field on the PartParameter model to be non-nullable
|
||||
migrations.AlterField(
|
||||
model_name="partparameter",
|
||||
name="model_id",
|
||||
field=models.PositiveIntegerField(
|
||||
help_text="ID of the target model for this parameter",
|
||||
verbose_name="Model ID",
|
||||
)
|
||||
),
|
||||
# Remove the "unique_together" constraint on the PartParameter model
|
||||
migrations.AlterUniqueTogether(
|
||||
name="partparameter",
|
||||
unique_together={('model_type', 'model_id', 'template')},
|
||||
),
|
||||
# Remove the obsolete "part" field from the PartParameter model
|
||||
migrations.RemoveField(
|
||||
model_name="partparameter",
|
||||
name="part",
|
||||
),
|
||||
]
|
||||
106
src/backend/InvenTree/part/migrations/0145_auto_20251203_1238.py
Normal file
106
src/backend/InvenTree/part/migrations/0145_auto_20251203_1238.py
Normal file
@@ -0,0 +1,106 @@
|
||||
# Generated by Django 5.2.8 on 2025-12-03 12:38
|
||||
|
||||
from django.db import migrations, models
|
||||
from django.db.models import deletion
|
||||
|
||||
|
||||
def update_category_parameters(apps, schema_editor):
|
||||
"""Copy the 'parameter_template' field to the new 'template' field."""
|
||||
|
||||
PartCategoryParameterTemplate = apps.get_model("part", "PartCategoryParameterTemplate")
|
||||
ParameterTemplate = apps.get_model("common", "ParameterTemplate")
|
||||
|
||||
category_parameters_to_update = []
|
||||
|
||||
for cat_param in PartCategoryParameterTemplate.objects.all():
|
||||
template = ParameterTemplate.objects.get(pk=cat_param.parameter_template_id)
|
||||
cat_param.template = 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 'parameter_template' field."""
|
||||
|
||||
PartParameterTemplate = apps.get_model("part", "PartParameterTemplate")
|
||||
PartCategoryParameterTemplate = apps.get_model("part", "PartCategoryParameterTemplate")
|
||||
|
||||
category_parameters_to_update = []
|
||||
|
||||
for cat_param in PartCategoryParameterTemplate.objects.all():
|
||||
template = PartParameterTemplate.objects.get(pk=cat_param.template_id)
|
||||
cat_param.parameter_template = 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=["parameter_template"],
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("part", "0144_auto_20251203_1045"),
|
||||
("common", "0040_parametertemplate_parameter")
|
||||
]
|
||||
|
||||
operations = [
|
||||
# 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",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -1,45 +0,0 @@
|
||||
# Generated by Django 5.2.8 on 2025-11-25 07:01
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("common", "0041_auto_20251028_1112"),
|
||||
("part", "0144_partcategoryparametertemplate_template"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name="partparametertemplate",
|
||||
name="selectionlist",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name="partcategoryparametertemplate",
|
||||
name="parameter_template",
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="partcategoryparametertemplate",
|
||||
name="template",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="part_categories",
|
||||
to="common.parametertemplate",
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name="partcategoryparametertemplate",
|
||||
constraint=models.UniqueConstraint(
|
||||
fields=("category", "template"),
|
||||
name="unique_category_parameter_pair",
|
||||
),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name="PartParameter",
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name="PartParameterTemplate",
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.2.8 on 2025-12-03 12:41
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("part", "0145_auto_20251203_1238"),
|
||||
]
|
||||
|
||||
# Remove the PartParameterTemplate and PartParameter models
|
||||
# Note: We *DO NOT* drop the underlying database tables,
|
||||
# as these are now used by the common.ParameterTemplate and common.Parameter models
|
||||
operations = [
|
||||
migrations.SeparateDatabaseAndState(
|
||||
state_operations=[
|
||||
migrations.DeleteModel(name='PartParameterTemplate'),
|
||||
migrations.DeleteModel(name='PartParameter'),
|
||||
],
|
||||
database_operations=[]
|
||||
),
|
||||
]
|
||||
@@ -1,33 +0,0 @@
|
||||
# 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