django-model-utils icon indicating copy to clipboard operation
django-model-utils copied to clipboard

bulk deletion of subclass objects not working

Open benwhalley opened this issue 13 years ago • 8 comments

If I create a series of models roughly like this:

class A(PolymorphicModel):
some fields ...

class B(A):
# no extra fields... just new methods

class C(A):
# no extra fields... just new methods
....

then create some objects:

B().save()
C().save()

and then try and delete them:

A.objects.all().delete()

then I get an error something like "'C' object has no attribute 'b_ptr'"

Whereas if I delete them individually:

[i.delete() for i in A.objects.all()] 
>[None, None]

then all is fine. I'm not sure if this is a bug or a feature, but it's frustrating because I'm going to have to override the admin to make deletion of inline objects work (I'm using B and C only to override methods on A, no additional fields are stored).

benwhalley avatar Apr 06 '11 08:04 benwhalley

I'm not sure what code this applies to, since there is no PolymorphicModel in django-model-utils and never has been.

carljm avatar Apr 13 '12 23:04 carljm

I am experiencing exactly this issue. When I define a custom Model Manager for my model that returns a filtered queryset I get pointer errors when I try to delete objects.

class AssetAbstract(models.Model):
...
    objects = PublishedAssetInheritanceObjectManager()

class PublishedAssetInheritanceObjectManager(InheritanceManagerMixin, models.Manager):
    def get_queryset(self):
        return super(PublishedAssetInheritanceObjectManager, self).get_queryset().filter(published=True)

spatialbits avatar Jun 30 '16 23:06 spatialbits

@carljm hey is this issue reopenable?

spatialbits avatar Jul 14 '16 14:07 spatialbits

@benwhalley, so 5 years later I run into the same issue. There wouldn't be any chance that A) you resolved it and B) you remember what you did 5 years ago?

spatialbits avatar Jul 14 '16 16:07 spatialbits

I can't remember the details, but I think came to the conclusion that subclassing non-abstract django models just wasn't worth it...

puterleat avatar Jul 14 '16 20:07 puterleat

@spatialbits when you say "I get pointer errors" - do you mean there's an exception whose stacktrace you could add to this ticket?

kezabelle avatar Jul 15 '16 07:07 kezabelle

yeah sorry, could have added that. I am finding that it's not just on a bulk delete. When I set published to False on a model instance and save it I get an error as per below:

>>> from heritage.models import HeritageAsset, SessionAsset
>>> s = SessionAsset.objects.get(id=5993)
>>> s.published=False
>>> s.save()

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/models/base.py", line 734, in save
    force_update=force_update, update_fields=update_fields)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/models/base.py", line 761, in save_base
    self._save_parents(cls, using, update_fields)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/models/base.py", line 786, in _save_parents
    self._save_table(cls=parent, using=using, update_fields=update_fields)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/models/base.py", line 846, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/models/base.py", line 885, in _do_insert
    using=using, raw=raw)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/models/query.py", line 920, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/models/sql/compiler.py", line 974, in execute_sql
    cursor.execute(sql, params)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/utils.py", line 98, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/utils/six.py", line 658, in reraise
    raise value.with_traceback(tb)
  File "/data/projects/overview-env/lib/python3.4/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: duplicate key value violates unique constraint "heritage_heritageasset_pkey"
DETAIL:  Key (secureasset_ptr_id)=(5993) already exists.

Model Definitions:

class AssetAbstract(models.Model):
    name = models.CharField(max_length=100, blank=False, null=False)
    published = models.BooleanField(default=True)

    objects = PublishedAssetInheritanceObjectManager()
    admin_objects = InheritanceManager()

    class Meta:
        abstract = True

class SecureAsset(AssetAbstract):
    file = models.FileField()
    class Meta:
        permissions = (
            ("view_secureasset", "Can view secure asset"),
        )

class HeritageAsset(SecureAsset):
    @property
    def storage_string(self):
        return "heritage_assets"

class SessionAsset(HeritageAsset):
    session = models.ForeignKey(Session)

And the object manager as posted above:

class PublishedAssetInheritanceObjectManager(InheritanceManagerMixin, models.Manager):
    def get_queryset(self):
        return super(PublishedAssetInheritanceObjectManager, self).get_queryset().filter(published=True)

spatialbits avatar Jul 15 '16 15:07 spatialbits

@spatialbits From what I figured, the InheritanceManager can only be used when dealing with non-abstract models. (Since it uses the one-to-one field that is not there if you do abstract inheritance.)

Eraldo avatar Feb 28 '23 11:02 Eraldo