Generic Foreign Keys and other tools for Django-Tastypie
Python
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
tastypie_generic
.gitignore
README.md
setup.py

README.md

tastypie-generic

Generic Foreign Keys and other basic tools for Django-Tastypie


NOTE: tastypie-generic has been integrated into toastdriven/django-tastypie, so this repo is DEPRECATED.

Installation

Run pip install tastypie-generic and add tastypie_generic to your INSTALLED_APPS.

Use

Generic Foreign Keys

Generic foreign keys can be plugged-in and used much as standard ForeignKeys, with the exception being that the to field takes in a dictionary, mapping models to resources, rather than a resource

GenericForeignKeyField(to, attribute[, **kwargs]):

  • to: a dictionary mapping models to resources (e.g { User: UserResource, Event: EventResource })
  • attribute: the name of the foreign key on the model
  • **kwargs: the standard kwargs from fields.ForeignKey

User-Edit Authorization

Often, you want to have a resource that an owner-user can edit, but anyone can view. That functionality is in UserAuthorization

UserAuthorization(attribute):

  • attribute the attribute of the user who can edit the resource (e.g. created_by).

Example:

Imagine I'm building an app where users can follow people or events. We keep track of a follow object which has created_by: the user following and content_object: the object followed. It also has notes, just for fun. The owner of a Follow (i.e. the User specified by created_by) can edit it, and anyone can view any follow.

models.py:

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.contrib.auth.models import User

class Follow(models.Model):
    created_by = models.ForeignKey(User, related_name="follows")
    content_type = models.ForeignKey(ContentType, related_name="follows")
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    notes = models.TextField()

api/resources.py:

from tastypie import fields
from tastypie.constants import ALL, ALL_WITH_RELATIONS
from tastypie.resources import Resource, ModelResource
from ..models import Follow
from tastypie_generic.authorization import UserAuthorization
from tastypie_generic.fields import GenericForeignKeyField
from django.contrib.auth.models import User
from myapp.models import Event
from myapp.api.resources import UserResource, EventResource

class FollowResource(ModelResource):

    created_by = fields.ForeignKey(UserResource, 'created_by')
    content_object = GenericForeignKeyField({
        User: UserResource,
        Event: EventResource,
    }, 'content_object')

    def obj_create(self, bundle, request, **kwargs):
        return super(FollowResource, self).obj_create(bundle, request, created_by=request.user)
    def obj_update(self, bundle, request, **kwargs):
        return super(FollowResource, self).obj_update(bundle, request, created_by=request.user)

    class Meta:
        queryset = Follow.objects.all().select_related()
        allowed_methods = ['get', 'put', 'post', 'delete']
        excludes = ['object_id']
        authorization = UserAuthorization('created_by')

Credits and Thanks

A huge thanks to David Hatch whose fork inspired the GenericForeignKeyField code.

Also to the django-tastypie team for continuing to work on an awesome piece of software, and particularly to Josh Bohde for answering my questions.