commit fab3d7a216de87bed8aef9830bb9d04a408859eb Author: Ryan McGrath Date: Sun Nov 7 02:14:40 2010 -0500 Initial commit; example Django application for using Twython OAuth with Twitter. Twython = Python Twitter API library/wrapper. Enjoy; a subproject of the mainline Twython effort. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..cd5b253 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2009 - 2010 Ryan McGrath + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.markdown b/README.markdown new file mode 100644 index 0000000..dafce06 --- /dev/null +++ b/README.markdown @@ -0,0 +1,71 @@ +Twython-Django (An example Django Python Twitter OAuth Application, using Twython) +========================================================================================= +OAuth is an annoying specification to work with. Twitter has an awesome and somewhat unique +real time data stream, though, and it'd be a shame to miss out on that stuff because of the warts +of a specification. + +Twython supports OAuth authentication with Twitter now, and this is a sample Django application to get +people up and running (fairly) instantly with Twitter OAuth in Django. Enjoy. + + +Requirements +----------------------------------------------------------------------------------------------------- +Django - pretty self explanatory. http://djangoproject.com/ + +Twython - the Python Twitter API wrapper of choice. + + (pip install | easy_install) twython + +...or, you can clone the repo and install it the old fashioned way. + + git clone https://ryanmcgrath@github.com/ryanmcgrath/twython.git + cd twython + sudo python setup.py install + +Twython (for versions of Python before 2.6) requires a library called +"simplejson". Depending on your flavor of package manager, you can do the following... + + (pip install | easy_install) simplejson + +Twython also requires the (most excellent) OAuth2 library for handling OAuth tokens/signing/etc. Again... + + (pip install | easy_install) oauth2 + + +Installation +----------------------------------------------------------------------------------------------------- +Copy the "twython_django_oauth" app into your project, and add it to your "INSTALLED_APPS" in your +settings.py file. If you wish to use the example template, feel free to copy that over as well. + +After you've done that, specify the following urlconf in your root urls.py: + + (r'^your_url_extension/', include('your_app.django_twitter_oauth.urls')), + +If you're using this app bare-bones (i.e, just starting out), add the following to your settings.py: + + AUTH_PROFILE_MODULE = 'django_twitter_oauth.Profile' + +(Obviously, if you've got your own custom User/Profile setup going, this should all be pretty self explanatory +to integrate into your application. The OAuth handshake flow is well documented here, as well as how to use it +with Twython calls.) + +Restart your Django app, and it should all work auto-magically. Build onwards from here if you're +just starting out, or integrate this into your existing model setup if you're already Django-savvy. + +Enjoy! + + +Need Twython Help? +----------------------------------------------------------------------------------------------------- +If you need help with the Twython library itself, check out the project on Github, it's all pretty self +contained (twython/twitter_endpoints.py contains just about every function definition you'll need): + + https://github.com/ryanmcgrath/twython + +Questions, Comments, etc? +----------------------------------------------------------------------------------------------------- +My hope is that twython-django is so simple that you'd never *have* to ask any questions, but if +you feel the need to contact me for this (or other) reasons, you can hit me up +at ryan@venodesigns.net. + +twython-django is released under an MIT License - see the LICENSE file for more information. diff --git a/templates/tweets.html b/templates/tweets.html new file mode 100644 index 0000000..a2ec453 --- /dev/null +++ b/templates/tweets.html @@ -0,0 +1,3 @@ +{% for tweet in tweets %} + {{ tweet.text }} +{% endfor %} diff --git a/twython_django_oauth/__init__.py b/twython_django_oauth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/twython_django_oauth/models.py b/twython_django_oauth/models.py new file mode 100644 index 0000000..bb3f5a1 --- /dev/null +++ b/twython_django_oauth/models.py @@ -0,0 +1,12 @@ +from django.db import models +from django.contrib.auth.models import User + +class Profile(models.Model): + """ + An example Profile model that handles storing the oauth_token and + oauth_secret in relation to a user. Adapt this if you have a current + setup, there's really nothing special going on here. + """ + user = models.ForeignKey(User) + oauth_token = models.CharField(max_length = 200) + oauth_secret = models.CharField(max_length = 200) diff --git a/twython_django_oauth/urls.py b/twython_django_oauth/urls.py new file mode 100644 index 0000000..965025a --- /dev/null +++ b/twython_django_oauth/urls.py @@ -0,0 +1,19 @@ +from django.conf.urls.defaults import * + +# your_app = name of your root djang app. +urlpatterns = patterns('your_app.django_twitter_oauth.views', + + # First leg of the authentication journey... + (r'^login/?$', begin_auth), + + # Logout, if need be + (r'^/logout?$', logout), # Calling logout and what not + + # This is where they're redirected to after authorizing - we'll + # further (silently) redirect them again here after storing tokens and such. + (r'^thanks/?$', thanks), + + # An example view using a Twython method with proper OAuth credentials. Clone + # this view and url definition to get the rest of your desired pages/functionality. + (r'^user_timeline/?$', user_timeline), +) diff --git a/twython_django_oauth/views.py b/twython_django_oauth/views.py new file mode 100644 index 0000000..c57632a --- /dev/null +++ b/twython_django_oauth/views.py @@ -0,0 +1,97 @@ +from django.contrib.auth import authenticate, login, logout +from django.contrib.auth.models import User +from django.http import HttpResponse, HttpResponseRedirect +from django.shortcuts import render_to_response +from django.contrib.auth.decorators import login_required + +from twython import Twython + +# If you've got your own Profile setup, see the note in the models file +# about adapting this to your own setup. +from your_app.twitter.models import Profile + +# Move these into your settings.py if you're feeling adventurous. +CONSUMER_KEY = "YOUR CONSUMER KEY HERE" +CONSUMER_SECRET = "YOUR CONSUMER SECRET HERE" + +def logout(request): + """ + Nothing hilariously hidden here, logs a user out. Strip this out if your + application already has hooks to handle this. + """ + logout(request) + return HttpResponseRedirect('/') + +def begin_auth(request): + """ + The view function that initiates the entire handshake. + For the most part, this is 100% drag and drop. + """ + # Instantiate Twython with the first leg of our trip. + twitter = Twython( + twitter_token = CONSUMER_KEY, + twitter_secret = CONSUMER_SECRET + ) + + # Request an authorization url to send the user to... + auth_props = twitter.get_authentication_tokens() + + # Then send them over there, durh. + request.session['request_token'] = auth_props + return HttpResponseRedirect(auth_props['auth_url']) + +def thanks(request): + """ + A user gets redirected here after hitting Twitter and authorizing your + app to use their data. + + *** + This is the view that stores the tokens you want + for querying data. Pay attention to this. + *** + """ + # Now that we've got the magic tokens back from Twitter, we need to exchange + # for permanent ones and store them... + twitter = Twython( + twitter_token = CONSUMER_KEY, + twitter_secret = CONSUMER_SECRET, + oauth_token = request.session['request_token']['oauth_token'], + oauth_token_secret = request.session['request_token']['oauth_token_secret'] + ) + + # Retrieve the tokens we want... + authorized_tokens = twitter.get_authorized_tokens() + + # If they already exist, grab them, login and redirect to a page displaying stuff. + try: + user = User.objects.get(username = authorized_tokens['screen_name']) + except User.DoesNotExist: + # We mock a creation here; no email, password is just the token, etc. + user = User.objects.create_user(authorized_tokens['screen_name'], "fjdsfn@jfndjfn.com", authorized_tokens['oauth_token_secret']) + profile = Profile() + profile.user = user + profile.oauth_token = authorized_tokens['oauth_token'] + profile.oauth_secret = authorized_tokens['oauth_token_secret'] + profile.save() + + user = authenticate( + username = authorized_tokens['screen_name'], + password = authorized_tokens['oauth_token_secret'] + ) + login(request, user) + return HttpResponseRedirect('/timeline') + +def user_timeline(request): + """ + An example view with Twython/OAuth hooks/calls to fetch data about the user + in question. Pretty self explanatory if you read through it... + """ + user = request.user.get_profile() + twitter = Twython( + twitter_token = CONSUMER_KEY, + twitter_secret = CONSUMER_SECRET, + oauth_token = user.oauth_token, + oauth_token_secret = user.oauth_secret + ) + user_tweets = twitter.getHomeTimeline() + return render_to_response('tweets.html', {'tweets': user_tweets})