How do I prevent fixtures from conflicting with django post_save signal code?

前端 未结 4 1773
清酒与你
清酒与你 2020-11-29 20:56

In my application, I want to create entries in certain tables when a new user signs up. For instance, I want to create a userprofile which will then reference their company

相关标签:
4条回答
  • 2020-11-29 21:29

    Simple solution, add this to the beginning of your post_save function:

    if kwargs.get('raw', False):
        return False
    

    This will cause this function to exit when loading a fixture.

    See: https://docs.djangoproject.com/en/dev/ref/signals/#post-save

    0 讨论(0)
  • 2020-11-29 21:33

    This is an old question, but the solution I've found most straightforward is to use the 'raw' argument, passed by load data, and decorate the listener functions, for example:

    from functools import wraps
    
    
    def disable_for_loaddata(signal_handler):
        @wraps(signal_handler)
        def wrapper(*args, **kwargs):
            if kwargs['raw']:
                print "Skipping signal for %s %s" % (args, kwargs)
                return
            signal_handler(*args, **kwargs)
        return wrapper
    

    and then

    @disable_for_loaddata
    def callback_create_profile(sender, **kwargs):
        # check if we are creating a new User
        ...
    
    0 讨论(0)
  • 2020-11-29 21:48

    I think I figured out a way to do this. There is a 'raw' parameter in the kwargs passed in along with signals so I can replace my test above with this one:

    if (kwargs.get('created', True) and not kwargs.get('raw', False)):
    

    Raw is used when loaddata is running. This seems to do the trick.

    It is mentioned here: http://code.djangoproject.com/ticket/13299

    Would be nice if this was documented: http://docs.djangoproject.com/en/1.2/ref/signals/#django.db.models.signals.post_save

    0 讨论(0)
  • 2020-11-29 21:50

    I faced a similar problem in one of my projects. In my case the signals were slowing down the tests as well. I ended up abandoning signals in favour of overriding a Model.save() method instead.

    In your case however I don't think it makes sense to achieve this by overriding any save() methods. In that case you might want to try this. Warning, I only tried it once. It seemed to work but is not thoroughly tested.

    1. Create your own test runner.
    2. Before you load the fixtures, disconnect the callback_create_profile function from the User class' post_save signal.
    3. Let the fixtures load.
    4. Connect the function back to the signal.
    0 讨论(0)
提交回复
热议问题