usar update_fields trigger signal save_user_profile español como python django signals

python - update_fields - trigger django



Accediendo a la solicitud del usuario en una señal post_save (9)

¿Por qué no agregar un middleware con algo como esto?

class RequestMiddleware(object): thread_local = threading.local() def process_request(self, request): RequestMiddleware.thread_local.current_user = request.user

y más adelante en su código (especialmente en una señal en ese tema):

thread_local = RequestMiddleware.thread_local if hasattr(thread_local, ''current_user''): user = thread_local.current_user else: user = None

He hecho la siguiente señal de post_save en mi proyecto.

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

La columna operation_by, quiero obtener el user_id y almacenarlo. ¿Alguna idea de cómo se puede hacer eso?


Ignacio tiene razón. Las señales modelo de Django están destinadas a notificar a otros componentes del sistema sobre eventos asociados con instancias y sus datos respetados, por lo que supongo que es válido que no pueda, digamos, acceder a datos de solicitud desde una señal modelo post_save , a menos que los datos de solicitud se post_save almacenado o asociado a la instancia

Supongo que hay muchas formas de manejarlo, que van de peor a mejor, pero diría que este es un excelente ejemplo para crear vistas genéricas basadas en clases / funciones que manejarán esto automáticamente por usted.

CreateView vistas que heredan de CreateView , UpdateView o DeleteView también se heredan de su clase AuditMixin si manejan verbos que operan en modelos que necesitan ser auditados. A continuación, AuditMixin puede conectarse a las vistas que crean con éxito / update / delete objetos y crean una entrada en la base de datos.

Tiene mucho sentido, es muy limpio, fácil de conectar y da a luz a ponis felices. ¿Otra cara? Tendrá que estar en la próxima versión de Django 1.3 que se lanzará próximamente o tendrá que pasar un tiempo combinando las vistas genéricas basadas en funciones y proporcionando nuevas para cada operación de auditoría.


Me imagino que habrías descubierto esto, pero tuve el mismo problema y me di cuenta de que todas las instancias que he creado tienen una referencia al usuario que las crea (lo que estás buscando).



No se puede hacer El usuario actual solo está disponible a través de la solicitud, que no está disponible cuando se utiliza únicamente la funcionalidad del modelo. Accede al usuario en la vista de alguna manera.


Para la trazabilidad, agregue dos atributos a su Modelo ( created_by y updated_by ), en "updated_by" guarde al último usuario que modificó el registro. Luego en tu señal tienes al usuario:

modelos.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)

vistas.py

p = Question.objects.get(pk=1) p.question_text = ''some new text'' p.updated_by = request.user p.save()

señales.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))


Pude hacerlo inspeccionando la pila y buscando la vista, luego observando las variables locales de la vista para obtener la solicitud. Se siente como un poco de un hack, pero funcionó.

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



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'', )