Ticket #3215: 3215.patch

File 3215.patch, 3.4 KB (added by russellm, 8 years ago)

Full patch (including tests) for deleting generic related objects

  • django/db/models/query.py

     
    11from django.db import backend, connection, transaction
    22from django.db.models.fields import DateField, FieldDoesNotExist
     3from django.db.models.fields.generic import GenericRelation
    34from django.db.models import signals
    45from django.dispatch import dispatcher
    56from django.utils.datastructures import SortedDict
     
    986987                        ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
    987988                    pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
    988989        for f in cls._meta.many_to_many:
     990            if isinstance(f, GenericRelation):
     991                from django.contrib.contenttypes.models import ContentType
     992                query_extra = 'AND %s=%%s' % f.rel.to._meta.get_field(f.content_type_field_name).column
     993                args_extra = [ContentType.objects.get_for_model(cls).id]
     994            else:
     995                query_extra = ''
     996                args_extra = []
    989997            for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
    990                 cursor.execute("DELETE FROM %s WHERE %s IN (%s)" % \
     998                cursor.execute(("DELETE FROM %s WHERE %s IN (%s)" % \
    991999                    (qn(f.m2m_db_table()), qn(f.m2m_column_name()),
    992                     ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]])),
    993                     pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
     1000                    ','.join(['%s' for pk in pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]]))) + query_extra,
     1001                    pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE] + args_extra)
    9941002        for field in cls._meta.fields:
    9951003            if field.rel and field.null and field.rel.to in seen_objs:
    9961004                for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
  • tests/modeltests/generic_relations/models.py

     
    105105[<TaggedItem: shiny>]
    106106>>> TaggedItem.objects.filter(content_type__pk=ctype.id, object_id=quartz.id)
    107107[<TaggedItem: clearish>]
     108
     109# If you delete an object with an explicit Generic relation, the related
     110# objects are deleted when the source object is deleted.
     111>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()]
     112[('clearish', <ContentType: mineral>, 1), ('fatty', <ContentType: vegetable>, 2), ('hairy', <ContentType: animal>, 1), ('salty', <ContentType: vegetable>, 2), ('shiny', <ContentType: animal>, 2), ('yellow', <ContentType: animal>, 1)]
     113
     114>>> lion.delete()
     115>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()]
     116[('clearish', <ContentType: mineral>, 1), ('fatty', <ContentType: vegetable>, 2), ('salty', <ContentType: vegetable>, 2), ('shiny', <ContentType: animal>, 2)]
     117
     118# If Generic Relation is not explicitly defined, any related objects
     119# remain after deletion of the source object.
     120>>> quartz.delete()
     121>>> [(t.tag, t.content_type, t.object_id) for t in TaggedItem.objects.all()]
     122[('clearish', <ContentType: mineral>, 1), ('fatty', <ContentType: vegetable>, 2), ('salty', <ContentType: vegetable>, 2), ('shiny', <ContentType: animal>, 2)]
     123
    108124"""}
Back to Top