在Django中,当我调用User.objects.create_user(用户名,电子邮件,密码)时 - 为什么post_save会被调用两次?

Deo*_*omo 2 django django-models django-errors django-users

在views.py中,我有以下视图,在注册新用户帐户时会调用该视图.它所做的就是从请求中获取用户名,电子邮件和密码,然后尝试使用这些凭据创建用户.在下面的代码中,"A"被打印,但"B"没有,因为它崩溃了:

views.py

def register(request):
    if request.method == 'POST':
        query_dict = request.POST
        username = query_dict['username']
        email = query_dict['user_email']
        password = query_dict['password']
        role = query_dict['role']
        print "A"
        user = User.objects.create_user(username, email, password)
        # the handler is called here and creates the user profile
        print "B"
        user = authenticate(username=username, password=password)
        user_profile = user.get_profile()
        user_profile.role = role
        user_profile.save()
        if user is not None and user.is_active:
            login(request, user)
            return HttpResponseRedirect("/")
Run Code Online (Sandbox Code Playgroud)

myapp/models.py我有处理程序的以下代码.

'models.py`

post_save.connect(create_user_profile, sender=User)

def create_user_profile(sender, instance, created, **kwargs):
    print "created="+str(created)
    if created: # as opposed to being saved after being created earlier, I assume
        print "attempting to create a user profile for "+instance.username
        up = UserProfile.objects.create(user=instance)
        print "created a new UserProfile: <"+str(up)+">"
Run Code Online (Sandbox Code Playgroud)

当我运行我的应用程序时,打印输出是:

A
created=True
attempting to create a user profile for john
created a new UserProfile: <john - >
created=True
attempting to create a user profile for john
~~~~CRASHES~~~~
Run Code Online (Sandbox Code Playgroud)

在过去几天我的开发过程中我注意到,create_user_profile当我运行时,方法被调用两次我User.objects.create_user(username, email, password) 直接从文档中复制了处理程序代码,所以我很确定它是正确的(https://docs.djangoproject.com/EN /开发/主题/认证/#存储附加信息前,大约用户).我不知道该create_user_profile方法从django代码中确切调用的位置,但我假设created只有在调用处理程序的save方法是由于正在创建的对象时才将标志设置为true.在过去的几天里,这段代码一直在正常工作,但今天突然间第二次create_user_profile处理程序调用该方法时,该created标志设置为true,就像它是第一次一样.这导致我的应用程序崩溃IntegrityError,抱怨它无法使用相同的主键创建两个对象.

所以有两件事我不明白.第一:为什么post_save在我只调用User.objects.create_user(username, email, password)一次时会发生两次; 第二:为什么created国旗突然停止像预期一样工作?

我该怎么调试呢?

谢谢

Ian*_*and 7

您的models.py文件可能正在导入并运行两次.在这种情况下,相同的信号处理程序将连接两次,并在保存模型实例时触发两次.

如果您将其导入一次,则很容易发生这种情况

import myapp.models
Run Code Online (Sandbox Code Playgroud)

再次如此

import myproject.myapp.models
Run Code Online (Sandbox Code Playgroud)

将某些内容打印到文件顶部的控制台可能会让您了解这是否正在发生.

无论如何,通过赋予信号处理程序唯一性,可以防止多次注册信号处理程序dispatch_uid.Django将检查Signal.connect是否已经为具有相同UID的同一发件人注册了处理程序,并且如果有,则不会重新注册它.

将连接代码的信号更改为类似的信号

post_save.connect(create_user_profile, sender=User, dispatch_uid='create_user_profile')
Run Code Online (Sandbox Code Playgroud)

看看是否有帮助