Djangoの管理サイトを使用しています。2つのDjangoシグナル(pre_saveとpost_save)があります。現在のユーザーのユーザー名を教えてください。どうすればいいですか?リクエストが送信できないか、理解できませんでした。
ありがとう
Djangoの管理サイトを使用しています。2つのDjangoシグナル(pre_saveとpost_save)があります。現在のユーザーのユーザー名を教えてください。どうすればいいですか?リクエストが送信できないか、理解できませんでした。
ありがとう
スレッドローカル状態をいじりたがらないので、別のアプローチを試すことにしました。私の知る限り、post_save
とpre_save
シグナルハンドラーは、を呼び出すスレッドで同期的に呼び出されますsave()
。通常のリクエスト処理ループにいる場合は、スタックを上に移動して、リクエストオブジェクトをローカル変数としてどこかに見つけることができます。例えば
from django.db.models.signals import pre_save
from django.dispatch import receiver
@receiver(pre_save)
def my_callback(sender, **kwargs):
import inspect
for frame_record in inspect.stack():
if frame_record[3]=='get_response':
request = frame_record[0].f_locals['request']
break
else:
request = None
...
現在のリクエストがある場合は、そこuser
から属性を取得できます。
注:inspect
モジュールのドキュメントに記載されているように、
この関数は、インタープリターでのPythonスタックフレームのサポートに依存しています。これは、Pythonのすべての実装に存在することが保証されているわけではありません。
管理サイトを使用している場合は、カスタムモデル管理者を使用してみませんか
class MyModelAdmin( admin.ModelAdmin ):
def save_model( self, request, obj, form, change ):
#pre save stuff here
obj.save()
#post save stuff here
admin.site.register( MyModel, MyModelAdmin )
シグナルとは、オブジェクトが管理者によって実行されているか、リクエストに関連付けられておらず、リクエストベースのアクションを実行するのに実際には適切な場所ではないプロセスによって実行されているかに関係なく、オブジェクトが保存されるたびに発生するものです。
ミドルウェアを使用して現在のユーザーを保存できます:http://djangosnippets.org/snippets/2179/
次に、ユーザーを取得することができますget_current_user()
ミドルウェアクラスを使用してこの問題を解決できます。ユーザー変数を格納する場所にシングルトンクラスを作成します。
class Singleton(type):
'''
Singleton pattern requires for GetUser class
'''
def __init__(cls, name, bases, dicts):
cls.instance = None
def __call__(cls, *args, **kwargs):
if cls.instance is None:
cls.instance = super(Singleton, cls).__call__(*args, **kwargs)
return cls.instance
class NotLoggedInUserException(Exception):
'''
'''
def __init__(self, val='No users have been logged in'):
self.val = val
super(NotLoggedInUser, self).__init__()
def __str__(self):
return self.val
class LoggedInUser(object):
__metaclass__ = Singleton
user = None
def set_user(self, request):
if request.user.is_authenticated():
self.user = request.user
@property
def current_user(self):
'''
Return current user or raise Exception
'''
if self.user is None:
raise NotLoggedInUserException()
return self.user
@property
def have_user(self):
return not user is None
LoggedInUserインスタンスのユーザーを設定する独自のミドルウェアクラスを作成し、settings.pyの「django.contrib.auth.middleware.AuthenticationMiddleware」の後にミドルウェアを挿入します。
from useranytimeaccess import LoggedInUser
class LoggedInUserMiddleware(object):
'''
Insert this middleware after django.contrib.auth.middleware.AuthenticationMiddleware
'''
def process_request(self, request):
'''
Returned None for continue request
'''
logged_in_user = LoggedInUser()
logged_in_user.set_user(request)
return None
シグナルでLoggedInUserクラスをインポートし、現在のユーザーを取得します
logged_in = LoggedInUser()
user = logged_in.user
ハックなし:ユーザーがログイン/ログアウトするときにシグナルを使用して、誰がログに記録されているかを記憶します。Djangoテストフレームワークの場合、接続してシグナルを呼び出す限り、これも機能します。
current_user = None
@receiver(user_logged_in, sender=User)
def user_logged_in(sender, request, user, **kwargs):
global current_user
current_user = user
@receiver(user_logged_out, sender=User)
def user_logged_out(sender, request, user, **kwargs):
global current_user
current_user = None
@receiver(post_save, sender=StatusHistory)
def status_history_post_save(sender, instance: StatusHistory,
created, **kwargs):
global current_user
if current_user is None or instance is None or instance.shipment is None:
return
# ok if we here -> user is connected, keep on:
# .........
# blabla
# .........
両方のシグナルで、シグナルは3つの引数を送信します。
必要なのは、変更されるインスタントです...
def signal_catcher(sender, instance, **kwargs):
uname = instance.username