from django.db import models from django.contrib.auth.models import User import datetime class Account(models.Model): """ I'm using doctests, because they keep everything in one file. If I make a lot of tests, I'd break it out into a separate file. But this is a one file coding sample, so I wont do that. Account is simply the twitter specific bits to add on to the regular Django User class. manages a set of tweets, keeps track of following, etc. First thing we need is a couple Django Users to add our Account objects to. >>> user1 = User(username="user1") >>> user1.save() >>> user2 = User(username="user2") >>> user2.save() Then we make some accounts, also pretty boring. >>> account1 = Account(user=user1) >>> account1.save() >>> account2 = Account(user=user2) >>> account2.save() Make some tweets to play around with... >>> account1.new_tweet("Twiddle twiddle tweet tweet.") >>> account1.new_tweet("Inconsequential twaddle.") Make sure the tweets got made. >>> tweets = Tweet.objects.all() >>> tweets[0].owner.user.username u'user1' Get a list of the user's current tweets. >>> len(account1.get_latesttweets()) 2 Make sure account2 doesn't get account1's tweets... >>> account2.get_latesttweets() [] Make sure an account can see the tweets from the accounts it's following >>> account2.get_followingtweets() [] >>> account2.add_follower(account1) >>> account2.get_followingtweets() [, ] Also ensure that following is not necessarily reciprocal >>> account1.get_followingtweets() [] """ def __unicode__(self): return self.user.username user = models.ForeignKey(User, unique=True) # manytomany, so following isn't reciprocal following = models.ManyToManyField('self', null=True ) def new_tweet(self, tweet): tweet = Tweet(owner=self, message=tweet, time_stamp=datetime.datetime.now()) tweet.save() def get_latesttweets(self): # performance -- values() is much faster than building an object... # and this would probably just be used to display a list of tweets, # you'd want to generate objects if you want to do manipulation. # (Oh how I've learned this lesson) return self.tweets.all().values() def add_follower(self, follower): self.following.add(follower) # may be backwards? need to test def get_followingtweets(self): return Tweet.objects.filter(owner__in=self.following.all())[:20] def get_favorites(self): return self.favorites.all() class Tweet(models.Model): """ >>> account1 = Account.objects.get(user__username='user1') >>> account2 = Account.objects.get(user__username='user2') Get some tweets to play with... >>> tweets = Tweet.objects.filter(owner=account1) >>> len(tweets) 2 Test that the ordering is correct, from the Meta class... tweet[0].time_stamp < tweet[1].timestamp 1 Add a tweet to account2's favorites >>> tweets[0].favorite_of(account2) And make sure it gets stored... >>> account2.get_favorites() [] """ owner = models.ForeignKey('Account', related_name='tweets') message = models.CharField(max_length=140) # I don't know why I originally made this one a ForeignKey, # but ManyToMany is the right choice here... favoriteof = models.ManyToManyField('Account', null=True, related_name='favorites') mentions = models.ForeignKey('self', null=True) time_stamp = models.DateTimeField() # auto_now_add is deprecated... class Meta: ordering = ('-time_stamp',) def favorite_of(self, account): self.favoriteof.add(account)