Pass additional parameters to post_save signal

前端 未结 2 1430
太阳男子
太阳男子 2020-12-03 01:56

I have a user registration form in my Django application which collects additional data while a user is trying to register such as address, city, country, phone number etc.<

相关标签:
2条回答
  • 2020-12-03 02:06

    What I do is to set some '_attrs' to the instance and then use them in the signal handler.

    I imagine your case could be:

    # Function to Create user Account/Profile
    def create_user_account(sender, instance, created, **kwargs):
        if created:
            attrs_needed = ['_language', '_field', '_otherfield']
            if all(hasattr(instance, attr) for attr in attr_needed):
                models.Account.objects.create(
                    user=instance, 
                    language=instance._language, 
                    field=instance._field,
                    otherfield=instance._otherfield)
    
    # Create User / User Registration
    def UserRegistration(request):
      if request.method == 'POST':
        username = request.POST['fn'].capitalize() + ' ' + request.POST['ln'].capitalize()
        # CREATE USER
        newuser = User.objects.create_user(
            username=username, email=request.POST['email'],
            password=request.POST['pw'])
        newuser.first_name = request.POST['fn'].capitalize()
        newuser.last_name = request.POST['ln'].capitalize()
    
        # Set some extra attrs to the instance to be used in the handler.
        newuser._language = request.POST['language']
        newuser._field = request.POST['field']
        newuser._otherfield = request.POST['otherfield']
        newuser.save()
    
    
      return HttpResponse(username)
    
    #Post Save handler to create user Account/Profile
    post_save.connect(create_user_account, sender=User)
    

    I hate to do this, and I imagine it can breaks in horrible ways, and is hard to debug sometimes, also there is no a strict way to force the data needed for the handler, one could define a signal_data(data, signal, instance) to define the data needed for the signal handler for a particular instance.

    A nice option that I haven't tried is to use methods of the instance as signal's handlers and maybe we can use a more structured way to pass the data.

    Bye.

    0 讨论(0)
  • 2020-12-03 02:06

    Both User.objects.create_user and User.objects.create immediately triggers the post_save handler, because the save is called in the UserManager create_user. So I cannot imagine how Jorge's answer can work (at least if you want the save to be triggered only once - why would you trigger it twice???). What you want to do is to look into what create_user does, dissect it and this way you can really control when the save is called:

    # Function to Create user Account/Profile
    def create_user_account(sender, instance, created, **kwargs):
        if created:
            attrs_needed = ['_language', '_field', '_otherfield']
            if all(hasattr(instance, attr) for attr in attr_needed):
                models.Account.objects.create(
                    user=instance, 
                    language=instance._language, 
                    field=instance._field,
                    otherfield=instance._otherfield)
    
    # Create User / User Registration
    def UserRegistration(request):
      if request.method == 'POST':
        username = request.POST['fn'].capitalize() + ' ' + request.POST['ln'].capitalize()
        # CREATE USER
        newuser = User(
            username=username,
            email=request.POST['email'],
            first_name=request.POST['fn'].capitalize()
            last_name = request.POST['ln'].capitalize()
        )
        newuser.set_password(request.POST['pw'])
    
        # Set some extra attrs to the instance to be used in the handler.
        newuser._language = request.POST['language']
        newuser._field = request.POST['field']
        newuser._otherfield = request.POST['otherfield']
        newuser.save()  # Now this will be really the first save which is called
    
      return HttpResponse(username)
    
    #Post Save handler to create user Account/Profile
    post_save.connect(create_user_account, sender=User, weak=False)
    

    Note that I also use the weak=False when I hook up the handler.

    0 讨论(0)
提交回复
热议问题