django-classfaves

A different approach to favorites in Django
Download

django-classfaves Ranking & Summary

Advertisement

  • Rating:
  • License:
  • BSD License
  • Price:
  • FREE
  • Publisher Name:
  • Eric Florenzano
  • Publisher web site:
  • http://code.google.com/u/floguy/

django-classfaves Tags


django-classfaves Description

A different approach to favorites in Django django-classfaves is a Django plugin that provides everything that you need to add favoriting abilities to your site. There are just a few steps that you need to go through to add this functionality to your site.Installation at a Glance1. Create a favorite model that has a ``ForeignKey`` to the domain object that you would like to be able to favorite or unfavorite.2. Instantiate ``CreateFavorite``, ``DeleteFavorite``, and ``UserFavorites`` in one of your url configurations, and map them into your urlpatterns.3. Integrate into your domain object's templates and views.Installation Example: Arcade SiteThis installation example comes from `Radiosox`_, for which this application was originally written. The site is a free online arcade site that allows users to mark certain games as their favorite ones. They are allowed to un-favorite those games if they change their mind. Finally, they are allowed to see a list of their favorite games.Step 1: Creating our ModelWe already have a domain object that looks a little bit like this:.. sourcecode:: python from django.db import models class Game(models.Model): name = models.CharField(max_length=64) slug = models.SlugField(max_length=64) description = models.TextField(blank=True) # ... there are many more fields hereNow what we want to do is in that same models.py file, we will create our favorite model, like shown here:.. sourcecode:: python from classfaves.models import FavoriteBase class GameFavorite(FavoriteBase): game = models.ForeignKey(Game)What this does is use our ``FavoriteBase`` abstract base class, provide by django-classfaves, and ensure that it's got a link to our ``Game`` domain object. This model is equivalent to manually writing this:.. sourcecode:: python import datetime from django.db import models from django.contrib.auth.models import User class GameFavorite(models.Model): game = models.ForeignKey(Game) user = models.ForeignKey(User) date_created = models.DateTimeField(default=datetime.datetime.now)In fact, you could write that model if you prefer. I prefer to subclass ``FavoriteBase``, since it's easier.Step 2: Attaching our ViewsIn our ``urls.py`` file for that arcade app whose models we were using in the previous step, we have something that, right now, looks like this:.. sourcecode:: python from django.conf.urls.defaults import patterns, url urlpatterns = patterns('arcade.views', url(r'^popular/$', 'popular', name='arcade_popular'), url(r'^new/$', 'new', name='arcade_new'), # ... there are more URLs here )What we want to do first is instantiate our views provided by the django-classfaves app:.. sourcecode:: python from arcade.models import GameFavorite, Game from classfaves.views import CreateFavorite, DeleteFavorite, UserFavorites create_favorite = CreateFavorite(GameFavorite, Game) delete_favorite = DeleteFavorite(GameFavorite, Game) public_games = lambda qs: qs.filter(game__enabled=True) user_favorites = UserFavorites(GameFavorite, Game, extra_filter=public_games)What this does is give us views to create, delete, and get user favorites for all games in the system. You'll note that we're passing an argument named ``extra_filter`` to ``UserFavorites`` which limits the view to only showing games with ``enabled`` set to ``True``. This can be used to limit the ``QuerySet`` arbitrarily. Kinda cool, huh?Anyway, the next step is to modify our ``urlpatterns`` so that it maps to these views:..sourcecode:: python urlpatterns = patterns('arcade.views', url(r'^popular/$', 'popular', name='arcade_popular'), url(r'^new/$', 'new', name='arcade_new'), # ... vvv THE NEW URLS ARE BELOW vvv url(r'^favorites/create/(?Pd+)/$', create_favorite, name='arcade_favorite_create'), url(r'^favorites/delete/(?Pd+)/$', delete_favorite, name='arcade_favorite_delete'), url(r'^favorites/list/$', user_favorites, name='arcade_my_favorites'), url(r'^favorites/list/(?P+)/$', user_favorites, name='arcade_user_favorites'), )Note how we were able to give the new views proper URL names, and how we were able to easily place them where they logically fit in the URL structure--under the URL space of the arcade app. Also note that we've ensured to have a ``pk`` for the create and delete views.Step 3: IntegrationAdmittedly, this part is the part where django-classfaves helps you out the least. Well, basically, django-classfaves doesn't help you out at all. The reason for this is by design: we don't know how your app is structured or how you want to use it, so we want to leave this bit completely up to you.So here's how we did it. First, on the page where you actually play the game, we want you to be able to decide that you like it and favorite it. We also wanted to make sure that you could do this while you are still playing the game, so it needed to be asynchronous using JavaScript.Our first step was to modify the view function for the game playing page...sourcecode:: python from arcade.models import GameFavorite def play(request, game_slug=None): # ... some of our view code here favorite = False if request.user.is_authenticated(): favorite = GameFavorite.objects.filter(user=request.user, game=game).count() > 0 context = { # ... other context here 'favorite': favorite, } # ... the rest of our view code hereJust a few lines of code, and we now know whether the user has a favorite on that specific domain object (the game) or not.Now, in the template, we do this with the information:..sourcecode:: python {% if user.is_authenticated %} {% if favorite %} Remove as Favorite {% else %} Add as Favorite {% endif %} {% else %} Add as Favorite {% endif %}In other words, based on whether the user is authenticated and based on whether or not they have already favorited the game, we set some classes and urls and messages on the links.We also have a bit of JavaScript, that looks like this:..sourcecode:: javascript var add_favorite_handlers = function(base_create, base_delete) { $('a.favorite.fave').live('click', function(e) { var pk = $(this).attr('id').replace('favorite_', ''); var url = base_create + pk + '/'; $.getJSON(url, function(data, textStatus) { $('#favorite_' + pk).removeClass('fave').addClass('unfave').text('Remove as Favorite'); }); return false; }); $('a.favorite.unfave').live('click', function(e) { var pk = $(this).attr('id').replace('favorite_', ''); var url = base_delete + pk + '/'; $.getJSON(url, function(data, textStatus) { $('#favorite_' + pk).removeClass('unfave').addClass('fave').text('Add as Favorite'); }); return false; }); };I'm not going to go into too much detail about this JavaScript code, except to say that it takes the base URL for the create and the delete pages, and turns links with certain classes into AJAX calls into the create and delete views.Finally, at the bottom of the page, we initialize this JavaScript like so:.. sourcecode:: htmlAnd with that, we're done! Not too bad, huh? You can browse around `Radisox` and play a game to see it in action. Look up at the top right of any game page to see the favorite/un-favorite button. Requirements: · Python · Django


django-classfaves Related Software