4

在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("/")

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)+">"

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

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~~~~

在过去几天的整个开发过程中,我注意到该create_user_profile方法在我运行时被调用了两次我User.objects.create_user(username, email, password) 直接从文档中复制了处理程序代码,所以我很确定它是正确的(https://docs.djangoproject.com /en/dev/topics/auth/#storing-additional-information-about-users)。我不确切知道该create_user_profile方法在 django 代码中的哪个位置被调用,但我假设它created仅在调用处理程序的保存方法是由于创建对象时才将标志设置为 true。在过去的几天里,这段代码一直在正常工作,但突然间create_user_profile,当处理程序第二次调用该方法时,created标志设置为 true,就像第一次一样。这导致我的应用程序崩溃IntegrityError,抱怨它不能创建两个具有相同主键的对象。

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

我该如何调试呢?

谢谢

4

1 回答 1

8

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

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

import myapp.models

再次作为

import myproject.myapp.models

在文件顶部打印一些内容到控制台可能会让您知道这是否正在发生。

无论如何,您可以通过给它一个唯一的dispatch_uid. Django 将检查Signal.connect是否已经为具有相同 UID 的同一发送者注册了处理程序,如果已注册,则不会重新注册。

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

post_save.connect(create_user_profile, sender=User, dispatch_uid='create_user_profile')

看看是否有帮助

于 2012-01-18T20:55:47.500 回答