Setting attributes on the request object when testing a django view - python

I'm writing some tests for a view function in django. The view function is decorated with an #facebook.require_login decorator from the pyFacebook library. This deciorator checks whether the user is logged in to facebook and provides access to an object which represents the facebook api if they are. The checking and populating of the request is done in some middleware.
I want to be able to control what the view function sees from the facebook api and so I am attempting to mock the facebook api object using the mock library. The problem is, the facebook middleware makes the facebook api available as an attribute on the request, as far as I can tell the django test client does not give you access to the request object so I cannot insert the mock facebook api object into the view.
The only way I can see to test this is to basically copy most of the code from the test client and modify it to make the request object accessible to the test code before the test is run. I don't have a problem with doing this, but is this the best way to do it? I feel like there must be an easier way.
Also, is it normal for middleware to set attributes on the request, it seems like it would be conceptually cleaner for the middleware to make any extra data available as extra arguments to the decorated function (in this example, I am sure there are others where that doesn't apply).

Have you looked at the RequestFactory [1]?
[1] http://docs.djangoproject.com/en/dev/topics/testing/#the-request-factory

Related

How to do a Customer Logger for Django to Capture Response and Request

I'm looking into differen't ways to capture the response object, request object, and performance in Django to create a custom json elk logger that will build audit logs.
I'm not sure what approach is best to take here. I was looking at custom middleware but I've never done that.
I tried to look up if it was possible to use a decorator to do this but doesn't seem like it.
Also, I use the django rest framework so I also have to figure out how to integrate the middleware if thats the route or whatever solution to DRF as well.
Looking for suggestions.
If you use DRF, i advice you pckage - drf-tracking. Just add mixin LoggingMixin to you class like this:
class ProbeView(LoggingMixin, APIView):
...
And after this, each qyery for this view wiil be logged in database. Example:

Why view functions require a request parameter In Django?

Example from Django documentation:
def index(request):
return HttpResponse('<h1>hellworld!</h1>')
def detail(request, question_id):
return HttpResponse("Question: %s" % question_id)
Since the request argument is never used, why should I include it in each function signature?
The purpose of a web server is to reply to HTTP requests (In simple terms). Django being a web framework generates responses depending on the request that it receives.
The business logic of handling the requests is done by Django Views, it is their purpose. This is why Django supplies the request to the view function, so the code can access the request data and choose what actions it should take and which response it should send back (even though that specific view doesn't make use of it).
The decision of requiring the view to receive the request as an argument is an implementation decision made by Django developers, making it part of the interface the view has with the rest of the "system". Other frameworks might choose making it available globally and not suplying it to the views/controllers directly, but the merits of one or another approach is other discussion.
Many of the examples in Django's documentation (and any documentation, really) are necessarily contrived. They're simple because the complexity of a real example would take away from the point that's being made.
In real use cases, you'll frequently want access to the request object. You may want to know which User is attached to the request (request.user) or whether the request is a GET or a POST (request.method).
You can also inspect the headers (request.headers), decode the JSON object sent with a POST request (json.loads(request.body)), etc.
Those are just examples. In real world a programmer would want to find request GET arguments, decode JSON POST body, inspect headers, get user or session data, etc.

Middleware in flask

I just stated using Flask and was trying to implement a small feature in my project. The objective is to set a cookie only if the request comes from a authenticated user.
I found two ways of doing this.
First method
#app.before_request
def before_request():
# set cookie if user is logged in
Second method, by implementing something like this
adding-a-simple-middleware-to-your-flask-application
Can someone explain to me what are the main differences between the two methods and when and where which method should be used.
Also, I am currently using "flask-login" to keep track of the logged in user.
If I use the first method, I can easily verify if someone is logged in by importing the current_user
from flask.ext.login import current_user
but if I try to do the same while using the second method, the current_user is always "None" as the application context is incorrect.
So, I wanted to know if I decided to go ahead with the second implementation, how do I check if the user is logged in or not.
I've never used the second method you've mentioned. I'm sure that it can be done with it, but it's very uncommon. I would suggest to use more common features of flask. For sake of maintainers of your code :)
So the first method you've mentioned is fine.
Or you can use decorators for more granular access restrictions. Keep in mind that setting cookies in flask can be done when making actual response object. That means you should use Deferred Request Callbacks for setting cookies in decorated function.

Defining both post and get method under same request handler

I'm using python to develop a web app.
I defined both "get" and "post" method in the same request handler to serve different purpose. That is, I use "get" method to present a form to user, and "post" method to handle the submitted form.
It works fine, but is this approach appropriate? Or should I better define get and post separately in different request handler? Thanks!
Your approach is appropriate. According to the newest documentation you can even define post and get as functions outside request handler and just as other functions in your module and that's a way I would choose since it eliminates problems that can happen when instanciating request handlers.
If starting a new app from scratch I probably would try to put my get and post function outside of request handler with the new python 2.7 runtime that according to docs supports that.

Django: Context processors in views, bad practice?

In my Django project, I have a context processor which returns a FacebookUser object based on the cookies present in the request (using Facebook's Python SDK). This means that when the user is logged in, their corresponding FacebookUser object is always available in my templates.
However, what should I do when I want to access this in views too?
Option 1: In each view where I want to access this FacebookUser object, call the context processor method, or a method that does exactly the same thing.
Option 2: Again, in each view, call RequestContext(request) in order to get access to the existing object added to the context by the context processor.
Which is better practice, and are there any recommended ways of working here?
If you need your FacebookUser object a lot then use middleware. Documentation is here
For a sample middleware class:
class FacebookApiIntegrator(object):
def process_request(self, request):
if request.user.is_authenticated():# check if user has logged in
request.facebook = <your profile func or obj..>
and in any view you can just use:
request.facebook
But do not forget, that your middeleware will run for every request and add your facebook profile object to request for every request of a logged in user. So using middleware for an object that do not used often is not a good idea.
Option 1. Delegate the context processor's work to another function, and call that function.
You're already using middleware.
https://docs.djangoproject.com/en/1.3/topics/http/middleware/#middleware
You just need to implement process_request and it's done in every request.
https://docs.djangoproject.com/en/1.3/topics/http/middleware/#process_request

Categories