mirror of
https://github.com/inventree/InvenTree.git
synced 2026-09-02 19:08:47 +00:00
Make save method atomic
This commit is contained in:
@@ -121,4 +121,13 @@ class Migration(migrations.Migration):
|
|||||||
related_name='images',
|
related_name='images',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
# Add constraint to ensure that only one 'primary' note exists per model instance
|
||||||
|
migrations.AddConstraint(
|
||||||
|
model_name="note",
|
||||||
|
constraint=models.UniqueConstraint(
|
||||||
|
condition=models.Q(("primary", True)),
|
||||||
|
fields=("model_type", "model_id"),
|
||||||
|
name="unique_primary_note_per_model",
|
||||||
|
),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -3000,21 +3000,34 @@ class Note(
|
|||||||
verbose_name = _('Note')
|
verbose_name = _('Note')
|
||||||
verbose_name_plural = _('Notes')
|
verbose_name_plural = _('Notes')
|
||||||
|
|
||||||
|
constraints = [
|
||||||
|
models.UniqueConstraint(
|
||||||
|
fields=['model_type', 'model_id'],
|
||||||
|
condition=models.Q(primary=True),
|
||||||
|
name='unique_primary_note_per_model',
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_api_url() -> str:
|
def get_api_url() -> str:
|
||||||
"""Return the API URL associated with the Parameter model."""
|
"""Return the API URL associated with the Parameter model."""
|
||||||
return reverse('api-note-list')
|
return reverse('api-note-list')
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
"""Perform custom save checks before saving a Note instance."""
|
"""Perform custom save checks before saving a Note instance."""
|
||||||
self.check_save()
|
self.check_save()
|
||||||
|
|
||||||
others = Note.objects.filter(
|
# Lock sibling notes to serialize concurrent primary-flag updates
|
||||||
model_type=self.model_type, model_id=self.model_id
|
siblings = (
|
||||||
).exclude(pk=self.pk)
|
Note.objects
|
||||||
|
.select_for_update()
|
||||||
|
.filter(model_type=self.model_type, model_id=self.model_id)
|
||||||
|
.exclude(pk=self.pk)
|
||||||
|
)
|
||||||
|
|
||||||
# If this is the *only* note for this model instance, then set it as the primary note
|
# If this is the *only* note for this model instance, then set it as the primary note
|
||||||
if not others.exists():
|
if not siblings.exists():
|
||||||
self.primary = True
|
self.primary = True
|
||||||
|
|
||||||
self.clean()
|
self.clean()
|
||||||
@@ -3023,9 +3036,7 @@ class Note(
|
|||||||
|
|
||||||
# Once this note is saved, mark other notes as non-primary
|
# Once this note is saved, mark other notes as non-primary
|
||||||
if self.primary:
|
if self.primary:
|
||||||
Note.objects.filter(
|
siblings.update(primary=False)
|
||||||
model_type=self.model_type, model_id=self.model_id
|
|
||||||
).exclude(pk=self.pk).update(primary=False)
|
|
||||||
|
|
||||||
self.cleanup_images()
|
self.cleanup_images()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user