import json import logging from django.core import serializers from django.db import models from django.db.models import JSONField from django.utils.translation import gettext_lazy as _ logger = logging.getLogger(__name__) class AsyncMigrationStatus(models.Model): meta = JSONField( 'meta', null=True, default=dict, help_text='Meta is for any params for migrations, e.g.: project, filter or error message.', ) project = models.ForeignKey( 'projects.Project', related_name='asyncmigrationstatus', on_delete=models.CASCADE, null=True, help_text='Project ID for this migration', ) name = models.TextField('migration_name', help_text='Migration name') STATUS_SCHEDULED = 'SCHEDULED' STATUS_STARTED = 'STARTED' STATUS_IN_PROGRESS = 'IN PROGRESS' STATUS_FINISHED = 'FINISHED' STATUS_ERROR = 'ERROR' STATUS_CHOICES = ( (STATUS_SCHEDULED, 'Migration is scheduled but not yet started.'), (STATUS_STARTED, 'Migration is started or queued.'), (STATUS_IN_PROGRESS, 'Migration is in progress. Check meta for job_id or status.'), (STATUS_FINISHED, 'Migration completed successfully.'), (STATUS_ERROR, 'Migration completed with errors. Check meta for more info.'), ) status = models.CharField(max_length=100, choices=STATUS_CHOICES, null=True, default=None) created_at = models.DateTimeField(_('created at'), auto_now_add=True, help_text='Creation time') updated_at = models.DateTimeField(_('updated at'), auto_now=True, help_text='Last updated time') def __str__(self): return f'(id={self.id}) ' + self.name + (' at project ' + str(self.project) if self.project else '') class DeletedRow(models.Model): """ Model to store deleted rows of other models. Useful for using as backup for deleted rows, in case we need to restore them. """ model = models.CharField(max_length=1024) # tasks.task, projects.project, etc. row_id = models.IntegerField(null=True) # primary key of the deleted row. task.id, project.id, etc. data = JSONField(null=True, blank=True) # serialized json of the deleted row. reason = models.TextField(null=True, blank=True) # reason for deletion. created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) # optional fields for searching purposes organization_id = models.IntegerField(null=True, blank=True) project_id = models.IntegerField(null=True, blank=True) user_id = models.IntegerField(null=True, blank=True) @classmethod def serialize_and_create(cls, model, **kwargs) -> 'DeletedRow': data = json.loads(serializers.serialize('json', [model]))[0] model = data['model'] row_id = int(data['pk']) return cls.objects.create(model=model, row_id=row_id, data=data, **kwargs) @classmethod def bulk_serialize_and_create(cls, queryset, **kwargs) -> list['DeletedRow']: serialized_data = json.loads(serializers.serialize('json', queryset)) bulk_objects = [] for data in serialized_data: model = data['model'] row_id = int(data['pk']) bulk_objects.append(cls(model=model, row_id=row_id, data=data, **kwargs)) return cls.objects.bulk_create(bulk_objects)