Skip to content

Commit

Permalink
Fix migration exception handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Bachibouzouk committed Feb 3, 2025
1 parent 3d9fa46 commit afee390
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 28 deletions.
29 changes: 18 additions & 11 deletions app/projects/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,12 @@ def __init__(self, *args, **kwargs):
# set the custom timeseries field for timeseries
# the qs_ts selects timeseries of the corresponding MVS type that either belong to the user or are open source
if "input_timeseries" in self.fields:
self.fields["input_timeseries"] = TimeseriesField(qs_ts=Timeseries.objects.filter(
Q(ts_type=self.asset_type.mvs_type) & (Q(open_source=True) | Q(user=self.user)),
))
self.fields["input_timeseries"] = TimeseriesField(
qs_ts=Timeseries.objects.filter(
Q(ts_type=self.asset_type.mvs_type)
& (Q(open_source=True) | Q(user=self.user)),
)
)

self.fields["inputs"] = forms.CharField(
widget=forms.HiddenInput(), required=False
Expand Down Expand Up @@ -918,23 +921,27 @@ def clean(self):
if input_method == "upload" or input_method == "manual":
# replace the dict with a new timeseries instance
cleaned_data["input_timeseries"] = self.create_timeseries_from_input(
ts_data)
ts_data
)
if input_method == "select":
# return the timeseries instance
timeseries_id = ts_data["input_method"]["extra_info"]
cleaned_data["input_timeseries"] = Timeseries.objects.get(id=timeseries_id)
cleaned_data["input_timeseries"] = Timeseries.objects.get(
id=timeseries_id
)

return cleaned_data

def create_timeseries_from_input(self, input_timeseries):
timeseries_name = input_timeseries["input_method"]["extra_info"]
timeseries_values = input_timeseries["values"]
ts_instance = Timeseries.objects.create(user=self.user,
name=timeseries_name,
ts_type=self.asset_type.mvs_type,
values=timeseries_values,
open_source=False
)
ts_instance = Timeseries.objects.create(
user=self.user,
name=timeseries_name,
ts_type=self.asset_type.mvs_type,
values=timeseries_values,
open_source=False,
)

return ts_instance

Expand Down
34 changes: 19 additions & 15 deletions app/projects/migrations/0023_migrate_timeseries_to_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ def convert_timeseries_to_model(apps, schema_editor):
Forward migration: Convert timeseries_old to Timeseries instance
"""
# Get historical models
Asset = apps.get_model('projects', 'Asset')
Timeseries = apps.get_model('projects', 'Timeseries')
Asset = apps.get_model("projects", "Asset")
Timeseries = apps.get_model("projects", "Timeseries")
db_alias = schema_editor.connection.alias

# Iterate through all assets with timeseries_old data
for asset in Asset.objects.using(db_alias).exclude(Q(input_timeseries_old__isnull=True) | Q(input_timeseries_old=[])):
for asset in Asset.objects.using(db_alias).exclude(
Q(input_timeseries_old__isnull=True) | Q(input_timeseries_old=[])
):
try:
# Calculate end time from asset start date and duration
duration = asset.scenario.evaluated_period
Expand All @@ -31,34 +33,38 @@ def convert_timeseries_to_model(apps, schema_editor):
open_source=False,
start_date=asset.scenario.start_date,
time_step=asset.scenario.time_step,
end_date=end_date
end_date=end_date,
)

# Update asset to point to new timeseries
asset.input_timeseries = timeseries
asset.save()

except Exception as e:
print(f"Error migrating asset {asset.id} timeseries: {str(e)}")
raise e
# print()
raise ValueError(
f"Error migrating asset {asset.id} timeseries: {str(e)}: input_timeseries_old is '{asset.input_timeseries_old}'"
)


def reverse_timeseries_conversion(apps, schema_editor):
"""
Reverse migration: Delete created Timeseries instances and restore old data
"""
Asset = apps.get_model('projects', 'Asset')
Timeseries = apps.get_model('projects', 'Timeseries')
Asset = apps.get_model("projects", "Asset")
Timeseries = apps.get_model("projects", "Timeseries")
db_alias = schema_editor.connection.alias

try:
# Find all timeseries created by this migration
migration_timeseries = Timeseries.objects.using(db_alias).filter(name__contains="_migration")
migration_timeseries = Timeseries.objects.using(db_alias).filter(
name__contains="_migration"
)

# Update assets to remove reference to timeseries
Asset.objects.using(db_alias).filter(input_timeseries__in=migration_timeseries).update(
input_timeseries=None
)
Asset.objects.using(db_alias).filter(
input_timeseries__in=migration_timeseries
).update(input_timeseries=None)

# Delete the timeseries instances
migration_timeseries.delete()
Expand All @@ -75,8 +81,6 @@ class Migration(migrations.Migration):
operations = [
# Run the timeseries migration
migrations.RunPython(
convert_timeseries_to_model,
reverse_timeseries_conversion
convert_timeseries_to_model, reverse_timeseries_conversion
),
]

5 changes: 3 additions & 2 deletions app/projects/models/base_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,6 @@ def set_date_attributes_from_scenario(self):
self.end_date = self.compute_end_date_from_duration()



class AssetType(models.Model):
asset_type = models.CharField(
max_length=30, choices=ASSET_TYPE, null=False, unique=True
Expand Down Expand Up @@ -447,7 +446,9 @@ def save(self, *args, **kwargs):
input_timeseries_old = models.TextField(
null=True, blank=False
) # , validators=[validate_timeseries])
input_timeseries = models.ForeignKey(Timeseries, on_delete=models.CASCADE, null=True, blank=False)
input_timeseries = models.ForeignKey(
Timeseries, on_delete=models.CASCADE, null=True, blank=False
)
crate = models.FloatField(
null=True, blank=False, default=1, validators=[MinValueValidator(0.0)]
)
Expand Down

0 comments on commit afee390

Please sign in to comment.