add ChangeSetUpdate and only save updates if something changed
This commit is contained in:
parent
a03d7cbda9
commit
ef3f4a979d
6 changed files with 120 additions and 8 deletions
69
src/c3nav/editor/migrations/0011_auto_20170704_1640.py
Normal file
69
src/c3nav/editor/migrations/0011_auto_20170704_1640.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.2 on 2017-07-04 16:40
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('editor', '0010_auto_20170704_1431'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ChangeSetUpdate',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('datetime', models.DateTimeField(auto_now_add=True, verbose_name='datetime')),
|
||||
('comment', models.TextField(max_length=1000, null=True)),
|
||||
('state', models.CharField(choices=[('unproposed', 'unproposed'), ('proposed', 'proposed'), ('review', 'in review'), ('rejected', 'rejected'), ('reproposed', 'reproposed'), ('finallyrejected', 'finally rejected'), ('applied', 'accepted')], db_index=True, max_length=20, null=None)),
|
||||
('title', models.CharField(max_length=100, null=True)),
|
||||
('description', models.TextField(max_length=1000, null=True)),
|
||||
('objects_changed', models.BooleanField(default=False)),
|
||||
('assigned_to', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
('author', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Change set update',
|
||||
'verbose_name_plural': 'Change set updates',
|
||||
'ordering': ['datetime', 'pk'],
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='changeset',
|
||||
name='last_update',
|
||||
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now, verbose_name='last update'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='changeset',
|
||||
name='session_id',
|
||||
field=models.CharField(db_index=True, max_length=32, null=True, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='changeset',
|
||||
name='state',
|
||||
field=models.CharField(choices=[('unproposed', 'unproposed'), ('proposed', 'proposed'), ('review', 'in review'), ('rejected', 'rejected'), ('reproposed', 'reproposed'), ('finallyrejected', 'finally rejected'), ('applied', 'accepted')], db_index=True, default='unproposed', max_length=20),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='changesetupdate',
|
||||
name='changeset',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='updates', to='editor.ChangeSet'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='changesetupdate',
|
||||
name='session_user',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='changesetupdate',
|
||||
name='user',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
|
@ -1 +1,3 @@
|
|||
from c3nav.editor.models.changedobject import ChangedObject # noqa
|
||||
from c3nav.editor.models.changeset import ChangeSet # noqa
|
||||
from c3nav.editor.models.changesetupdate import ChangeSetUpdate # noqa
|
||||
|
|
|
@ -182,6 +182,7 @@ class ChangedObject(models.Model):
|
|||
return delete_fields
|
||||
|
||||
def save_instance(self, instance):
|
||||
old_updated_fields = self.updated_fields
|
||||
self.updated_fields = {}
|
||||
for field in self.model_class._meta.get_fields():
|
||||
if not isinstance(field, Field) or field.primary_key:
|
||||
|
@ -204,11 +205,16 @@ class ChangedObject(models.Model):
|
|||
self.updated_fields[field.name] = value
|
||||
|
||||
self.clean_updated_fields()
|
||||
for name, value in self.updated_fields.items():
|
||||
if old_updated_fields.get(name, None) != value:
|
||||
self.changeset._object_changed = True
|
||||
break
|
||||
self.save()
|
||||
if instance.pk is None and self.pk is not None:
|
||||
instance.pk = self.obj_pk
|
||||
|
||||
def mark_deleted(self):
|
||||
self.changeset._object_changed = True
|
||||
self.deleted = True
|
||||
self.save()
|
||||
|
||||
|
@ -237,6 +243,7 @@ class ChangedObject(models.Model):
|
|||
|
||||
if (m2m_added_before != self._m2m_added_cache.get(name, set()) or
|
||||
m2m_removed_before != self._m2m_removed_cache.get(name, set())):
|
||||
self.changeset._object_changed = True
|
||||
self.save()
|
||||
return True
|
||||
return False
|
||||
|
|
|
@ -7,7 +7,6 @@ from django.conf import settings
|
|||
from django.db import models, transaction
|
||||
from django.db.models import Q
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ungettext_lazy
|
||||
|
||||
|
@ -25,16 +24,18 @@ class ChangeSet(models.Model):
|
|||
('proposed', _('proposed')),
|
||||
('review', _('in review')),
|
||||
('rejected', _('rejected')),
|
||||
('reproposed', _('reproposed')),
|
||||
('finallyrejected', _('finally rejected')),
|
||||
('applied', _('accepted')),
|
||||
)
|
||||
created = models.DateTimeField(auto_now_add=True, verbose_name=_('created'))
|
||||
last_change = models.DateTimeField(auto_now_add=True, verbose_name=_('last change'))
|
||||
state = models.CharField(max_length=20, choices=STATES, default='unproposed')
|
||||
last_update = models.DateTimeField(auto_now_add=True, verbose_name=_('last update'))
|
||||
state = models.CharField(max_length=20, db_index=True, choices=STATES, default='unproposed')
|
||||
author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, verbose_name=_('Author'))
|
||||
title = models.CharField(max_length=100, default='', verbose_name=_('Title'))
|
||||
description = models.TextField(max_length=1000, default='', verbose_name=_('Description'))
|
||||
session_id = models.CharField(unique=True, null=True, max_length=32)
|
||||
session_id = models.CharField(unique=True, db_index=True, null=True, max_length=32)
|
||||
assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT,
|
||||
related_name='assigned_changesets', verbose_name=_('assigned to'))
|
||||
|
||||
|
@ -53,7 +54,7 @@ class ChangeSet(models.Model):
|
|||
self.m2m_added = {}
|
||||
self.m2m_removed = {}
|
||||
|
||||
self.last_change_cache = None
|
||||
self._object_changed = False
|
||||
|
||||
"""
|
||||
Get Changesets for Request/Session/User
|
||||
|
@ -278,9 +279,14 @@ class ChangeSet(models.Model):
|
|||
changeset = ChangeSet.objects.select_for_update().get(pk=self.pk)
|
||||
if not changeset.can_edit_changes(request):
|
||||
raise PermissionError
|
||||
self._object_changed = False
|
||||
yield
|
||||
changeset.last_change = timezone.now()
|
||||
changeset.save()
|
||||
if self._object_changed:
|
||||
update = changeset.updates.create(user=request.user if request.user.is_authenticated else None,
|
||||
objects_changed=True)
|
||||
changeset.last_update = update.datetime
|
||||
changeset.last_change = update.datetime
|
||||
changeset.save()
|
||||
else:
|
||||
yield
|
||||
|
||||
|
|
28
src/c3nav/editor/models/changesetupdate.py
Normal file
28
src/c3nav/editor/models/changesetupdate.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from c3nav.editor.models import ChangeSet
|
||||
|
||||
|
||||
class ChangeSetUpdate(models.Model):
|
||||
changeset = models.ForeignKey(ChangeSet, on_delete=models.CASCADE, related_name='updates')
|
||||
datetime = models.DateTimeField(auto_now_add=True, verbose_name=_('datetime'))
|
||||
comment = models.TextField(max_length=1000, null=True)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, related_name='+')
|
||||
|
||||
state = models.CharField(null=None, db_index=True, choices=ChangeSet.STATES, max_length=20)
|
||||
author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, related_name='+')
|
||||
title = models.CharField(max_length=100, null=True)
|
||||
description = models.TextField(max_length=1000, null=True)
|
||||
session_user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, related_name='+')
|
||||
assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, related_name='+')
|
||||
objects_changed = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Change set update')
|
||||
verbose_name_plural = _('Change set updates')
|
||||
ordering = ['datetime', 'pk']
|
||||
|
||||
def __repr__(self):
|
||||
return '<Update #%s on ChangeSet #%s>' % (str(self.pk), str(self.changeset_id))
|
|
@ -23,8 +23,8 @@
|
|||
{% endif %}
|
||||
{% endwith %}
|
||||
<br>
|
||||
{% with datetime=changeset.last_change|date:"DATETIME_FORMAT" %}
|
||||
{% blocktrans %}last change at {{ datetime }}{% endblocktrans %}
|
||||
{% with datetime=changeset.last_update|date:"DATETIME_FORMAT" %}
|
||||
{% blocktrans %}last update at {{ datetime }}{% endblocktrans %}
|
||||
{% endwith %}
|
||||
</p>
|
||||
{% bootstrap_messages %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue