change model: discarded_by instead of deletes_change and reset updates

This commit is contained in:
Laura Klünder 2017-06-20 11:43:05 +02:00
parent 86511ceb93
commit 2ee650d6a4
2 changed files with 47 additions and 40 deletions

View file

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-06-20 09:34
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('editor', '0003_auto_20170618_1942'),
]
operations = [
migrations.RemoveField(
model_name='change',
name='deletes_change',
),
migrations.AddField(
model_name='change',
name='discarded_by',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='discards', to='editor.Change', verbose_name='discarded by other change'),
),
migrations.AlterField(
model_name='change',
name='action',
field=models.CharField(choices=[('create', 'create object'), ('delete', 'delete object'), ('update', 'update attribute'), ('m2m_add', 'add many to many relation'), ('m2m_remove', 'add many to many relation')], max_length=16, verbose_name='action'),
),
migrations.AlterField(
model_name='change',
name='model_name',
field=models.CharField(max_length=50, verbose_name='model name'),
),
]

View file

@ -4,7 +4,6 @@ from collections import OrderedDict
from django.apps import apps from django.apps import apps
from django.conf import settings from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.db import models from django.db import models
from django.db.models import Q from django.db.models import Q
from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor, ManyToManyDescriptor from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor, ManyToManyDescriptor
@ -87,11 +86,17 @@ class ChangeSet(models.Model):
if change.existing_object_pk is None: if change.existing_object_pk is None:
if change.action == 'update': if change.action == 'update':
self.created_objects[model][change.created_object_id][name] = value if value is None:
self.created_objects[model][change.created_object_id].pop(name)
else:
self.created_objects[model][change.created_object_id][name] = value
return return
if change.action == 'update': if change.action == 'update':
self.updated_existing.setdefault(model, {}).setdefault(pk, {})[name] = value if value is None:
self.updated_existing.setdefault(model, {}).setdefault(pk, {}).pop(name)
else:
self.updated_existing.setdefault(model, {}).setdefault(pk, {})[name] = value
def get_changed_values(self, model, name): def get_changed_values(self, model, name):
r = tuple((pk, values[name]) for pk, values in self.updated_existing.get(model, {}).items() if name in values) r = tuple((pk, values[name]) for pk, values in self.updated_existing.get(model, {}).items() if name in values)
@ -305,7 +310,6 @@ class ChangeSet(models.Model):
class Change(models.Model): class Change(models.Model):
ACTIONS = ( ACTIONS = (
('delchange', _('delete change')),
('create', _('create object')), ('create', _('create object')),
('delete', _('delete object')), ('delete', _('delete object')),
('update', _('update attribute')), ('update', _('update attribute')),
@ -316,9 +320,9 @@ class Change(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, verbose_name=_('Author')) author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.PROTECT, verbose_name=_('Author'))
created = models.DateTimeField(auto_now_add=True, verbose_name=_('created')) created = models.DateTimeField(auto_now_add=True, verbose_name=_('created'))
action = models.CharField(max_length=16, choices=ACTIONS, verbose_name=_('action')) action = models.CharField(max_length=16, choices=ACTIONS, verbose_name=_('action'))
deletes_change = models.OneToOneField('Change', null=True, on_delete=models.CASCADE, related_name='deleted_by', discarded_by = models.OneToOneField('Change', null=True, on_delete=models.CASCADE, related_name='discards',
verbose_name=_('deletes change')) verbose_name=_('discarded by other change'))
model_name = models.CharField(max_length=50, null=True, verbose_name=_('model name')) model_name = models.CharField(max_length=50, verbose_name=_('model name'))
existing_object_pk = models.PositiveIntegerField(null=True, verbose_name=_('id of existing object')) existing_object_pk = models.PositiveIntegerField(null=True, verbose_name=_('id of existing object'))
created_object = models.ForeignKey('Change', null=True, on_delete=models.CASCADE, related_name='changed_by', created_object = models.ForeignKey('Change', null=True, on_delete=models.CASCADE, related_name='changed_by',
verbose_name=_('changed object')) verbose_name=_('changed object'))
@ -409,41 +413,9 @@ class Change(models.Model):
self.created_object = None self.created_object = None
self._set_object = value self._set_object = value
def clean(self):
if self.action == 'delchange':
if self.deletes_change is None:
raise ValidationError('deletes_change has to be set if action is delchange.')
if self.deletes_change.changeset_id != self.changeset_id:
raise ValidationError('deletes_change refers to a change from a different changeset.')
for field_name in ('model_name', 'existing_object_pk', 'created_object', 'field_name', 'field_value'):
if getattr(self, field_name) is not None:
raise ValidationError('%s must not be set if action is delchange.' % field_name)
return
if self.deletes_change is not None:
raise ValidationError('deletes_change can only be set if action is delchange.')
if self.model_name is None:
raise ValidationError('model_name has to be set if action is not delchange.')
try:
# noinspection PyUnusedLocal
tmp = self.model_class if self.action == 'create' else self.obj # noqa
except TypeError as e:
raise ValidationError(str(e))
except ObjectDoesNotExist:
raise ValidationError('existing object does not exist.')
if self.action in ('create', 'delete'):
for field_name in ('field_name', 'field_value'):
if getattr(self, field_name) is not None:
raise ValidationError('%s must not be set if action is create or delete.' % field_name)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.clean()
if self.pk is not None: if self.pk is not None:
raise TypeError('change objects can not be edited.') raise TypeError('change objects can not be edited (use update to set discarded_by)')
if self.changeset.proposed is not None or self.changeset.applied is not None: if self.changeset.proposed is not None or self.changeset.applied is not None:
raise TypeError('can not add change object to uneditable changeset.') raise TypeError('can not add change object to uneditable changeset.')
super().save(*args, **kwargs) super().save(*args, **kwargs)