Is it possible to access the current session in the user model .save()?
pseudo code of what I want to achieve:
# users.models.py
def save(self, *args, **kwargs):
created = True
if self.pk:
created = False
super(AbstractUser, self).save(*args, **kwargs)
# post-save
if created:
look_for_invite_in_session_and_register_if_found(self, session)
Seems it something wrong in your architecture. You shouldn't access request in models layer. All work with request must be done in view. You can do it like this:
user, created = AbstractUser.objects.get_or_create(name=name)
if created:
look_for_invite_in_session_and_register_if_found(user, request.session)
Related
I want to encrypt the username data before save in django auth User model, and decrypt the username data. we are using model like this
class Profile(models.Model):
user = models.OneToOneField(User,related_name='profile_data',on_delete=models.PROTECT)
Regarding this Any solution reference pls.
You can override the save method, and do the encryption logic in there. It would be executed just before saving anything in Profile Modal. Like this:
class Profile(models.Model):
user = models.OneToOneField(User,related_name='profile_data',on_delete=models.PROTECT)
def encrypt(self, to_be_encrypted_value):
# Here, you would do the logic of encrypting, and return the encrypted value.
# To be used in save method.
...
return encrypted_value
def save(self, *args, **kwargs):
self.user = self.encrypt(self.user)
super().save(*args, **kwargs)
I am trying to find a clean way to process some task after successfully completes the PUT request for REST API. I am using post_update() function but its never being called. Here is my code
class portfolio_crud(generics.RetrieveUpdateDestroyAPIView):
lookup_field = 'id'
serializer_class = user_ticker_portfolio_serializer
def get_queryset(self):
return user_ticker_portfolio.objects.filter(user = self.request.user)
def put(self, request, *args, **kwargs):
print("got the put request to update portfolio")
return self.update(request, *args, **kwargs)
def post_update(self, serializer):
print("got the post save call") #never executed
Depends on what you want to do, but I usually use django's post_save hook as opposed to something on the viewset or serializer. Something like this:
from django.db.models.signals import post_save
#receiver(post_save, sender=YourPortolioClass)
def portfolio_post_save(sender, created, instance, raw, **kwargs):
""" We need to do something after updating a portfolio
"""
if created or raw:
return
# do your update stuff here.
Not sure if this will be much help to you (but I hope so) - I just use multithreading and create another thread before returning.
I don't see anything calling that function... but I am curious
I'm trying to pull the session user into my model's save() method. The docs for HttpRequest and all the examples I've found assume you already have the object instanciated, but I can't seem to find a method that will do the instanciation.
I'm thinking I should be using HttpRequest.user , but I don't know how to generate the instance in my model so I can actually do it.
Here's my save() override. It generates type object 'HttpRequest' has no attribute 'user', but considering this is a class and not an object reference that isn't really surprising.:
def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not hasattr(self, 'id'):
self.date_created = timezone.now()
self.created_by = HttpRequest.user
self.last_updated_date = timezone.now()
self.last_updated_by = HttpRequest.user
super(Caregiver, self).save(*args, **kwargs)
views.py added for more info
class CaregiverCreateView(CreateView):
template_name = 'single_form_generic.html'
model = Caregiver
form_class = CaregiverCreateForm
django-cuser can do this easily. This library adds middleware that can be called in a view, model method, etc to get the current user. If you are ok with the user being assigned at the model's save method, then you just need to call the middleware to inspect the session as below.
Once set up, it can be called like this:
from cuser.middleware import CuserMiddleware
class YourModel(models.Model):
def save(self, *args, **kwargs):
self.created_by = CuserMiddleware.get_user()
super(YourModel,self).save(*args, **kwargs)
If you are calling save() explicitly, you could pass the user instance directly to the method:
def save(self, user, *args, **kwargs):
# use the user
Then when you call it in views.py, do:
instance.save(request.user)
I had to dig around a little, but I did end up finding an answer for you future googlers:
The class based view docs actually have a relevant example. Since the view already has access to the request and the form and model are tied, you really only need to inject it in the view submission by overriding the form_valid method there.
def form_valid(self, form):
form.instance.created_by = self.request.user
form.instance.last_updated_by = self.request.user
return super(CaregiverCreateView, self).form_valid(form)
There is a Project model with a ManyToMany relation to User model, using a join table.
If a user is not member of a project (not in the join table), I want to prevent the user from accessing a view that shows the specific project.
I know it could be solved with a simple if statement inside the view method or a custom filter in the template, but I would like to be able to do this with a custom decorator.
Is this possible? If so how could it be done?
Something like:
def may_user_view_this(function):
def wrapper(request, *args, **kwargs):
user = request.user
project = Project.objects.get(id=???????) #id
if not project.has_user(user):
return HttpResponse('You cannot view this.')
else:
return function(request, *args, **kwargs)
return wrapper
#may_user_view_this() # if not go the specific url
def my_view(request, page_id=None):
# do stuff and render
How can I access the parameter page_id sent to my_view from the decorator function?
I am just using the admin site in Django. I have 2 Django signals (pre_save and post_save). I would like to have the username of the current user. How would I do that? It does not seem I can send a request Or I did not understand it.
Thanks
Being reluctant to mess around with thread-local state, I decided to try a different approach. As far as I can tell, the post_save and pre_save signal handlers are called synchronously in the thread that calls save(). If we are in the normal request handling loop, then we can just walk up the stack to find the request object as a local variable somewhere. e.g.
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
...
If there's a current request, you can grab the user attribute from it.
Note: like it says in the inspect module docs,
This function relies on Python stack frame support in the interpreter, which isn’t
guaranteed to exist in all implementations of Python.
If you are using the admin site why not use a custom model admin
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 )
A signal is something that is fired every time the object is saved regardless of if it is being done by the admin or some process that isn't tied to a request and isn't really an appropriate place to be doing request based actions
You can use a middleware to store the current user: http://djangosnippets.org/snippets/2179/
Then you would be able to get the user with get_current_user()
We can solve this problem using middleware classes.
Create singleton class in where will be storing user variable.
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
Create own middleware class that will be setting user for LoggedInUser instance,and insert out middleware after 'django.contrib.auth.middleware.AuthenticationMiddleware' in settings.py
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
In signals import LoggedInUser class and get current user
logged_in = LoggedInUser()
user = logged_in.user
In both signals, signal send three arguments,
Sender
Instance
Using
What you need is the Instant being modified...
def signal_catcher(sender, instance, **kwargs):
uname = instance.username
http://docs.djangoproject.com/en/dev/ref/signals/#pre-save