How to get json data from a url using flask in python - python-2.7

I am developing an openerp module.
Someone makes a POST to a url.the POST contains json data:
{
"phone":"987654321",
"message":"this is a test",
"date": "2015/10/09 12:00:00",
}
I want to get the data from the URL,and handle the parameters inside the openerp. This is my code so far :
from flask import Flask, request
app = Flask(__name__)
class myClass():
def __init__(self):
self.HOST = "http://0.0.0.0:8069"
self.DB = 'database'
self.LOGIN = 'admin'
self.PASSWORD = 'admin'
self.phone = None
self.message = None
self.date = None
def authenticate(self):
p = {'jsonrpc': "2.0",
'method': "call",
'params': {
'db': self.DB,
'login': self.LOGIN,
'password': self.PASSWORD}
}
#app.route("/post", methods=['GET', 'POST'])
def post():
sent_obj = myClass()
sent_obj.phone = request.args.get('phone')
sent_obj.message = request.args.get('message')
sent_obj.date = request.args.get('date')
if __name__ == "__main__":
app.debug = True
app.run()
How can i use flask, so i can get the data from the url, authenticate openerp, and handle the data inside the openerp?What is the procedure i have to follow?I am really confused...

Use json.loads() to read and decode the data.
from flask import Flask,jsonify
import requests
import simplejson
import json
app = Flask(__name__)
#app.route("/")
def home():
uri = "https://api.stackexchange.com/2.0/users? order=desc&sort=reputation&inname=fuchida&site=stackoverflow"
try:
uResponse = requests.get(uri)
except requests.ConnectionError:
return "Connection Error"
Jresponse = uResponse.text
data = json.loads(Jresponse)
displayName = data['items'][0]['display_name']# <-- The display name
reputation = data['items'][0]['reputation']# <-- The reputation
return Jresponse
if __name__ == "__main__":
app.run(debug = True)

Use the following code:
json.loads(request.data)

Related

How to test a non-view function in a Flask app factory?

I'm using the factory pattern in Flask. This is a simplified version of my code:
def create_app():
app = Flask(__name__)
#app.before_request
def update_last_seen():
if current_user.is_authenticated:
current_user.update(last_seen=arrow.utcnow().datetime)
#app.route('/', methods=['GET'])
def home():
return render_template("home.html")
return app
I'm using pytest-flask and I would like to be able to write a test for the update_last_seen function.
How can I access that function? I can't find it in client.application (client being a fixture auto-used through pytest-flask), nor in my app fixture that I set through conftest.py like so:
#pytest.fixture
def app():
os.environ["FLASK_ENV"] = "test"
os.environ["MONGO_DB"] = "test"
os.environ["MONGO_URI"] = 'mongomock://localhost'
app = create_app()
app.config['ENV'] = 'test'
app.config['DEBUG'] = True
app.config['TESTING'] = True
app.config['WTF_CSRF_ENABLED'] = False
return app
So when I run this test:
def test_previous_visit_is_stored_in_session(app, client):
app.update_last_seen()
The error I get is:
def test_previous_visit_is_stored_in_session(app, client):
> app.update_last_seen()
E AttributeError: 'Flask' object has no attribute 'update_last_seen'
I've been looking through app.before_request_funcs too, but to no avail unfortunately.
Referring to the docs, you can manually run the pre-processing of a request.
initial_last_seen = current_user.last_seen
with app.test_request_context('/'):
app.preprocess_request()
assert current_user.last_seen != initial_last_seen # ...for example

Setting up flask test_client

