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実行時にメソッドが2回呼び出されることに気付きましUser.objects.create_user(username, email, password) た。ハンドラーコードをドキュメントから直接コピーしたので、正しいと確信しています(https://docs.djangoproject.com / en / dev / topics / auth /#storing-additional-information-about-users)。create_user_profiledjangoコードのどこからメソッドが呼び出されるかは正確にはわかりませんがcreated、ハンドラーを呼び出したsaveメソッドがオブジェクトの作成によるものである場合にのみ、フラグがtrueに設定されると想定しています。過去数日間、このコードは正常に機能していましたが、今日、2回目にcreate_user_profileメソッドがハンドラーによって呼び出されるとcreated、最初と同じようにフラグがtrueに設定されます。これにより、アプリがクラッシュしますIntegrityError、同じ主キーで2つのオブジェクトを作成できないと文句を言います。

ですから、私には理解できないことが2つあります。まず、一度だけ呼び出したのにpost_saveが2回発生するのはなぜですかUser.objects.create_user(username, email, password)。第二に:なぜcreated旗が突然期待通りに機能しなくなったのですか?

どうすればこれをデバッグできますか?

ありがとう

4

1 に答える 1

8

models.pyファイルが2回インポートされ、実行されている可能性があります。この場合、同じシグナルハンドラーが2回アタッチされ、モデルインスタンスが保存されるときに2回起動します。

これは、一度インポートすると簡単に発生する可能性があります。

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 に答える