kopia lustrzana https://github.com/wagtail/wagtail
Set blank=True on current_task_state, and address issue with MySQL backend not recogning conditional unique 'one in progress workflow' constraint by adding an additional check in pre-save validation.
rodzic
514bc7de20
commit
8664d7cea7
|
@ -1,4 +1,4 @@
|
|||
# Generated by Django 3.0.3 on 2020-02-17 10:19
|
||||
# Generated by Django 3.0.3 on 2020-02-18 15:33
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
@ -10,9 +10,9 @@ import wagtail.core.models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
('wagtailcore', '0046_site_name_remove_null'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('auth', '0011_update_proxy_permissions'),
|
||||
]
|
||||
|
||||
|
@ -76,7 +76,7 @@ class Migration(migrations.Migration):
|
|||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('status', models.CharField(choices=[('in_progress', 'In progress'), ('approved', 'Approved'), ('rejected', 'Rejected'), ('cancelled', 'Cancelled')], default='in_progress', max_length=50, verbose_name='status')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='created at')),
|
||||
('current_task_state', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='wagtailcore.TaskState', verbose_name='current task state')),
|
||||
('current_task_state', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='wagtailcore.TaskState', verbose_name='current task state')),
|
||||
('page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='workflow_states', to='wagtailcore.Page', verbose_name='page')),
|
||||
('requested_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='requested_workflows', to=settings.AUTH_USER_MODEL, verbose_name='requested by')),
|
||||
('workflow', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='workflow_states', to='wagtailcore.Workflow', verbose_name='workflow')),
|
||||
|
|
|
@ -2785,12 +2785,22 @@ class WorkflowState(models.Model):
|
|||
editable=True,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='requested_workflows')
|
||||
current_task_state = models.OneToOneField('TaskState', on_delete=models.SET_NULL, null=True, blank=False,
|
||||
current_task_state = models.OneToOneField('TaskState', on_delete=models.SET_NULL, null=True, blank=True,
|
||||
verbose_name=_("current task state"))
|
||||
|
||||
# allows a custom function to be called on finishing the Workflow successfully.
|
||||
on_finish = import_string(getattr(settings, 'WAGTAIL_FINISH_WORKFLOW_ACTION', 'wagtail.core.workflows.publish_workflow_state'))
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
# The unique constraint is conditional, and so not supported on the MySQL backend - so an additional check is done here
|
||||
if WorkflowState.objects.filter(status=self.STATUS_IN_PROGRESS, page=self.page).exclude(pk=self.pk).exists():
|
||||
raise ValidationError(_('There may only be one in progress workflow state per page.'))
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.full_clean()
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return _("Workflow '{0}' on Page '{1}': {2}").format(self.workflow, self.page, self.status)
|
||||
|
||||
|
@ -2884,7 +2894,7 @@ class WorkflowState(models.Model):
|
|||
class Meta:
|
||||
verbose_name = _('Workflow state')
|
||||
verbose_name_plural = _('Workflow states')
|
||||
# prevent multiple STATUS_IN_PROGRESS workflows for the same page
|
||||
# prevent multiple STATUS_IN_PROGRESS workflows for the same page. This is not supported by MySQL, so is checked additionally on save.
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=['page'], condition=Q(status='in_progress'), name='unique_in_progress_workflow')
|
||||
]
|
||||
|
|
|
@ -3,6 +3,7 @@ import datetime
|
|||
import pytz
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import Group
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.utils import IntegrityError
|
||||
from django.test import TestCase, override_settings
|
||||
|
||||
|
@ -115,7 +116,7 @@ class TestWorkflows(TestCase):
|
|||
def test_error_when_starting_multiple_in_progress_workflows(self):
|
||||
# test trying to start multiple status='in_progress' workflows on a single page will trigger an IntegrityError
|
||||
self.start_workflow_on_homepage()
|
||||
with self.assertRaises(IntegrityError):
|
||||
with self.assertRaises((IntegrityError, ValidationError)):
|
||||
self.start_workflow_on_homepage()
|
||||
|
||||
@freeze_time("2017-01-01 12:00:00")
|
||||
|
|
Ładowanie…
Reference in New Issue