Is there a way to call a function in ListView? - django

I have a ListView and I want to execute a script in python to update our database everytime I enter in the listview, or periodically.
Is there a way to do that ?
class AccessPointList(generic.ListView): #receives the whole set of AccessPoint and send to HTML
model = AccessPoint
#call a function in python -> c.update()
#or create a def to update our database

Sure, just override one of the methods when you want to run it, then call super to continue with normal execution of the ListView
class AccessPointList(generic.ListView):
model = AccessPoint
def get(self, request, *args, **kwargs):
# call your function
return super().get(request, *args, **kwargs)

Related

How to modify the Login view in inherited class in django?

I want to handle "confirm form resubmission" pop ups, when the user refresh the login page with incorrect data.
I'm using a class named: UserLogin inherited from LoginView('django built-in'), I know that I need to write a method in my own class to handle this issue, and I did it with HttpRespone for my Registration view. who can I solve it for my Login View?
my urls.py:
path('login/', UserLogin.as_view(template_name='userLogin/login.html'), name='login')
in my views:
class UserLogin(LoginView):
def refresh_page(self):
pass
return HttpResponse('login/')
I don't know How to fill my refresh_page method. besides, I tried :
class UserLogin(LoginView):
def refresh_page(self):
print('hello')
and I noticed that the method doesn't called at all! because it didn't print "hello" on my console
I think you can do it on different ways, one of them, just send post data to your view where you can handle user action and react to it. For example, like this:
class UserLogin(LoginView):
def post(self, request, *args, **kwargs):
if request.data.get('refresh'):
self.refresh_page()
return super().post(self, request, *args, **kwargs)
def refresh_page(self):
return HttpResponse('login/')

Django REST API: run operations after put request

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

Custom wagtail page model save method called twice

In a Django+Wagtail project, I have a custom method which I call from the model save() method. It works - but everytime I save an instance via the wagtail admin interface, this method is called twice - why?
# models.py
from wagtail.core.models import Page
class ArticlePage(Page):
def my_method(self):
print('I will be printed twice on save...')
def save(self, *args, **kwargs):
self.my_method()
super().save(*args, **kwargs)
By using traceback.print_stack as suggested by HÃ¥ken Lid I've found out that the method is first called via
File ".../.venv/lib/python3.6/site-packages/wagtail/admin/views/pages.py", line 336, in edit
submitted_for_moderation=is_submitting,
File ".../.venv/lib/python3.6/site-packages/wagtail/core/models.py", line 653, in save_revision
self.save(update_fields=update_fields)
and the second time via
File ".../.venv/lib/python3.6/site-packages/wagtail/admin/views/pages.py", line 343, in edit
revision.publish()
File ".../.venv/lib/python3.6/site-packages/wagtail/core/models.py", line 1498, in publish
page.save()
But even with this information I'm not aware how to only trigger my method on the second save...
Env:
Django 2.0.4
Wagtail 2.0.1
In case you want to do something on page publish, You can use the page_published signals as below:
from django.dispatch import receiver
from wagtail.core.signals import page_published
#receiver(page_published)
def do_stuff_on_page_published(instance, **kwargs):
print('=======================',instance,kwargs)
In case of save, you can also check the update_fields argument in the kwargs:
def save(self, *args, **kwargs):
if kwargs.get('update_fields'):
pass # save not called from publish
# do_stuff_on_save()
else:
pass
# do_stuff_on_publish()
return super().save(*args, **kwargs)
For more info about wagtail signal code visit this link
and this for the official docs
http://docs.wagtail.io/en/v1.7/reference/signals.html

How do I get the current user for my created_by field in Django 1.9?

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)

Django custom decorator for custom permission

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?