Facebook is migrating to HTTPS and OAuth to increase the safety of their users. Unfortunately these changes aren’t backwards compatible and will require some effort to follow. To support the new Facebook system you need to upgrade to Django Facebook 3.0 before October 1st.
In addition to the required migrations, this version also includes several new features. The largest change is the underlying Facebook API client. You can read about the improvements here or skip down to the upgrade instructions.
Open Facebook – New Python Facebook client
Open Facebook is a python client to the Facebook graph API. Currently it’s included in Django Facebook, but in time it will be spun of as a separate project. The client is supported, tested and up to date with the current version of Facebook’s graph API.
It handles connection issues cleanly and raises separate error classes for various Facebook error scenarios.
The syntax is very straightforward to use:
open_facebook = OpenFacebook(token)
#info about me
open_facebook.me()
#retrieving a page
open_facebook.get('fashiolista')
#retrieving your albums
open_facebook.get('me/albums')
#posting a message on your wall
open_facebook.set('me/feed', message='Check out Fashiolista', picture=image_url)
#setting a like
open_facebook.set('fashiolista/likes')
#fql example
result = open_facebook.fql('SELECT name FROM user WHERE uid = me()')
#authorization is handled separately from the API class
token = FacebookAuthorization.get_app_access_token()
test_user = FacebookAuthorization.create_test_user(token)
Album upload Example
Uploading pictures to Facebook is as simple as this:
open_facebook = get_facebook_graph(request)
photo_urls = [
'http://d.fashiocdn.com/images/entities/0/6/t/p/d/0.365x365.jpg',
'http://e.fashiocdn.com/images/entities/0/5/E/b/Q/0.365x365.jpg',
]
for photo in photo_urls:
uploaded = open_facebook.set('me/photos', url=photo,
message='Fashiolista is awesome', name='FashiolistaTest'
)
So there are good reasons to upgrade even if Facebook didn’t force us to :)
How to upgrade to 3.0
First Step – Install Django Facebook 3.0
Follow the installation instructions.
Javascript changes
In your Facebook initialization code enable OAuth.
FB.init({appId: facebookAppId, status: false, cookie: true, xfbml: true, oauth: true});
Perms has been renamed to scope.
FB.login(function() {}, {'scope' : 'offline_access'});
Django Facebook changes
The get_facebook_graph function is no longer persistent by default, if you want the old behavior use get_persistent_graph.
Furthermore the FacebookUserConverter class and the core Facebook API client are now separated. get_facebook_graph returns the core facebook API client. To go from the API class to the user converter class use something like
graph = get_facebook_graph(request) facebook = FacebookUserConverter(graph)
That should be all.
If you are encountering problems feel free to let me know in the comments.
Last Step – Enable the new Facebook Migrations
Go to the Facebook Apps page and enable the OAuth migration.
Select your app -> About -> Advanced -> Migrations
Enable Force OAuth
Enable OAuth Migration
Background reading
Moving to OAuth 2.0 + HTTPS
Updated JavaScript SDK and OAuth 2.0 Roadmap
New Facebook Authentication Docs
PHP SDK v.3.1.1
PHP SDK v3.0.0
We’re hiring!
Do you also see the beauty in clean code? Are you experienced with high scalability web apps? Currently we’re looking for additional talent over at our Amsterdam office. Feel free to drop me a line at my personal email for more information: thierryschellenbach[at]gmail.com
Mellow Morning » Django Facebook 3.0 – OAuth migration – Time to … | Pici Blog responded on 15 Aug 2011 at 1:30 am #
[...] the original here: Mellow Morning » Django Facebook 3.0 – OAuth migration – Time to … This entry was posted in Uncategorized and tagged and-will, https, increase-the, require-some, [...]
Dexter Holiday responded on 07 Sep 2011 at 7:01 am #
Hey there, this is by far the best FB hook I’ve seen, and I’ve (over the last weel) installed and played with all of them. I struggled to get photos posting to a users Photo Album, but you solved it in a few lines of code. Thank you.
I do have one query though, apologies if this isn’t the time or place.
I’m building a Facebook Application, served through an iFrame, but struggling with two things.
– Can django-facebook tell me if the user “Likes” the page?
– How do I pass around the token from page to page, what are the initial steps? Ie: my opening page for the Facebook App asks ‘graph = get_persistent_graph(request)’, then later down the track I’m trying to hook into their Facebook Albums. Every now and then it fails.
Any example code would be amazing, I’m still new to the FB hookups.
Thanks again …
Thierry Schellenbach responded on 07 Sep 2011 at 10:22 am #
Testing if a user likes a page is very easy
just do
fb.get(‘me/likes/fashiolista’)
docs are here
http://developers.facebook.com/docs/reference/api/user/#likes
example output
http://developers.facebook.com/tools/explorer/?method=GET&path=me/likes/19292868552
Regarding your second question, you should indeed be using get_persistent_graph, this uses the session to save your access_token. You would need to tell me more about the error your getting, get_persistent_graph works fine over here :)
Dexter Holiday responded on 07 Sep 2011 at 1:56 pm #
Thanks Thierry,
So the ‘get_persistent_graph’ would be on the first page of my Facebook App? Then how would I reference or use the graph on other pages, the same way? I think I was receiving the error when a user returns to the first page in the iframe and the “request” was empty.
I was using:
graph = get_persistent_graph(request) on my first page, then need to access albums and such on subsequent pages:
get_albums = graph.get(‘me/albums’), Is it as simple as this? I seemed to encounter sporadic errors.
Re ‘Like’, is it possible to get the ‘Page’ title (ie: “fashiolista”) without hardcoding it into the page?
Thanks again.
jeffwong responded on 09 Sep 2011 at 8:46 pm #
I’ve been having a lot of trouble just getting to the point where I can try your nice examples of simplicity.
The install doc says that the Django registration plugin is not required, but doesn’t describe a way to avoid the requirement. I ended up on line 133 of connect.py.
Is there a way to avoid registration?
Dexter Holiday responded on 12 Sep 2011 at 4:03 am #
Thanks for the help so far.
I just can’t seem to hold onto the the ‘request’ after getting permissions.
Everytime I ask for:
graph = get_persistent_graph(request)
On a second or third page, I get a ‘Session Timed out error’
Thierry Schellenbach responded on 12 Sep 2011 at 11:44 am #
@jeff
Django Registration is required unless you want to modify the code.
Doing so is however not that hard. (will take you 1-2 days).
@dexter
Normal access tokens have a limited validity, ie they expire after some point.
If you want permanent tokens ask for the offline_access permission.
Thierry Schellenbach responded on 12 Sep 2011 at 4:36 pm #
PS, support for offline access (well it’s supported now, but automatic support, without you manually having to store the access token somewhere)
is scheduled for version 3.1
Expect that in the coming weeks
Jason responded on 03 Oct 2011 at 9:44 pm #
There is a bug in the version of Chrome I am using. (Developer Channel)
Facebook’s login pop up does not close. The app is authenticated on Facebook’s side but the site does not receive confirmation.
In case you missed it or it reaches release version, this code fixes it; although, the popup remains open.
facebookAppId = ‘{{ FACEBOOK_APP_ID }}’;
function facebookJSLoaded(){
FB.init({appId: facebookAppId, status: false, cookie: true, xfbml: true, oauth: true});
// Browser-specific hacks to make FB Connect more reliable
$.browser.chrome = /chrome/.test(navigator.userAgent.toLowerCase());
if ($.browser.chrome || $.browser.msie) {
FB.XD._origin = window.location.protocol + “//” + document.domain + “/” + FB.guid();
FB.XD.Flash.init();
FB.XD._transport = “flash”;
} else if ($.browser.opera) {
FB.XD._transport = “fragment”;
FB.XD.Fragment._channelUrl = window.location.protocol + “//” + window.location.host + “/”;
}
}
window.fbAsyncInit = facebookJSLoaded;
F = new facebookClass(facebookAppId);
F.load();
Source: https://gist.github.com/1013530
Ian Wilson responded on 07 Oct 2011 at 8:46 pm #
I must have done something badly wrong as the installation instructions seemed simple but I have had many, many issues (would be great to change the docs to show that registration *is* required).
Right now I am my problem is that my login flow, for a new user, seems to do this:
1. Register user (connect 174)
2. Update user (connect 178)
3. get user profile (connect 198)
It fails at 3 because a UserProfile has not yet been created.
Is that the normal flow (I am sure it cannot be)?
I wonder where I am going wrong?
(I used the abstract FacebookProfile class. I copied the folder into my project but did not “install”, in case that is a problem).
Ideas welcome, thanks!
Thierry Schellenbach responded on 12 Oct 2011 at 1:36 pm #
Hey Ian,
Django is usually setup to create a user profile when a user is created. This might be weird if you’re not already working with a system like that.
Registration is indeed required, I will update the docs to update that.
@Jason
Thanks for the bugreport, I still expect that they will fix this before release.