Opened 15 years ago
Closed 12 years ago
#13299 closed Bug (duplicate)
Handicapped objects passed to models signals during loaddata
Reported by: | Patryk Zawadzki | 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 |
Description
The documentation:
http://docs.djangoproject.com/en/1.1/ref/signals/#django.db.models.signals.post_save
...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:
instance.id = None instance.foo_field = 0 instance.bar_field = 3
While...
instance.foo_ptr_id = 1 instance.foo_ptr.id = 1 instance.foo_ptr.foo_field = 2
I can think of three solutions:
- document it throughly and suggest doing something like:
if not instance.id: instance = instance.__class__.objects.get(id=instance.pk)
- make
save_base
reconstruct the object before calling signals
- ignore signals at all during raw object saves
Change History (8)
comment:1 by , 15 years ago
comment:2 by , 15 years ago
Component: | Uncategorized → Documentation |
---|---|
Triage Stage: | Unreviewed → 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 by , 15 years ago
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 by , 14 years ago
Severity: | → Normal |
---|---|
Type: | → Bug |
comment:8 by , 12 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
The documentation update is addressed in the patch for #20136.
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
andpre_save
signal handlers receive a "raw" instance. This is signalled by passingTrue
for theraw
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: