I'm following this tutorial to learn how to get OAuth2.0 login onto my site, and I'm having some problems. My site is registered on GAE and I have my client ID. I also pip installed google-api-python-client. However, I don't know what to import into my project. I have two pages in my application. One that handles authorization and one that actually has the page.
authorize.py
import cgi, webapp2
from google.appengine.api import users
LOGIN_PAGE_HTML="""\
<html>
<body>
<input type="submit" method="post" action="/AuthorizeUser"/>
</body>
</html>
"""
class LoginPage(webapp2.RequestHandler):
def get(self):
self.response.write(LOGIN_PAGE_HTML)
class AuthorizeUser(webapp2.RequestHandler):
def post(self):
state = ''.join(random.choice(string.ascii_uppercase + string.digits)for x in xrange(32))
session['state'] = state
response = make_response('/LandingPage',
CLIENT_ID='MY ID',
STATE=state
APPLICATION_NAME='Summit Tech Help'))
if request.args.get('state','') != session['state']:
response = make_response(json.dumps('Invalid state parameter.'), 401)
response.headers['Content-Type'] = 'application/json'
return response
application = webapp2.WSGIApplication([
('/',LoginPage),
('/AuthorizeUser',AuthorizeUser),
], debug=True)
landing.py
import cgi, webapp2
from google.appengine.api import mail
LANDING_PAGE_HTML="""\
<html>
<body>
<p>test</p>
</body>
</html>
"""
class LandingPage(webapp2.RequestHandler):
def get(self):
self.response.write(LANDING_PAGE_HTML)
application = webapp2.WSGIApplication([
('LandingPage',LandingPage),
],debug=True)
My app.yaml has '-url: /.*' set to script:authorize.application
Any help would be much appreciated!
~Carpetfizz
to use a 3rd party module you need to import it in your app, if that's what you meant to ask,
also do check this link to use external libraries in gae.
You can check this example app for using Oauth2.0 in GAE
Related
I'm trying to get a simple web form up and running that only asks for a URL.
This is the HTML Code (index.html)
<!DOCTYPE html>
<html>
<body>
<form name = 'test' action = "." method = "post">
<form action="test.php" method="get">
URL <input type="text" link="link" name = "URL"/>
<input type="submit" />
</form>
</body>
</html>
I'm using Flask to run the simple web application this is the Flask Code: (app.py)
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route("/")
def index():
return render_template('index.html')
#app.route("/", methods = ["POST"])
def get_value():
url = request.form["URL"]
return 'The url is ' + url
if __name__ == "__main__":
app.run(debug=True)
and I'm trying to get the inputted URL to another python script so I can do something with it, this is the other python script: (url.py)
from app import get_value
print(get_value())
However, whenever I run python3 url.py it gives me this error:
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem.
Any idea how to print get the URL over successfully? In a lot of detail preferably because I am very new to Flask.
The error occurs because you called a function that needs data from a request to get the user inputs. You should call the url handling function instead letting the handling function call the retrieval of the url.
Consider this answer https://stackoverflow.com/a/11566296/5368402 to make sure you pass the url correctly. Now that you have your url, simply pass it to your other script.
import url # your url.py module
#app.route("/", methods = ["POST"])
def get_value():
input_url = request.form["URL"]
url.handle_url(input_url) #call a function inside url.py
I found code for a guestbook storing text in a datastore. I've been looking all morning to find how would i modify my code to upload a file instead of reading from the textfield. and displaying the file details after displaying it. I would appreciate any help? or maybe there's an answer already out there i just haven't found it.
Here's my code so far:
import cgi
import datetime
import urllib
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.api import users
import webapp2
class Greeting(db.Model):
author = db.UserProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
def upload_key(upload_name=None):
return db.Key.from_path('Upload', upload_name or 'default_upload')
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
upload_name=self.request.get('upload_name')
greetings = db.GqlQuery("SELECT * "
"FROM Greeting "
"WHERE ANCESTOR IS :1 "
"ORDER BY date DESC LIMIT 10",
upload_key(upload_name))
for greeting in greetings:
if greeting.author:
self.response.out.write(
'<b>%s</b> wrote:' % greeting.author.nickname())
else:
self.response.out.write('An anonymous person wrote:')
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(greeting.content))
self.response.out.write("""
<form action="/sign?%s" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Upload a File"></div>
</form>
<hr>
<form>Name: <input value="%s" name="upload_name">
<input type="submit" value="switch user"></form>
</body>
</html>""" % (urllib.urlencode({'upload_name': upload_name}),
cgi.escape(upload_name)))
class Upload(webapp2.RequestHandler):
def post(self):
upload_name = self.request.get('upload_name')
greeting = Greeting(parent=upload_key(upload_name))
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/?' + urllib.urlencode({'upload_name': upload_name}))
APP = webapp2.WSGIApplication([
('/', MainPage),
('/sign', Upload)
], debug=True)
def main():
APP.RUN()
if __name__ == '__main__':
main()
There's two basic approaches. The traditional approach, and the approach you'll find the most samples for, is the Blobstore API. The new approach is Google Cloud Storage. The advantages of the Blobstore is that there are more existing samples, but the advantage of GCS is that the same code can work outside the context of App Engine.
APPROACH 1 - BLOBSTORE API - EASIER *
Here are the official Blobstore docs with samples.
Here's a similar Stack Overflow question.
APPROACH - GOOGLE CLOUD STORAGE API - BETTER
For Google Cloud Storage, the official client library is gcloud-python. Since this is not part of the App Engine SDK, you will generally "vendor" it (include it directly in your project) before you deploy the App Engine app using pip -t flag, and modififying an appengine_config.py file. See the instructions for that in "Installing a library". The short version of the story is that you do
mkdir lib
pip install gcloud-python -t lib
then add an appengine_config.py with the follow lines:
from google.appengine.ext import vendor
# Third-party libraries are stored in "lib", vendoring will make
# sure that they are importable by the application.
vendor.add('lib')
Finally, we walk through using this API in a Python app in this tutorial
I have implemented a form using iron-form and I am able to process it in the server, but then I can't figure out how to get the response out, I cannot redirect to another page or refresh. If I remove the 'is="iron-form' then it works fine. I'm using polymer 1.0, google app engine, and jinja2 for templating.
HTML:
<div class="c-form">
<h1>"Contact us"</h1>
<p> {{ sucess-message }} </p>
<form is="iron-form" id="contact-form" method="post" action="/formhandler">
<paper-input label="Name" name="name" required></paper-input>
<paper-textarea label="Message" name="msj" required></paper-textarea>
<paper-button raised class="colorful" onclick="submitForm()">Send</paper-button>
</form>
</div>
<script>
function submitForm() {
document.getElementById('contact-form').submit();
}
</script>
main.py:
class FormHandler(MainHandler):
def post(self):
self.name = self.request.get('name')
self.msj = self.request.get('msj')
mesj = MensajesDB.new_msj(self.name, self.msj)
mesj.put()
self.respose.out.write("SUCCESS") //Here I would like to render the template,
but I can't get it to render or redirect to
another page...
class MainPage(MainHandler):
def get(self):
self.render("home.html", route="home", title="Home")
app = webapp2.WSGIApplication([
('/', MainPage),
('/formhandler', FormHandler),
], debug=True)
It seems like you might be having trouble debugging where the failure is happening. I suggest familiarizing yourself with the Chrome DevTools -- specifically, the Network tab, which will allow you to monitor the requests from your JS to your server, and then the server responses.
From your server-side application, you can access the entire request body from within your FormHandler.post method using the self.request.POST variable, as documented here.
If you want to redirect after saving to the Datastore, you'll need to remove the self.response.out.write() line and use self.redirect() instead. Note that you cannot send a response body/string and redirect in a single response.
I am trying to read and print a file in Google App Engine, but the code bellow seems unresponsive. I can upload the file, and my expectation was that it would just print the text, but it does nothing. I thought about adding a submit button, but I have no idea how to link submit with pythons printing. How can I get this to print on command?
I have seen the example provided by GAE here, but I would first like to keep it all on one page, and second I still don't understand how the submit calls that second page.
import webapp2
from google.appengine.ext.webapp import util
class MainPage(webapp2.RequestHandler):
#http://bukhantsov.org/2011/12/python-google-app-engine-calculator/
def get(self):
# build a list of operations
self.response.out.write("""<html>
<body>
<form action='/' method='get' autocomplete='off'>
<input type='file' name='file'/><br/>
#<input type='submit' name="test" value="submit">
</form>
</body>
</html>""")
file = self.request.get('file')
self.response.out.write(file)
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
def main():
util.run_wsgi_app(app)
if __name__ == '__main__':
main()
Your form is sent using the HTTP GET method, but for file uploads you need POST. Change it from:
method='get'
to:
method='post'
You will also need to handle POST requests in a different method. The POST body itself should be available as self.request.POST. So you end up with something like:
def post(self):
file = self.request.POST['file']
self.response.out.write(file)
Is it possible to create a textbox in HTML, type a string into it, click a "save" button, store that information onto a GAE datastore model and have the text stay displayed in the textbox and saved in the datastore?
The HTML is on a separate file, just rendered through my main.py file using
class MainPage(webapp.RequestHandler):
def get(self):
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
What I tried for my problem is this:
class equipmentBox(db.Model):
equipCode = db.StringProperty()
class equipmentBoxGet(webapp.RequestHandler):
def post(self):
I think this will help, i have modified default guestbook app for you. Usual way of doing is having html files separately and using templates to render it. Here everything is just embedded into the controller itself
import cgi
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class EquipmentBox(db.Model):
equipCode = db.StringProperty()
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
equips = db.GqlQuery("SELECT * FROM EquipmentBox")
for equip in equips:
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(equip.equipCode))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/post" method="post">
<div><input type="text" name="equip_code" /></div>
<div><input type="submit" value="post equipcode"></div>
</form>
</body>
</html>""")
class EquipBox(webapp.RequestHandler):
def post(self):
equip = EquipmentBox()
equip.equipCode = self.request.get('equip_code')
equip.put()
self.redirect('/')
application = webapp.WSGIApplication(
[('/', MainPage),
('/post', EquipBox)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
The best way to build this sort of interface, where the user "saves" data on the page without the page changing, is to use AJAX calls.
While a full explanation of how AJAX works is probably beyond the scope of an answer here, the basic idea is that you have a Javascript onclick event attached to your Save button, which sends the contents of your textbox via a POST request to the server. See the link above for a tutorial.