Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[1.5.X] Fixed #20136 - Fixed and expanded the docs for loaddata and m…

…odel signals.

Thanks brandon@ and Anssi for the report.

Backport of 2c62a50 from master
  • Loading branch information...
commit 18a2fb19074ce6789639b62710c279a711dabf97 1 parent 13de270
@timgraham timgraham authored
Showing with 41 additions and 4 deletions.
  1. +1 −3 django/core/serializers/base.py
  2. +40 −1 docs/ref/django-admin.txt
View
4 django/core/serializers/base.py
@@ -161,9 +161,7 @@ def __repr__(self):
def save(self, save_m2m=True, using=None):
# Call save on the Model baseclass directly. This bypasses any
# model-defined save. The save is also forced to be raw.
- # This ensures that the data that is deserialized is literally
- # what came from the file, not post-processed by pre_save/save
- # methods.
+ # raw=True is passed to any pre/post_save signals.
models.Model.save_base(self.object, using=using, raw=True)
if self.m2m_data and save_m2m:
for accessor_name, object_list in self.m2m_data.items():
View
41 docs/ref/django-admin.txt
@@ -344,7 +344,46 @@ application, ``<dirname>/foo/bar/mydata.json`` for each directory in
:setting:`FIXTURE_DIRS`, and the literal path ``foo/bar/mydata.json``.
When fixture files are processed, the data is saved to the database as is.
-Model defined ``save`` methods and ``pre_save`` signals are not called.
+Model defined :meth:`~django.db.models.Model.save` methods are not called, and
+any :data:`~django.db.models.signals.pre_save` or
+:data:`~django.db.models.signals.post_save` signals will be called with
+``raw=True`` since the instance only contains attributes that are local to the
+model. You may, for example, want to disable handlers that access
+related fields that aren't present during fixture loading and would otherwise
+raise an exception::
+
+ from django.db.models.signals import post_save
+ from .models import MyModel
+
+ def my_handler(**kwargs):
+ # disable the handler during fixture loading
+ if kwargs['raw']:
+ return
+ ...
+
+ post_save.connect(my_handler, sender=MyModel)
+
+You could also write a simple decorator to encapsulate this logic::
+
+ from functools import wraps
+
+ def disable_for_loaddata(signal_handler):
+ """
+ Decorator that turns off signal handlers when loading fixture data.
+ """
+ @wraps(signal_handler)
+ def wrapper(*args, **kwargs):
+ if kwargs['raw']:
+ return
+ signal_handler(*args, **kwargs)
+ return wrapper
+
+ @disable_for_loaddata
+ def my_handler(**kwargs):
+ ...
+
+Just be aware that this logic will disable the signals whenever fixtures are
+deserialized, not just during ``loaddata``.
Note that the order in which fixture files are processed is undefined. However,
all fixture data is installed as a single transaction, so data in
Please sign in to comment.
Something went wrong with that request. Please try again.