Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #20136 - Fixed and expanded the docs for loaddata and model sig…

…nals.

Thanks brandon@ and Anssi for the report.
  • Loading branch information...
commit 2c62a509deb50e39375b0cd44cfc85a743978fdc 1 parent 679a2ac
Tim Graham authored May 11, 2013
4  django/core/serializers/base.py
@@ -161,9 +161,7 @@ def __repr__(self):
161 161
     def save(self, save_m2m=True, using=None):
162 162
         # Call save on the Model baseclass directly. This bypasses any
163 163
         # model-defined save. The save is also forced to be raw.
164  
-        # This ensures that the data that is deserialized is literally
165  
-        # what came from the file, not post-processed by pre_save/save
166  
-        # methods.
  164
+        # raw=True is passed to any pre/post_save signals.
167 165
         models.Model.save_base(self.object, using=using, raw=True)
168 166
         if self.m2m_data and save_m2m:
169 167
             for accessor_name, object_list in self.m2m_data.items():
41  docs/ref/django-admin.txt
@@ -373,7 +373,46 @@ application,  ``<dirname>/foo/bar/mydata.json`` for each directory in
373 373
 :setting:`FIXTURE_DIRS`, and the literal path ``foo/bar/mydata.json``.
374 374
 
375 375
 When fixture files are processed, the data is saved to the database as is.
376  
-Model defined ``save`` methods and ``pre_save`` signals are not called.
  376
+Model defined :meth:`~django.db.models.Model.save` methods are not called, and
  377
+any :data:`~django.db.models.signals.pre_save` or
  378
+:data:`~django.db.models.signals.post_save` signals will be called with
  379
+``raw=True`` since the instance only contains attributes that are local to the
  380
+model. You may, for example, want to disable handlers that access
  381
+related fields that aren't present during fixture loading and would otherwise
  382
+raise an exception::
  383
+
  384
+    from django.db.models.signals import post_save
  385
+    from .models import MyModel
  386
+
  387
+    def my_handler(**kwargs):
  388
+        # disable the handler during fixture loading
  389
+        if kwargs['raw']:
  390
+            return
  391
+        ...
  392
+
  393
+    post_save.connect(my_handler, sender=MyModel)
  394
+
  395
+You could also write a simple decorator to encapsulate this logic::
  396
+
  397
+    from functools import wraps
  398
+
  399
+    def disable_for_loaddata(signal_handler):
  400
+        """
  401
+        Decorator that turns off signal handlers when loading fixture data.
  402
+        """
  403
+        @wraps(signal_handler)
  404
+        def wrapper(*args, **kwargs):
  405
+            if kwargs['raw']:
  406
+                return
  407
+            signal_handler(*args, **kwargs)
  408
+        return wrapper
  409
+
  410
+    @disable_for_loaddata
  411
+    def my_handler(**kwargs):
  412
+        ...
  413
+
  414
+Just be aware that this logic will disable the signals whenever fixtures are
  415
+deserialized, not just during ``loaddata``.
377 416
 
378 417
 Note that the order in which fixture files are processed is undefined. However,
379 418
 all fixture data is installed as a single transaction, so data in

0 notes on commit 2c62a50

Please sign in to comment.
Something went wrong with that request. Please try again.