Django: Context processors in views, bad practice? - python

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

Related

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.

Tornado - Python global variable

I'm trying to use Tornado with SqlAlchemy, I need to pass the current user from RequestHandler (tornado) to models (SqlAlchemy) in the insert or update action. But I don't want to pass the value directly to the model, example:
#### RequestHandler POST method...
user = Session.query(User).get(1)
user.name = "bla, bla, bla..."
user.updated_by = self.current_user # don't use...
session.commit()
I'm using a global variable, in a __ init__.py file, and set the current user value in the RequestHandler and after, get the value, in before update event with SqlAlchemy.
The idea is to know what user is the creator and updater.
Why I don't want pass the current user directly to model like the before example ?, because this will be a tool for other developers, and I'm trying to make comfortable for them, also, they can forget about it and it is important.
Is this a good idea, or maybe is there other better way ?
Your solution will have issues if you're handling more than one request at a time. Tornado is an async web framework so another request might overwrite your global var and set the user to someone else. It's good practice to store request depending data on self, tornado will make sure that data is altered by other simultaneous requests.
A solution that might work for you is to add your tool in the basic handler or create a decorator. It's tricky to sugest more details, please include more info in your question if you would like to get better alternatives.
The current user is available in every handler (and template). How you determine, authenticate and set the current user is up to you.
Basically just subclass tornado.web.RequestHandlerand override the get_current_user method in your new/own BaseHandler.
Here the quote from the tornado docs:
tornado User authentication
User authentication
The currently authenticated user is available in every request handler as self.current_user, and in every template as current_user. By default, current_user is None.
To implement user authentication in your application, you need to override the get_current_user() method in your request handlers to determine the current user based on, e.g., the value of a cookie. Here is an example that lets users log into the application simply by specifying a nickname, which is then saved in a cookie.
You can see a fully working example in the official tornado blog demo

Webapp2 + WTForms issue: How to pass values and errors back to user?

I am having a problem with webapp2 and wtforms. More specifically I have defined two methods in two different handlers, called:
create, which is a GET method listening to a specific route
save, which is a POST method listening to another route
In the save method I validate my form and if fails, I want to redirect to the create method via the redirect_to method, where I can render the template with the form. Is this possible with any way? I found an example on how this can be done if the same handler with get and post methods, but is this possible in methods of different handlers?
Thanks in advance!
I think this will work if the routes are part of the same app.
But why not using a single handler with get and put and a method _create, which can be called (self._create instead of a redirect) by get and put to render the template with the form. It is faster than a browser redirect and you can pass arguments in an easy way.

How do I display a confirmation message after a custom admin action with an intermediate page (in Django)?

The built-in actions that come with the Django admin generally display a helpful message after they execute at the top, e.g. saying that a new object was added or what have you.
The docs show how to do it with simple actions that can be represented as methods of the custom ModelAdmin. However, with custom actions that need intermediate pages (covered further down on that same page), I am encouraged to pass the user onto another view. That's great, but it means that I no longer have access to the custom ModelAdmin instance in order to call its message_user() method... Or at least I'm not sure how to get it.
Can you tell me how to get a hold of the current ModelAdmin instance or, if there's a better way, how else to display one of those helpful little messages when I'm done in the other view?
To mimic the ModelAdmin.message_user method you only need to do the following:
from django.contrib import messages
messages.info(request, message)
Adding a message is documented here https://docs.djangoproject.com/en/dev/ref/contrib/messages/#adding-a-message and the way ModelAdmin uses it can be seen here: https://code.djangoproject.com/browser/django/trunk/django/contrib/admin/options.py#L691
Construct a LogEntry and write a custom templatetag to render messages on your intermediat page, for instance:
LogEntry.objects.log_action(
user_id=request.user.id,
content_type_id=ContentType.objects.get_for_model(yourmodel).pk,
object_id=case.id,
object_repr=force_unicode(yourmodel),
action_flag=ADDITION if created else CHANGE)
read more: Django docs (Message Framework)

Setting attributes on the request object when testing a django view

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

Categories