Ticket #28099: delete_on_update_bug.diff

File delete_on_update_bug.diff, 4.8 KB (added by milosu, 7 years ago)

code to reproduce the bug

  • (a) a/django/db/models/deletion.py.orig vs. (b) b/django/db/models/deletion.py

    a b  
    287287            # update fields
    288288            for model, instances_for_fieldvalues in six.iteritems(self.field_updates):
    289289                query = sql.UpdateQuery(model)
    290                 for (field, value), instances in six.iteritems(instances_for_fieldvalues):
     290                items = instances_for_fieldvalues.items()
     291                import random
     292                random.shuffle(items)
     293                items = OrderedDict(items)
     294                for (field, value), instances in six.iteritems(items):
     295                    print field.name, value, instances
    291296                    query.update_batch([obj.pk for obj in instances],
    292297                                       {field.name: value}, self.using)
    293298
  • tests/delete_regress/models.py

    diff --git a/tests/delete_regress/models.py b/tests/delete_regress/models.py
    index f0145de..1e6da6b 100644
    a b class OrderedPerson(models.Model):  
    139139
    140140    class Meta:
    141141        ordering = ['name']
     142
     143def organization_on_delete(collector, field, sub_objs, using):
     144    deleted_objs = sub_objs.filter(report__isnull=True)
     145    ignored_objs = sub_objs.filter(report__isnull=False)
     146    collector.add_field_update(field, None, ignored_objs)
     147    models.CASCADE(collector, field, deleted_objs, using)
     148   
     149
     150class Organization(models.Model):
     151    name = models.CharField(max_length=255)
     152   
     153class Report(models.Model):
     154    name = models.CharField(max_length=255)
     155   
     156class ThreatenedOrganization(models.Model):
     157    organization = models.ForeignKey(Organization, null=True, blank=True,
     158                                     on_delete=organization_on_delete)
     159    organization_name = models.CharField(max_length=255)
     160    report = models.ForeignKey(Report, null=True, blank=True)
     161
     162    def __unicode__(self):
     163        if self.report_id:
     164            return 'reported threatened org'
     165        return 'threatened org'
     166   
     167class CostClaim(models.Model):
     168    organization = models.ForeignKey(Organization, null=True, blank=True,
     169                                     on_delete=organization_on_delete)
     170    organization_name = models.CharField(max_length=255)
     171    report = models.ForeignKey(Report, null=True, blank=True)
     172    threatened = models.ForeignKey(ThreatenedOrganization, null=True, blank=True,
     173                                   on_delete=models.SET_NULL)
     174
     175    def __unicode__(self):
     176        if self.report_id:
     177            return 'reported cost claim'
     178        return 'cost claim'
     179   
  • tests/delete_regress/tests.py

    diff --git a/tests/delete_regress/tests.py b/tests/delete_regress/tests.py
    index 7472731..01257ba 100644
    a b from .models import (  
    77    Award, AwardNote, Book, Child, Eaten, Email, File, Food, FooFile,
    88    FooFileProxy, FooImage, FooPhoto, House, Image, Item, Location, Login,
    99    OrderedPerson, OrgUnit, Person, Photo, PlayedWith, PlayedWithNote, Policy,
    10     Researcher, Toy, Version,
     10    Researcher, Toy, Version, Organization, Report, ThreatenedOrganization,
     11    CostClaim
    1112)
    1213
    1314
    class OrderedDeleteTests(TestCase):  
    343344        OrderedPerson.objects.create(name='Bob', lives_in=h)
    344345        OrderedPerson.objects.filter(lives_in__address='Foo').delete()
    345346        self.assertEqual(OrderedPerson.objects.count(), 0)
     347
     348class CollectorUpdateTests(TestCase):
     349    def test_delete_with_custom_handlers(self):
     350
     351        org, _ = Organization.objects.get_or_create(name="test org")
     352
     353        t_org, _ = ThreatenedOrganization.objects.get_or_create(
     354            organization=org, organization_name="test org",
     355            report=None)
     356
     357        cost_claim, _ = CostClaim.objects.get_or_create(
     358            organization=org, organization_name="test org",
     359            threatened=t_org, report=None)
     360
     361        report, _ = Report.objects.get_or_create(name="test report")
     362
     363        t_org_in_report, _ = ThreatenedOrganization.objects.get_or_create(
     364            organization=org, organization_name="test org",
     365            report=report)
     366
     367        cost_claim_in_report, _ = CostClaim.objects.get_or_create(
     368            organization=org, organization_name="test org",
     369            threatened=t_org_in_report, report=report)
     370
     371        org.delete()
     372
     373        try:
     374            cost_claim = CostClaim.objects.get(id = cost_claim.pk)
     375            self.assertTrue(False)
     376        except CostClaim.DoesNotExist:
     377            self.assertTrue(True)
     378
     379        cost_claim_in_report = CostClaim.objects.get(
     380            id = cost_claim_in_report.pk)
     381        self.assertEqual(cost_claim_in_report.threatened_id, t_org_in_report.pk)
     382        self.assertEqual(cost_claim_in_report.report_id, report.pk)
     383        self.assertEqual(cost_claim_in_report.organization_id, None)
Back to Top