Opened 5 years ago

Closed 3 years ago

#13299 closed Bug (duplicate)

Handicapped objects passed to models signals during loaddata

Reported by: patrys Owned by: nobody
Component: Documentation Version: 1.2-beta
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


The documentation:

...states that actual model instances are to be expected in post_save and pre_save signals.

This is not the case during loaddata. Models that use natural python inheritance (not proxy or abstract) are passed as handicapped instances that only have their own fields filled. This breaks signals that try to access any of the fields of the parent model. This happens because loaddata passes raw=True to the save method.

Consider the following:

class Foo(models.Model):
    foo_field = models.IntegerField(default=0)

class Bar(Foo):
    bar_field = models.IntegerField(default=0)

During loaddata the instance is passed as follows: = None
instance.foo_field = 0
instance.bar_field = 3


instance.foo_ptr_id = 1 = 1
instance.foo_ptr.foo_field = 2

I can think of three solutions:

  1. document it throughly and suggest doing something like:
    if not instance = instance.__class__.objects.get(
  1. make save_base reconstruct the object before calling signals
  1. ignore signals at all during raw object saves

Change History (8)

comment:1 Changed 5 years ago by patrys

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Ok, after consulting current trunk I see that raw kwarg is already being passed to the signal so I guess this is a documentation request.

Maybe something like:

There are some rare cases (for example during fixture loading) when your post_save and pre_save signal handlers receive a "raw" instance. This is signalled by passing True for the raw keyword argument. "Raw" instances do not contain any fields inherited from the parent model. If your application relies on model inheritance, make sure you take this into account. You can get a regular instance by using code below:

if raw:
    instance = instance.__class__._default_manager.get(

comment:2 Changed 5 years ago by russellm

  • Component changed from Uncategorized to Documentation
  • Triage Stage changed from Unreviewed to Accepted

The issue is that when you call loaddata, we are specifically saving only the attributes that are local to the model; if we don't do this, we get a bunch of extra objects created up the inheritance hierarchy. This is what the raw save does. As a consequence of this, we don't actually have access to the values for the parent fields at time of save.

I think you're right that this may need to be a documentation fix; doing the database lookup to populate the parent fields will be expensive for anyone that doesn't need it.

comment:3 Changed 5 years ago by patrys

Yes, I understand why parent object data is not available when loading a fixture and agree that doing an extra select for each insert is not a good idea.

Documenting raw=True would also let people skip signals during loading of fixtures. This might be the desired behavior if the fixture also contains objects normally created by post_save.

comment:4 Changed 5 years ago by julien

  • Severity set to Normal
  • Type set to Bug

comment:5 Changed 4 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:6 Changed 4 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:7 Changed 3 years ago by julien

See also #8399 which suggests adding a new pre_loaddata signal.

comment:8 Changed 3 years ago by timo

  • Resolution set to duplicate
  • Status changed from new to closed

The documentation update is addressed in the patch for #20136.

Note: See TracTickets for help on using tickets.
Back to Top