How I store an instance of a connection in twisted.web? I have seen request.getSession() but I searched and there are very few examples of how it is stored and retrieved later.
Thanks.
Update:
I want to store the ldap connection in a session for retrieve later
def render_POST(self, request):
command = request.path[1:]
session = request.getSession()
if command == "authentication":
Connect = LdapConnection(request.args['host'][0],request.args['user'][0],request.args['password'][0])
session.addComponent(LdapConnection, Connect)
if command == "users":
Connect = session.getComponent(LdapConnection)
u = Users(Connect, request.args['name'][0],request.args['employeeNumber'])
return
There are plenty of examples in the documentation of twisted. If you prefer a quick summary on how to use sessions.
from twisted.web.resource import Resource
class ShowSession(Resource):
def render_GET(self, request):
return 'Your session id is: ' + request.getSession().uid
class ExpireSession(Resource):
def render_GET(self, request):
request.getSession().expire()
return 'Your session has been expired.'
resource = ShowSession()
resource.putChild("expire", ExpireSession())
Do not forget that request.getsession() will create the session if it doesn't already exists. This tutorial explains how to store objects in session.
cache()
from zope.interface import Interface, Attribute, implements
from twisted.python.components import registerAdapter
from twisted.web.server import Session
from twisted.web.resource import Resource
class ICounter(Interface):
value = Attribute("An int value which counts up once per page view.")
class Counter(object):
implements(ICounter)
def __init__(self, session):
self.value = 0
registerAdapter(Counter, Session, ICounter)
class CounterResource(Resource):
def render_GET(self, request):
session = request.getSession()
counter = ICounter(session)
counter.value += 1
return "Visit #%d for you!" % (counter.value,)
resource = CounterResource()
Related
I am using the python requests library to intereact with an api.
I am first authenticating, getting a session-id and then creating a request session to persist that connection.
So I created a class to do this, but every time I use the class I am reinitialising and doing the authentication again. Which I want to avoid.
Essentially I created an API between the API I am calling using DRF.
How can I ensure that only 1 authenticated session is used across the entire app and that it persists through multiple request?
The class:
class RestClient:
session = None
def create_rest_client(self):
auth = requests.auth.HTTPBasicAuth(
USERNAME,
PASSWORD
)
response = requests.post(
f'https://{ settings.HOST }/rest/session',
auth=auth
)
session = requests.Session()
session_id = response.json().get('value')
session.headers.update({'api-session-id': session_id})
return session
def get_rest_client(self):
if self.session:
return self.session
else:
return self.create_rest_client()
Using the class I instantiate and get the client (naturally redoing the auth). I think this should either be global or a singleton.
Using class:
class ProductDetail(APIView):
def get(self, request, format=None, **kwargs):
response = []
rest_client = RestClient()
session = rest_client.get_rest_client()
response = session.get(
....use authenticated session
)
return Response(response.json())
I'd wire up a property like this:
class RestClient:
_session = None
#property
def session(self):
if self._session:
return self._session
auth = requests.auth.HTTPBasicAuth(USERNAME, PASSWORD)
response = requests.post(
f"https://{ settings.HOST }/rest/session", auth=auth
)
session = requests.Session()
session_id = response.json().get("value")
session.headers.update({"api-session-id": session_id})
self._session = session
return session
Now you can simply do client.session and it will be set up on the first access and reused thereafter.
EDIT: To persist this between RestClient instances, change references to self._session to RestClient._session.
Now I am creating new connection to SQLite db each time I edit username. What should I do to make a single connection for a whole application?
class UserEditHandler(tornado.web.RequestHandler):
def get(self, user_id):
self.render('user_edit.html')
def post(self, user_id):
edited_name = str(self.get_arguments('name')[0])
session = create_session()
user_object = session.query(User).filter_by(id=user_id).first()
user_object.name = edited_name
session.commit()
There are couple solutions:
wrap it in some singleton class (as Nikos noted)
wrap it in separate module with global session and function get_session (effectively the same as class singleton, but in module scope)
handle db in Application class, that is injected in RequestHandler
I would recommend third one:
import tornado
class MyApp(tornado.web.Application):
def __init__(self, *args, **kwargs):
super(MyApp, self).__init__(*args, **kwargs)
# or even initilaize connection
self._db = None
#property
def db(self):
if self._db is None:
self._db = create_session()
# additionally you can check here if session is time-outed or something
return self._db
class UserEditHandler(tornado.web.RequestHandler):
def get(self, user_id):
self.render('user_edit.html')
def post(self, user_id):
edited_name = str(self.get_arguments('name')[0])
user_object = self.application.db.query(User).filter_by(
id=user_id
).first()
user_object.name = edited_name
self.application.db.commit()
One another option is to add a connection to your app settings, it will be accessible in all classes inherited form RequestHandler or WebSocketHandler.
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r"/", UserEditHandler)
],
settings = dict(
db_session = create_session()
)
class UserEditHandler(tornado.web.RequestHandler):
def get(self, user_id):
self.render('user_edit.html')
def post(self, user_id):
edited_name = str(self.get_arguments('name')[0])
session = self.settings['db_session']
user_object = session.query(User).filter_by(id=user_id).first()
user_object.name = edited_name
session.commit()
if __name__ == "__main__":
app = Application()
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Also make sure to check out tornado demos for more insights https://github.com/tornadoweb/tornado/tree/master/demos
I'm learning how to implement user login in GAE following the instruction in http://gosurob.com/post/20024043690/gaewebapp2accounts.
Below is a portion of the code that creates a user aware handler that my other handlers are supposed to inherit. This allows me to simply return user info by self.user. Now my question is how do I retrieve the user info in a ndb class which obviously inherits ndb.Model rather than BaseHandler. Please advise. Thanks!
class BaseHandler(webapp2.RequestHandler):
def dispatch(self):
# Get a session store for this request.
self.session_store = sessions.get_store(request=self.request)
try:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self)
#super(BaseHandler,self).dispatch()
finally:
# Save all sessions.
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def auth(self):
return auth.get_auth(request=self.request)
#webapp2.cached_property
def user(self):
user = self.auth.get_user_by_session()
return user
#webapp2.cached_property
def user_model(self):
user_model, timestamp = self.auth.store.user_model.get_by_auth_token(
self.user['user_id'],
self.user['token']) if self.user else (None, None)
return user_model
class Global_Var(ndb.Model): #<<< This is the ndb class from which I want to use the user info.
current_user = ndb.StringProperty()
#staticmethod
def get_id():
return user['email'] #<<< This, of course, errors out since user is not defined in this class
I am new to Python and MongoDB environment. I am implementing a small application in Python with Tornado + MongoDB. I want to store sessions in mongoDB.
In server.py
import os
import tornado.web
import tornado.ioloop
import settings
application = tornado.web.Application(
settings.urls,
my_template_path,
my_static_path
)
if __nam__ == '__main__':
application.listen(8000)
tornado.ioloop.IOLoop.instance().start()
In settings.py
import handler as H
urls = [
(r"/", H.ShowHome),
(r"/login", H.ShowLogin),
(r"/dashboard", H.ShowDashboard)
]
In handler.py
import os
# import session or some library ????
class ShowHome(tornado.web.RequestHandler):
SESSION = False
def initialize(self):
#
# check session related things here
#
# self.SESSION = True or False based on session cookie
def get(self):
if not self.SESSION:
self.redirect('/login')
else:
self.render('index.html')
class ShowLogin(tornado.web.RequestHandler):
SESSION = False
def initialize(self):
#
# check session related things here
#
# self.SESSION = True or False based on session cookie
def get(self):
if self.SESSION:
self.redirect('/dashboard')
else:
self.render('login.html')
class ShowDashboard(tornado.web.RequestHandler):
SESSION = False
def initialize(self):
#
# check session related things here
#
# self.session = True or False based on session cookie
def get(self):
if not SESSION:
self.redirect('/login')
else:
self.render('dashboard.html')
In handlers I want to check session, how do I do this?
Do you mean something like this?
class Base(tornado.web.RequestHandler):
def get_unique_id(self):
return self.get_secure_cookie('unique_id')
def set_unique_id(self, some_value):
return self.set_secure_cookie('unique_id', some_value)
class ShowLogin(Base):
def get(self):
if get_unique_id():
# Get stuff from Mongo using unique_id
# mongo calls
self.redirect('/dashboard')
else:
self.render('login.html')
class LoginLogin(Base):
def post(self):
self.set_unique_id(some_id)
You probably dont want to do this though - Let Tornado handle if someone is logged in or out with the authenticated decorator
And unless you are holding a lot of data or very sensitive data it's normal (and easier) to put session data in the cookies
I have a simple NDB model:
from google.appengine.ext import ndb
import logging
from libs import Api
class User(ndb.Model):
oauth_token = ndb.StringProperty(required=False, indexed=False)
#classmethod
def update_data(self):
logging.info("uid = %s, oauth token = %s" % (self.key, self.oauth_token))
api = Api.Init(self.oauth_token)
In a separate file test.py, I have the following code:
from models import User
from google.appengine.ext import webapp, ndb
import logging
class Test(webapp.RequestHandler):
def get(self):
uid = 1
u = ndb.Key(User, str(uid)).get()
logging.info("uid = %s, oauth token = %s" % (u.key.string_id(), u.oauth_token))
u.update_data()
Here's the output in the log:
INFO 2012-07-22 16:32:42,532 test.py:8] uid = Key('User', '1'), oauth token = xxxxxxxxxxxxxxxxxxx
INFO 2012-07-22 16:32:42,532 user.py:9] uid = ModelKey('__key__'), oath token = StringProperty('oauth_token', indexed=False)
Why am I getting StringProperty('oauth_token', indexed=False) instead of the actual property's value?
update_data is decorated with #classmethod, which means that self in update_data is a reference to the User class, instead of an instance method. Just remove #classmethod.