Django

Code

Ticket #3215 (closed: fixed)

Opened 2 years ago

Last modified 2 years ago

Deletion of objects with a GenericRelation(X) deletes unrelated X objects with the same object_id!

Reported by: Thomas Steinacher <tom@eggdrop.ch> Assigned to: adrian
Milestone: Component: Database layer (models, ORM)
Version: SVN Keywords:
Cc: peter.kese@ijs.si, gabor@nekomancer.net, larlet@gmail.com Triage Stage: Accepted
Has patch: 1 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

Take a look at the following models file:

from django.db import models
from django.contrib.contenttypes.models import ContentType

class Pointer(models.Model):
    object = models.GenericForeignKey()
    object_id = models.IntegerField()
    content_type = models.ForeignKey(ContentType)

class A(models.Model):
    pointers = models.GenericRelation(Pointer)

class B(models.Model):
    pointers = models.GenericRelation(Pointer)

Let's create an A, a B and two Pointer objects:

In [1]: from test import models
In [2]: a = models.A.objects.create()
In [3]: b = models.B.objects.create()
In [4]: pa = models.Pointer.objects.create(object=a)
In [5]: pb = models.Pointer.objects.create(object=b)
In [6]: [(p.content_type, p.object_id) for p in models.Pointer.objects.all()]
Out[6]: [(<ContentType: a>, 1), (<ContentType: b>, 1)]

Now let's delete ONE object. Notice that ALL pointer objects with this object_id will be deleted. Django DOES NOT take a look at the content_type!

In [7]: a.delete()
In [8]: [(p.content_type, p.object_id) for p in models.Pointer.objects.all()]
Out[8]: []

It looks like the deletion happens in django/db/models/query.py (lines 935-940):

        for f in cls._meta.many_to_many:
            for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
                cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
                    (qn(f.m2m_db_table()), qn(f.m2m_column_name()),
                    ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
                    pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])

The pointer class is in the object's many_to_many list, because I added "pointers = models.GenericRelation?(Pointer)" to the model:

In [9]: models.A._meta.many_to_many[0].m2m_db_table()
Out[9]: 'test_pointer'
In [10]: models.A._meta.many_to_many[0].m2m_column_name()
Out[10]: 'object_id'

I'm using Django SVN (rev 4269).

Attachments

3215-testcase.patch (1.3 kB) - added by russellm on 01/23/07 04:46:52.
Test case for deletion problem
3215.patch (3.4 kB) - added by russellm on 01/23/07 06:54:44.
Full patch (including tests) for deleting generic related objects

Change History

01/01/07 14:02:40 changed by Thomas Steinacher <tom@eggdrop.ch>

Looks like this bug is related to #2749. This should be fixed as soon as possible as it deletes unrelated objects...

01/22/07 08:19:55 changed by peter.kese@ijs.si

  • cc set to peter.kese@ijs.si, .

01/22/07 16:48:38 changed by SmileyChris

  • stage changed from Unreviewed to Accepted.

01/22/07 22:38:46 changed by Alex Dedul

I've already tried to implement fix for this in #3081, but it needs improvements - for now it couples contrib content types to django database wrapper, uses generator expressions available only in python 2.4, lacks tests etc. And if generic relations will be moved to contrib apps too seems like it would be problematic to do proper deletion at all.. But this should be investigated further.

01/23/07 02:06:42 changed by gabor@nekomancer.net

  • cc changed from peter.kese@ijs.si, to peter.kese@ijs.si, gabor@nekomancer.net.

01/23/07 03:06:53 changed by anonymous

  • cc changed from peter.kese@ijs.si, gabor@nekomancer.net to peter.kese@ijs.si, gabor@nekomancer.net, larlet@gmail.com.

01/23/07 04:46:52 changed by russellm

  • attachment 3215-testcase.patch added.

Test case for deletion problem

01/23/07 06:54:44 changed by russellm

  • attachment 3215.patch added.

Full patch (including tests) for deleting generic related objects

01/23/07 07:12:19 changed by russellm

  • has_patch set to 1.
  • version set to SVN.

Patch needs a sanity check from a pair of eyes that aren't jetlagged.

01/25/07 05:36:17 changed by russellm

  • status changed from new to closed.
  • resolution set to fixed.

(In [4428]) Fixed #3215, #3081, #2749 -- Fixed problem with mistaken deletion of objects when a GenericRelation?? is involved. Thanks to Thomas Steinacher for helping to narrow down the problem (#3215), and Alex Dedul (#3081) for the starting point of a working patch.


Add/Change #3215 (Deletion of objects with a GenericRelation(X) deletes unrelated X objects with the same object_id!)




Change Properties
Action