I am trying to test my flask app but I am getting this error
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in a way. To solve
this set up an application context with app.app_context(). See the
documentation for more information.`
I have tried understanding the error but all I kknow is that there is a client instance that should be instantiated to be used in testing. Help.
My code:
import unittest
from flask import jsonify
class TestAuth(unittest.TestCase):
"""Class for testing all the API endpoints"""
def setUp(self):
"""Initializing a test client and making the environment a testing one"""
app.app.config['TESTING'] = True
self.app = app.app.test_client()
self.app.testing = True
def sign_in(self, email='user#gmail.com', password='testpass'):
user_data = jsonify({"email": email, "password": password})
return self.app.post('/api/v1/auth/signup/', data=user_data)
def log_in(self, email='user#gmail.com', password='testpass'):
user_data = jsonify({"email": email, "password": password})
return self.app.post('/api/v1/auth/login/', data=user_data)
def test_home_status_code(self):
result = self.app.get('/api/v1/')
self.assertEqual(result.status_code, 200)
def test_signin_status_code(self):
result = self.sign_in()
self.assertEqual(result.status_code, 200)
def test_login_correct_login(self):
"""test login after signing in"""
self.sign_in()
result = self.log_in()
self.assertEqual(result.status_code, 200)
self.assertIn(b'Success', result.message)
def test_login_with_wrong_credentials(self):
"""test successful login"""
self.sign_in() # must sign in first for successful login
result = self.log_in(email='wrong#mail', password='wrongpass')
self.assertIn(b'Wrong Username or Password', result.message)
if __name__ == "__main__":
unittest.main()
try this:
def test_home_status_code(self):
with self.app as client:
result = client.get('/api/v1/')
self.assertEqual(result.status_code, 200)

How to get clean urls?

from flask import Flask, redirect, url_for, session, request, jsonify
from flask_oauthlib.client import OAuth
app = Flask(__name__)
app.config['GOOGLE_ID'] = "12"
app.config['GOOGLE_SECRET'] = "A"BC
app.debug = True
app.secret_key = 'development'
oauth = OAuth(app)
google = oauth.remote_app(
'google',
consumer_key=app.config.get('GOOGLE_ID'),
consumer_secret=app.config.get('GOOGLE_SECRET'),
request_token_params={
'scope': 'email'
},
base_url='https://www.googleapis.com/oauth2/v1/',
request_token_url=None,
access_token_method='POST',
access_token_url='https://accounts.google.com/o/oauth2/token',
authorize_url='https://accounts.google.com/o/oauth2/auth',
)
#app.route('/')
def index():
if 'google_token' in session:
me = google.get('userinfo')
return jsonify({"data": me.data})
return redirect(url_for('login'))
#app.route('/login')
def login():
return google.authorize(callback=url_for('authorized', _external=True))
#app.route('/logout')
def logout():
session.pop('google_token', None)
return redirect(url_for('index'))
#app.route('/login/authorized')
def authorized():
resp = google.authorized_response()
if resp is None:
return 'Access denied: reason=%s error=%s' % (
request.args['error_reason'],
request.args['error_description']
)
session['google_token'] = (resp['access_token'], '')
me = google.get('userinfo')
return jsonify({"data": me.data})
#google.tokengetter
def get_google_oauth_token():
return session.get('google_token')
Here when i am logging via google, my URL changes to something like this:
http://localhost:5000/login/authorized?code=4/U89v8kn76_zspiZUuZwdv01KuifACegxtt7NWBQLF3w#
What I want is what I gave in the URL
http://localhost:5000/login/authorized
What should I do?
This sounds like expected behavior for the callback portion of the auth process.
What you want to do is redirect the user to the main route at the end of the authorized() function. that function more or less "belongs" to the OAuth process (is a good way to think about it). you just determine if the process was successful and then redirect the user where they need to go.
i like to use Message Flashing to communicate with the user during this process.
example:
#app.route('/')
def index():
if 'google_token' not in session:
flash("Please log in to see this page")
return redirect(url_for('login'))
me = google.get('userinfo')
return render_template("index.html", user=me)
#app.route('/login/authorized')
def authorized():
resp = google.authorized_response()
if resp is None:
flash("Access denied: reason={0} error={1}".format(
request.args['error_reason'],
request.args['error_description']
))
return redirect(url_for("login"))
session['google_token'] = (resp['access_token'], '')
flash("Successful login!") # superfluous, just for example
return redirect(url_for("index"))
and you should see here that the session key is present (e.g. the cyrptocookie)... also obviously you should set secret key with os.urandom(24) per the docs

rauth/flask: How to login via Twitter?

The provided example in rauth is using the PIN instead of the callback. I don't understand how this should work via web callback.
1) Minor problem:
According to twitter, if oauth_callback URL is passed in, then it should be used instead whatever entry is in the https://dev.twitter.com settings. However this doesn't seem to be true, if I dont set it to http://127.0.0.1:8080/twitter/authorized it would never get to that Url after a successful authorization.
app.add_url_rule('/twitter/login', view_func=views.twitter_login)
app.add_url_rule('/twitter/authorized', 'twitter_authorized', view_func=views.twitter_authorized)
def twitter_login():
request_token, request_token_secret = twitter.get_request_token()
redirect_uri = url_for('twitter_authorized', _external=True)
params = {'oauth_callback': redirect_uri, 'request_token':request_token}
return redirect(twitter.get_authorize_url(**params))
2) Major problem is here:
I can see the request.args has both ['oauth_token'] and ['oauth_verifier'].
But I don't understand how to use them to get the twitter session for obtaining user details such as picture and display name:
def twitter_authorized():
tw_session = twitter.get_auth_session(request_token ??? , request_token_secret ???)
resp = tw_session.get("account/verify_credentials.json", params={'format':'json'})
me = resp.json()
user = User.get_or_create(...)
if user:
login_user(user)
return redirect(url_for('index'))
If someone could shed some light on this, would be highly appreciated.
Here's a working Twitter sign-in examples using Flask based on the Facebook example:
'''
twitter
-------
A simple Flask demo app that shows how to login with Twitter via rauth.
Please note: you must do `from twitter import db; db.create_all()` from
the interpreter before running this example!
'''
from flask import (Flask, flash, request, redirect, render_template, session,
url_for)
from flask.ext.sqlalchemy import SQLAlchemy
from rauth.service import OAuth1Service
from rauth.utils import parse_utf8_qsl
# Flask config
SQLALCHEMY_DATABASE_URI = 'sqlite:///twitter.db'
SECRET_KEY = '\xfb\x12\xdf\xa1#i\xd6>V\xc0\xbb\x8fp\x16#Z\x0b\x81\xeb\x16'
DEBUG = True
TW_KEY = 'oZSbVzKCeyAZTDxw1RKog'
TW_SECRET = 'TuNoqA6NzEBS3Zrb8test7bxQfKTlBfLTXsZ8RaKAo'
# Flask setup
app = Flask(__name__)
app.config.from_object(__name__)
db = SQLAlchemy(app)
# rauth OAuth 1.0 service wrapper
twitter = OAuth1Service(
name='twitter',
consumer_key=TW_KEY,
consumer_secret=TW_SECRET,
request_token_url='https://api.twitter.com/oauth/request_token',
access_token_url='https://api.twitter.com/oauth/access_token',
authorize_url='https://api.twitter.com/oauth/authorize',
base_url='https://api.twitter.com/1.1/')
# models
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
fb_id = db.Column(db.String(120))
def __init__(self, username, fb_id):
self.username = username
self.fb_id = fb_id
def __repr__(self):
return '<User %r>' % self.username
#staticmethod
def get_or_create(username, fb_id):
user = User.query.filter_by(username=username).first()
if user is None:
user = User(username, fb_id)
db.session.add(user)
db.session.commit()
return user
# views
#app.route('/')
def index():
return render_template('login.html')
#app.route('/twitter/login')
def login():
oauth_callback = url_for('authorized', _external=True)
params = {'oauth_callback': oauth_callback}
r = twitter.get_raw_request_token(params=params)
data = parse_utf8_qsl(r.content)
session['twitter_oauth'] = (data['oauth_token'],
data['oauth_token_secret'])
return redirect(twitter.get_authorize_url(data['oauth_token'], **params))
#app.route('/twitter/authorized')
def authorized():
request_token, request_token_secret = session.pop('twitter_oauth')
# check to make sure the user authorized the request
if not 'oauth_token' in request.args:
flash('You did not authorize the request')
return redirect(url_for('index'))
try:
creds = {'request_token': request_token,
'request_token_secret': request_token_secret}
params = {'oauth_verifier': request.args['oauth_verifier']}
sess = twitter.get_auth_session(params=params, **creds)
except Exception, e:
flash('There was a problem logging into Twitter: ' + str(e))
return redirect(url_for('index'))
verify = sess.get('account/verify_credentials.json',
params={'format':'json'}).json()
User.get_or_create(verify['screen_name'], verify['id'])
flash('Logged in as ' + verify['name'])
return redirect(url_for('index'))
if __name__ == '__main__':
db.create_all()
app.run()
Hope that helps!

How to send request from one django server to another server

I have a django problem. I want to send datas which are from browser or business logic
on my django server to another django server or just the same server but different port, to handle the request. How can I do? I have tried to achieve using socket,but it seems no working.
Following is my code:
accept the client's request:
def im(request):
userp = None
try:
userp = UserProfile.objects.get(user = request.user)
except:
pass
if not userp:
return HttpResponse("error")
print '111'
if request.method == "GET":
import json
msg = json.loads(request.GET.get('msg'))
try:
msg['from_id'] = userp.id
if msg.get('type', '') == 'sync': #页面同步消息
msg['to_id'] = userp.id
push_msg(msg)
return HttpResponse("success")
except:
return HttpResponse("error")
#return HttpResponseRedirect("http://127.0.0.1:9000/on_message")
return HttpResponse("error")
helper.py:push_msg:
def push_msg(msg):
print '111'
params = str(msg)
headers = {"Content-type":"application/x-www-form-urlencoded", "Accept":"text/plain"}
conn = httplib.HTTPConnection("http://127.0.0.1:9000/push_msg/")
conn.request("POST", "/cgi-bin/query", params, headers)
url(r'^push_msg/$', 'chat.events.on_message')
events.py:on_message
def on_message(request):
msg = request.POST.get('msg')
msg = eval(msg)
try:
print 'handle messages'
from_id = int(msg['from_id'])
to_id = int(msg['to_id'])
user_to = UserProfile.objects.get(id = msg['to_id'])
django_socketio.broadcast_channel(msg, user_to.channel)
if msg.get('type', '') == 'chat':
ct = Chat.objects.send_msg(from_id=from_id,to_id=to_id,content=data['content'],type=1)
ct.read = 1
ct.save()
except:
pass
use python requests module to do this requests has more features then httplib2 and it is very easy to use http://docs.python-requests.org/
I have used httplib2 to accomplish something similar. From the httplib2 documentation try:
import httplib2
import urllib
data = {'name': 'fred', 'address': '123 shady lane'}
body = urllib.urlencode(data)
h = httplib2.Http()
resp, content = h.request("http://example.com", method="POST", body=body)
You should then be able to handle the POST in your second django server, and return the appropriate results to the first django server.