プロジェクトで以下のpost_save信号を実行しました。
from Django.db.models.signals import post_save
from Django.contrib.auth.models import User
# CORE - SIGNALS
# Core Signals will operate based on post
def after_save_handler_attr_audit_obj(sender, **kwargs):
print User.get_profile()
if hasattr(kwargs['instance'], 'audit_obj'):
if kwargs['created']:
kwargs['instance'].audit_obj.create(operation="INSERT", operation_by=**USER.ID**).save()
else:
kwargs['instance'].audit_obj.create(operation="UPDATE").save()
# Connect the handler with the post save signal - Django 1.2
post_save.connect(after_save_handler_attr_audit_obj, dispatch_uid="core.models.audit.new")
Operation_by列では、user_idを取得して保存します。どのようにそれを行うことができますか?
できません。現在のユーザーは、リクエストを介してのみ利用できます。純粋なモデル機能を使用している場合は利用できません。どういうわけかビューでユーザーにアクセスします。
スタックを調べてビューを探し、ビューのローカル変数を調べてリクエストを取得することで、それを行うことができました。それは少しハックのように感じますが、うまくいきました。
import inspect, os
@receiver(post_save, sender=MyModel)
def get_user_in_signal(sender, **kwargs):
for entry in reversed(inspect.stack()):
if os.path.dirname(__file__) + '/views.py' == entry[1]:
try:
user = entry[0].f_locals['request'].user
except:
user = None
break
if user:
# do stuff with the user variable
イグナシオは正しいです。 Djangoのモデル信号は、インスタンスに関連付けられたイベントとそれらの尊重されるデータについて他のシステムコンポーネントに通知することを目的としているため、たとえば、モデルからのリクエストデータにアクセスできないことは有効だと思いますpost_save
シグナル。ただし、リクエストデータがインスタンスに保存されているか、インスタンスに関連付けられている場合を除きます。
それを処理する方法はたくさんありますが、悪いものから良いものまでさまざまですが、これはprimeがこれを自動的に処理するクラスベース/関数ベースの汎用ビューを作成するための例だと思いますあなたのために。
CreateView
、UpdateView
、またはDeleteView
から継承するビューに、監査が必要なモデルで動作する動詞を処理する場合、AuditMixin
クラスから追加で継承させる。 AuditMixin
は、オブジェクトを正常に作成、更新、削除するビューにフックして、データベースにエントリを作成できます。
完全な意味があり、非常にきれいで、簡単に差し込むことができ、幸せなポニーを生み出します。フリップサイド?間もなくリリースされるDjango 1.3リリースを使用するか、関数ベースの汎用ビューをいじくり回してそれぞれに新しいビューを提供する必要があります。監査操作。
トレーサビリティのために、モデルに2つの属性を追加します(created_by
およびupdated_by
)、「updated_by」で、レコードを変更した最後のユーザーを保存します。次に、あなたの信号であなたはユーザーを持っています:
models.py:
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
created_by = models. (max_length=100)
updated_by = models. (max_length=100)
views.py
p = Question.objects.get(pk=1)
p.question_text = 'some new text'
p.updated_by = request.user
p.save()
signal.py
@receiver(pre_save, sender=Question)
def do_something(sender, instance, **kwargs):
try:
obj = Question.objects.get(pk=instance.pk)
except sender.DoesNotExist:
pass
else:
if not obj.user == instance.user: # Field has changed
# do something
print('change: user, old=%s new=%s' % (obj.user, instance.user))
この目的でDjango-reversionを使用することもできます。
from reversion.signals import post_revision_commit
import reversion
@receiver(post_save)
def post_revision_commit(sender, **kwargs):
if reversion.is_active():
print(reversion.get_user())
APIの詳細を読む https://Django-reversion.readthedocs.io/en/stable/api.html#revision-api
次のようなミドルウェアを追加してみませんか。
class RequestMiddleware(object):
thread_local = threading.local()
def process_request(self, request):
RequestMiddleware.thread_local.current_user = request.user
コードの後半(特にそのトピックのシグナル):
thread_local = RequestMiddleware.thread_local
if hasattr(thread_local, 'current_user'):
user = thread_local.current_user
else:
user = None
あなたがこれを理解したと想像しますが、同じ問題があり、作成するすべてのインスタンスが、それらを作成するユーザーへの参照を持っていることに気付きました(あなたが探しているものです)
context_processors.py
from Django.core.cache import cache
def global_variables(request):
cache.set('user', request.user)
----------------------------------
in you model
from Django.db.models.signals import pre_delete
from Django.dispatch import receiver
from Django.core.cache import cache
from news.models import News
@receiver(pre_delete, sender=News)
def news_delete(sender, instance, **kwargs):
user = cache.get('user')
in settings.py
TEMPLATE_CONTEXT_PROCESSORS = (
'web.context_processors.global_variables',
)