tutorial app engine and facebook connect
Unfortunately, there is not much built in support for PyFacebook in Google App Engine, and very few tutorials about it. This is a brief tutorial to explain how to get Facebook Connect working with Google App Engine.
If you want to jump straight to the source code, download google_app_engine_facebook_connect_python.zip.
SETUP GOOGLE
To get started, you need to make sure you have signed up for Google App Engine, downloaded the SDK, and added an application to your account. The Google App Engine Launcher is a great way to develop for app engine. It's a convenient tool that allows you to test locally, and deploy to your app engine appspot quickly. For the purpose of our tutorial, we'll refer to the Facebook Connect app engine project as gae-facebook-connect.
SETUP FACEBOOK
After setting up your Google App Engine account, you'll need to create a Facebook Application. Don't worry too much about step 2 (the xd_receiver.html step), as I've included an xd_receiver.html file in the tutorial zip at the end of this tutorial. Once we're set up, we need to setup the Facebook Connect URL for our app engine.
INSTALL PYFACEBOOK
Now that we have both Google App Engine and Facebook Connect setup, let's configure Facebook's Python library (appropriately named PyFacebook). In order to use PyFacebook with Google App Engine, you need to make a modification to the __init__.py file in PyFacebook's facebook directory. Add the following code to the Facebook class in __init__.py.
def check_connect_session(self, request):
"""
For use in a facebook Connect application running in Google App Engine
Takes a Google App Engine Request
http://code.google.com/appengine/docs/webapp/requestclass.html
and determines if the current user has a valid session
"""
# our session is stored in cookies - validate them
params = self.validate_cookie(request.cookies)
if not params:
return False
if params.get('expires'):
self.session_key_expires = int(params['expires'])
if 'session_key' in params and 'user' in params:
self.session_key = params['session_key']
self.uid = params['user']
else:
return False
return True
def validate_cookie(self, cookies):
"""
Validates parameters passed to a Facebook connect app through cookies
"""
# check for the hashed secret
if self.api_key not in cookies:
return None
# create a dict of the elements that start with the api_key
# the resultant dict removes the self.api_key from the beginning
args = dict([(key[len(self.api_key) + 1:], value)
for key, value in cookies.items()
if key.startswith(self.api_key + "_")])
# check the hashes match before returning them
if self._hash_args(args) == cookies[self.api_key]:
return args
return None
This trick is documented on the Facebook developer forums. For convenience, you can copy __init__.py into the root directory of your app engine project (where your main.py is), and call it facebook.py. This is not required, but it's the structure of the tutorial zip.
WRITE APP
Now that we've got the PyFacebook library configured properly, all that's left to do is write our Facebook Connect login app. First, make your app.yaml read like so.
application: gae-facebook-connect version: 1 runtime: python api_version: 1 handlers: - url: /static static_dir: static - url: /.* script: main.pyThe static directory is where any images, css, js, etc goes. In our case, this is where the xd_receiver.html will sit. The application value should be whatever your application is called on Google App Engine.
Next, we need to write main.py to.
#!/usr/bin/env python
import wsgiref.handlers
import os
import facebook
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext import db
class BaseHandler(webapp.RequestHandler):
def get(self):
self.API_KEY = ''# YOUR API KEY
self.SECRET_KEY = ''# YOUR SECRET KEY
self.facebookapi = facebook.Facebook(self.API_KEY, self.SECRET_KEY)
if not self.facebookapi.check_connect_session(self.request):
self.tpl('login.html')
return
try:
self.user = self.facebookapi.users.getInfo(
[self.facebookapi.uid],
['uid', 'name', 'birthday', 'relationship_status'])[0]
except facebook.FacebookError:
self.tpl('login.html')
return
self.get_secure()
def tpl(self, tpl_file, vars = {}):
vars['apikey'] = self.API_KEY
path = os.path.join(os.path.dirname(__file__), 'templates/' + tpl_file)
self.response.out.write(template.render(path, vars))
class MainHandler(BaseHandler):
def get_secure(self):
template_values = {
'name': self.user['name'],
'birthday': self.user['birthday'],
'relationship_status': self.user['relationship_status'],
'uid': self.user['uid']
}
self.tpl('index.html', template_values)
def main():
application = webapp.WSGIApplication([('/', MainHandler)], debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
There is a lot of boilerplate here, but the basic functionality is that MainHandler takes all requests to the root domain. The get() function is called, which is in the BaseHandler. The BaseHandler will check to see if the user is logged in. If the user is logged in, BaseHandler will call get_secure() in MainHandler, which will print the index.html template. If the user is not logged in, BaseHandler will print the login.html template.
Let's look at login.html.
<html>
<body>
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US" type="text/javascript"><script>
<script type="text/javascript">FB.init("{{ apikey }}", "/static/xd_receiver.html");</script>
<fb:login-button v="2" onlogin='window.location="/";' size="large">Connect with Facebook</fb:login-button>
</body>
</html>
And now index.html.
<html>
<body>
<script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US" type="text/javascript"></script>
<script type="text/javascript">FB.init("{{ apikey }}", '/static/xd_receiver.html');</script>
Hello, {{ name }}!
<br/><br/>
<a href="#" onclick="javascript:FB.Connect.logoutAndRedirect('/')">Logout</a>
</body>
</html>
It should be fairly obvious what these two html files are doing. If you don't know what XFBML is, read here.
CONCLUSION
That's all! Just deploy your app, and you should be able to log in and out of your Facebook Connect Google App Engine app.
LINKS
google_app_engine_facebook_connect_python.zip
Google App Engine
Facebook Developer Tools
Facebook XFBML
Facebook Application Setup
PyFacebook
PyFacebook App Engine Patch
blog comments powered by Disqus
