简体   繁体   English

将附加参数传递给 post_save 信号

[英]Pass additional parameters to post_save signal

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.我的 Django 应用程序中有一个用户注册表单,它在用户尝试注册时收集其他数据,例如地址、城市、国家/地区、电话号码等。

This data is saved in the Account model class through post_save signal.该数据通过post_save信号保存在 Account 模型类中。 The user creation process goes something like this :用户创建过程是这样的:

# Function to Create user Account/Profile
def create_user_account(sender, instance, created, **kwargs):
    if created:
      models.Account.objects.create(user=instance)

# 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()
        newuser.save()
    return HttpResponse(username)

#Post Save handler to create user Account/Profile
post_save.connect(create_user_account, sender=User)

Here the UserRegistration function is called when a user posts a form and under this function, I can get the POST data, what I want is to pass that data to create_user_account method so that it fills in the fields in the Account model.在这里,当用户发布表单时调用UserRegistration函数,在此函数下,我可以获得 POST 数据,我想要将该数据传递给create_user_account方法,以便它填充Account模型中的字段。

Right now, I do see Account objects created in the database, but all the fields except the user field are empty.现在,我确实看到在数据库中创建了Account对象,但是除了用户字段之外的所有字段都是空的。 Obviously, because the POST variables are not being passed to the create_user_account method.显然,因为 POST 变量没有被传递给create_user_account方法。

What I do is to set some '_attrs' to the instance and then use them in the signal handler. 我所做的是为实例设置一些'_attrs',然后在信号处理程序中使用它们。

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. 我讨厌这样做,我想它可能会以可怕的方式打破,有时很难调试,也没有严格的方法来强制处理程序所需的数据,可以定义一个signal_data(data, signal, 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. 再见。

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 . User.objects.create_userUser.objects.create立即触发post_save处理程序,因为在UserManager create_user调用了save 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???). 所以我无法想象Jorge的答案是如何起作用的(至少如果你想要只触发一次保存 - 为什么你会触发它两次?)。 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: 你想要做的是研究create_user作用,剖析它,这样你可以真正控制何时调用save

# 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. 请注意,当我挂钩处理程序时,我也使用weak=False

我发现当我们使用 create_user 和 create 方法时,receiver(post_save, sender=User) 会立即被调用,所以我们需要先初始化对象,然后填充额外的字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM