django class view access response - django

in function view:
def view(request):
# do something with request
response = render(request, 'view.html')
# do something with response
return response
but now I have a View class:
class ArticleDeleteView(View):
pass
# or even something more complicated
class ArticleDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
pass
which function shall I overwrite to access to the response?
sorry that it may seems a silly question to you, but I looked through the docs and failed to find an answer.
thanks for all suggestions in comment. here's why I need to access to the response. Conditional Django Middleware (or how to exclude the Admin System)
I am building a specific type of 'middleware', for certain class based view, they are not actually middleware since they are not called for each request. I need to access to the response in order to do something before and after the response then return it, therefore I much would like to know which function generate response.

The easiest answer is: you don't. The View classes tend to be uncomplicated enough to be easily rewritten as a custom view which inherently gives you access to the response.
However if you insist I guess one of the functions you could override is the following: as_view, dispatch or setup as the request function goes through all of them. Sadly I couldn't find any mention of the one that was intended for that purpose.

Related

Implementing RPC in RESTful API using DRF

I am using the Django Rest Framework to present a RESTful API. I have a router/viewset/serializer creating an endpoint for a Person resource:
/api/People/<id>/
I would would like some way of triggering a non-idempotent action on this resource (for example send-email-to). One idea I had to do so without having to re-do a lot of the routing/serialization infrastructure was to add a write-only boolean field to the serializer:
class PersonSerializer(serializers.ModelSerializer):
send_email = serializers.BooleanField(write_only=True, required=False)
and then add a write-only property to the model:
class Person(models.Model):
...
def do_send_email(self, value):
# We also need to check the object is fully constructed here, I think
if do_send_email:
...
send_email = property(fset=do_send_email)
and then I can PATCH to the end point with the payload of send_email=True.
Is this the best way to accomplish an RPC like function using a REST API? Is this the best way to accomplish this in DRF? Ideally I would like to solve this problem having to-implement as little as possible (ie see how few lines of code the solution is). send-email-to is not the only action that I would like to handle.
You can use the extra actions drf provides. In your case especifically, I would use #detail_route.
Something like that:
#detail_route(methods=['post'])
def send_mail(self, request, pk=None):
send_mail_to(pk) # Write here your email function.
You have to define this function within the Person viewset so, in order to call this function, you will have to POST at /people/{person_id}/send_mail where {person_id} is the primary key for the person.
As a side note, since this function are synchronously called from the client and it may take a while to answer, I would recommend you the use of celery. This will allow you to call the send_mail_to function asynchronously without delaying the user response.

#login_required and is_authenticated() -- When to use which in Django?

I do not see a clear distinction between using #login_required decorator and is_authenticated(): somehow, I think they perform similar checks (though not exactly).
Let say I have a function in my views.py:
def dosomethingNow(request):
if request.user.is_authenticated():
//carry out the function
else:
//redirect to login page
Same function with login_required decorator:
#login_required
def dosomethingNow(request):
//carry out the function
Both the function does similar checks except that is_authenticated(), gives the option of redirecting to homepage if not logged in.
Any other benefits of using one over the other and places where they can't be used interchangeably?
Thanks
In the way you're using them in your example code, they're essentially equivalent.
Using user.is_aunthenticated is more flexible (as you note, you can decide what to do if they're not--output a different template, redirect to a login form, redirect somewhere else, etc.)
However, #login_required is "declarative", which can be nice. You could write a script that listed all of your view functions and whether or not they had the #login_required decorator around them, for instance, so you had a nice report of "login-required" sections of your site. When the checking happens in your own code buried inside the function, you lose that kind of possibility.
So it's a really a question of development style: do you need the flexibility to handle this as a special case? Or does make sense to use a declarative style?
(And, if you wanted a different implementation but a declarative style--say,if you frequently wanted to redirect non-logged-in-users to the homepage, you could write your own decorator, #homepage_if_not_auth, and use that)

Sharing code among views in Django

Forgive me if this has been asked repeatedly, but I couldn't find an example of this anywhere.
I'm struggling to understand how to share code among view functions in Django. For example, I want to check if the user is authenticated in many views. If they're not, I'd like to log some information about that request (IP address, etc.) then display a canned message about needing authentication.
Any advice on how to accomplish this?
You can write those code in a function, then call it in many views.
For example:
def check_login():
pass
def view1():
check_login()
pass
def view2():
check_login()
pass
This is probably best accomplished by creating a utils.py file, rather than a view. Views that don't return an HTTPResponse object are not technically valid.
See: https://docs.djangoproject.com/en/dev/intro/tutorial03/#write-views-that-actually-do-something
"Each view is responsible for doing one of two things: Returning an HttpResponse object containing the content for the requested page, or raising an exception such as Http404." ... "All Django wants is that HttpResponse. Or an exception."
Heroku will throw an error if the view does not return an HttpResponse.
What I usually do in this instance is write a function in a separate file called utils.py and import it and use it from the application files that need it.
from utils import check_login
def view1(request):
check_login(request)
pass
def view2(request):
check_login(request)
pass
One simple solution would be to use decorators just like in django's login_required, however if you need something more complex maybe you want something like class based views

How to manipulate the response object in django-piston?

I have some existing python code that uses django-piston which returns a dictionary as its response. For example:
from piston.handler import BaseHandler
class FooHandler(BaseHandler):
allowed_methods = ('GET',)
#classmethod
def create(self, request):
return { 'foo': 'bar' }
This code works fine, and is serialized into JSON with the appropriate HTTP header set (I'm assuming this works by some piston magic involving emitters; for bonus points, feel free to clarify how this behavior works as well, as I'm still getting to know django-piston).
I need to be able to modify the response in arbitrary ways, e.g. setting headers, status codes, etc. without using some pre-baked solution designed for a specific purpose. Is there a convenient way to access the response object in the context of this code and manipulate it, or has the response object not yet been created? In order to get access to a response object, will I have to construct it manually (a la vanilla django), serialize the dictionary, and set the appropriate headers by hand, and thus lose out on some of the useful magic of django-piston?
Every django-piston method returns an HTTPResponse.
When you return that dictionary, django-piston is just serializing it and sticking it in an HTTPResponse that it has crafted of some variety.
Kind of surprised you didn't pick up on that given that those "return rc.CREATED" lines in all the django-piston examples in the wiki are just hyper-simplistic responses with an HTTP code and response body.
Take a look here: https://bitbucket.org/jespern/django-piston/src/c4b2d21db51a/piston/utils.py
at the rc_factory class, which creates a variety of simple HTTPResponse objects for use with Piston.
At the very least you can observe how they do it, and then craft your own.
But the answer to the essence of your question "can I make a custom HTTPResponse" is yes, you can. Of course, that's what web servers do.
It is possible to set a custom response code by returning an HttpResponse object from your handler methods.
return HttpResponse({'foo': 'bar'}, status=404)
Unfortunately, you cannot set headers in the same way. For this, you have to write a custom Emitter that sets the headers you need. Something along these lines might work:
class CustomEmitter(JSONEmitter):
def render(self, request):
content = super(CustomEmitter, self).render(request)
response = HttpResponse(content)
response['Cache-Control'] = 'max-age=60'
Emitter.register('json', CustomEmitter, 'application/json; charset=utf-8')
You are quite right that django-piston uses emitters to serialize/deserialize requests and responses. You can even register your own emitters with piston and have it use those.
There are several ways that you can determine what the format should be.
1. mime-type
2. <format> in your URL
3. .json at the end of your URL
Which particular headers are you wanting to manipulate? There may be other solutions then just hacking away at the response object.

Can a django template know whether the view it is invoked from has the #login_required decorator?

Let's say that I have a system that has some pages that are public (both non-authenticated users and logged-in users can view) and others which only logged-in users can view.
I want the template to show slightly different content for each of these two classes of pages. The #login_required view decorator is always used on views which only logged-in users can view. However, my template would need to know whether this decorator is used on the view from which the template was invoked from.
Please keep in mind that I do not care whether the user is logged in or not for the public pages. What I care about is whether a page can be viewed by the general public, and the absence of a #login_required decorator will tell me that.
Can anyone throw me a hint on how the template would know whether a particular decorator is being used on the view from which the template invoked from?
Yes, it is possible, but not terribly straightforward. The complicating factor is that Django's login_required decorator actually passes through 2 levels of indirection (one dynamic function and one other decorator), to end up at django.contrib.auth.decorators._CheckLogin, which is a class with a __call__ method.
Let's say you have a non-django, garden-variety decorated function that looks like this:
def my_decorator(func):
def inner():
return func()
return inner
#my_decorator
def foo():
print foo.func_name
# results in: inner
Checking to see if the function foo has been wrapped can be as simple as checking the function object's name. You can do this inside the function. The name will actually be the name of the last wrapper function. For more complicated cases, you can use the inspect module to walk up the outer frames from the current frame if you're looking for something in particular.
In the case of Django, however, the fact that the decorator is actually an instance of the _CheckLogin class means that the function is not really a function, and therefore has no func_name property: trying the above code will raise an Exception.
Looking at the source code for django.contrib.auth.decorators._CheckLogin, however, shows that the _CheckLogin instance will have a login_url property. This is a pretty straightforward thing to test for:
#login_required
def my_view(request):
is_private = hasattr(my_view, 'login_url')
Because _CheckLogin is also used to implement the other auth decorators, this approach will also work for permission_required, etc. I've never actually had a need to use this, however, so I really can't comment on what you should look for if you have multiple decorators around a single view... an exercise left to the reader, I guess (inspect the frame stack?).
As unrequested editorial advice, however, I would say checking the function itself to see if it was wrapped like this strikes me as a bit fiddly. You can probably imagine all sorts of unpredictable behaviour waiting to happen when a new developer comes to the project as slaps on some other decorator. In fact, you're also exposed to changes in the django framework itself... a security risk waiting to happen.
I would recommend Van Gale's approach for that reason as something that is explicit, and therefore a much more robust implementation.
I would pass an extra context variable into the template.
So, the view that has #login_required would pass a variable like private: True and the other views would pass private: False
Why does your template need to know this? If the #login_required decorator is used, the view itself prevents people who aren't logged in from ever reaching the page and therefore never seeing the template to begin with.
Templates are hierarchical so why not have a #login_required version and a "no #login_required" version, both of which inherit from the same parent?
This would keep the templates a lot cleaner and easier to maintain.