Greetings to all.
I am using Python3
and Django2
for a project, now I am creating an abstract class that will be inherited by all the classes in my project, this to determine who created a record and who was the last one to modify it. For this I am using a Middleware
based on this example that I found on the following website click here .
Here is the code as I am using it:
File utils.py
:
import threading
_thread_locals = threading.local()
def set_current_user(user):
_thread_locals.user = user
def get_current_user():
return getattr(_thread_locals, 'user', None)
def remove_current_user():
_thread_locals.user = None
File models.py
:
class ControlUsuarios(models.Model):
fecha_creacion = models.DateTimeField(auto_now_add=True, verbose_name=_('fecha de creación'))
fecha_modificacion = models.DateTimeField(auto_now_add=False, null=True, blank=True,
verbose_name=_('fecha de modificación'))
creador_por = models.ForeignKey(Usuario, null=True, editable=False, related_name='%(class)s_creador_por',
on_delete=models.PROTECT)
modificado_por = models.ForeignKey(Usuario, null=True, editable=False, related_name='%(class)s_modificado_por',
on_delete=models.PROTECT)
ip_creacion = models.GenericIPAddressField(null=True, blank=True, verbose_name=_('ip de creación'))
def save(self, *args, **kwargs):
if not self.pk:
self.fecha_creacion = datetime.today()
else:
self.fecha_modificacion = datetime.today()
user = get_current_user()
if user and user.is_authenticated():
self.modificado_por = user
if self._state.adding:
self.creador_por = user
super(ControlUsuarios, self).save(*args, **kwargs)
class Meta:
abstract = True
File middleware.py
:
from aplicaciones.parametros.utils import set_current_user, remove_current_user
# Seccion inicial del sitio web
class CurrentUserMiddleware:
def process_request(self, request):
set_current_user(getattr(request, 'user', None))
# Consejos adicionales del sitio web
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
set_current_user(getattr(request, 'user', None))
response = self.get_response(request)
remove_current_user()
# Code to be executed for each request/response after
# the view is called.
return response
File settings.py
:
MIDDLEWARE = [
# ...
' aplicaciones.parametros.middleware.CurrentUserMiddleware ' ,
]
Middleware
Two things happen with him.
If I use it as seen in the first section of the web I get the following error before I can run the server:
TypeError: CurrentUserMiddleware() takes no arguments
I add the tips that are given below with the methods
__init__
and__call__
applied this allows me to run the server, but it generates the following error when trying to save a record:TypeError: 'bool' object is not callable
And it tells me that the problem occurs in the save
model class Usuario
near the conditional lineif user and user.is_authenticated():
Finally, I want to automatically add the ip
one where the record is created from, as I can implement request.META['REMOTE_ADDR']
in themiddleware
I appreciate any help you can give me on this matter.
Solution to the errorTypeError: 'bool' object is not callable
The error 'bool' object is not callable
was due to the fact that user.is_authenticated
it must be used as a property and not as a function in the conditional. Also adjust the code so that the updated by only runs when the created by already exists:
user = get_current_user()
if user and user.is_authenticated:
if self._state.adding:
self.creador_por = user
else:
self.modificado_por = user
super(ControlUsuarios, self).save(*args, **kwargs)
Earring:
I still have the doubt of how to implement request.META['REMOTE_ADDR']
in Middleware
it any help or guide that you can give me, I thank you.
I got the solution by installing the library
django-crum
that allows me to access the request from the model.middleware is installed
And my Model is as follows