Skip to content

Commit

Permalink
Rename to django-rest-framework, get simpleexample working
Browse files Browse the repository at this point in the history
  • Loading branch information
tom christie tom@tomchristie.com committed Jan 30, 2011
1 parent 8a470f0 commit 42f2f9b
Show file tree
Hide file tree
Showing 28 changed files with 155 additions and 68 deletions.
20 changes: 12 additions & 8 deletions README.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
# To install django-rest-framework...
#
# Requirements:
# python2.6
# virtualenv
# To install django-rest-framework in a virtualenv environment...

hg clone https://tomchristie@bitbucket.org/tomchristie/django-rest-framework
cd django-rest-framework/
virtualenv --no-site-packages --distribute --python=python2.6 env
source ./env/bin/activate
pip install -r ./requirements.txt
python ./src/manage.py test
pip install -r requirements.txt

# To build the documentation...

sphinx-build -c docs -b html -d cache docs html
pip install -r docs/requirements.txt
sphinx-build -c docs -b html -d docs-build docs html

# To run the examples...

pip install -r examples/requirements.txt
cd examples
export PYTHONPATH=..
python manage.py syncdb
python manage.py runserver

File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions flywheel/emitters.py → djangorestframework/emitters.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
"""Emitters are used to serialize a Resource's output into specific media types.
FlyWheel also provides HTML and PlainText emitters that help self-document the API,
django-rest-framework also provides HTML and PlainText emitters that help self-document the API,
by serializing the output along with documentation regarding the Resource, output status and headers,
and providing forms and links depending on the allowed methods, emitters and parsers on the Resource.
"""
from django.conf import settings
from django.template import RequestContext, loader
from django import forms

from flywheel.response import NoContent
from flywheel.utils import dict2xml, url_resolves
from djangorestframework.response import NoContent
from djangorestframework.utils import dict2xml, url_resolves

from urllib import quote_plus
import string
Expand Down Expand Up @@ -193,7 +193,7 @@ def emit(self, output=NoContent, verbose=False):

class DocumentingHTMLEmitter(DocumentingTemplateEmitter):
"""Emitter which provides a browsable HTML interface for an API.
See the examples listed in the FlyWheel documentation to see this in actions."""
See the examples listed in the django-rest-framework documentation to see this in actions."""
media_type = 'text/html'
template = 'emitter.html'

Expand Down
42 changes: 30 additions & 12 deletions flywheel/modelresource.py → djangorestframework/modelresource.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from django.db.models.query import QuerySet
from django.db.models import Model

from flywheel.response import status, Response, ResponseException
from flywheel.resource import Resource
from djangorestframework.response import status, Response, ResponseException
from djangorestframework.resource import Resource

import decimal
import inspect
Expand Down Expand Up @@ -336,28 +336,41 @@ def _dict(data):
return _any(data, self.fields)


def post(self, request, content, *args, **kwargs):
def post(self, request, auth, content, *args, **kwargs):
# TODO: test creation on a non-existing resource url
all_kw_args = dict(content.items() + kwargs.items())
instance = self.model(**all_kw_args)
if args:
instance = self.model(pk=args[-1], **all_kw_args)
else:
instance = self.model(**all_kw_args)
instance.save()
headers = {}
if hasattr(instance, 'get_absolute_url'):
headers['Location'] = self.add_domain(instance.get_absolute_url())
return Response(status.HTTP_201_CREATED, instance, headers)

def get(self, request, *args, **kwargs):
def get(self, request, auth, *args, **kwargs):
try:
instance = self.model.objects.get(**kwargs)
if args:
# If we have any none kwargs then assume the last represents the primrary key
instance = self.model.objects.get(pk=args[-1], **kwargs)
else:
# Otherwise assume the kwargs uniquely identify the model
instance = self.model.objects.get(**kwargs)
except self.model.DoesNotExist:
raise ResponseException(status.HTTP_404_NOT_FOUND)

return instance

def put(self, request, content, *args, **kwargs):
def put(self, request, auth, content, *args, **kwargs):
# TODO: update on the url of a non-existing resource url doesn't work correctly at the moment - will end up with a new url
try:
instance = self.model.objects.get(**kwargs)
if args:
# If we have any none kwargs then assume the last represents the primrary key
instance = self.model.objects.get(pk=args[-1], **kwargs)
else:
# Otherwise assume the kwargs uniquely identify the model
instance = self.model.objects.get(**kwargs)
for (key, val) in content.items():
setattr(instance, key, val)
except self.model.DoesNotExist:
Expand All @@ -367,9 +380,14 @@ def put(self, request, content, *args, **kwargs):
instance.save()
return instance

def delete(self, request, *args, **kwargs):
def delete(self, request, auth, *args, **kwargs):
try:
instance = self.model.objects.get(**kwargs)
if args:
# If we have any none kwargs then assume the last represents the primrary key
instance = self.model.objects.get(pk=args[-1], **kwargs)
else:
# Otherwise assume the kwargs uniquely identify the model
instance = self.model.objects.get(**kwargs)
except self.model.DoesNotExist:
raise ResponseException(status.HTTP_404_NOT_FOUND, None, {})

Expand All @@ -382,7 +400,7 @@ class RootModelResource(ModelResource):
allowed_methods = ('GET', 'POST')
queryset = None

def get(self, request, *args, **kwargs):
def get(self, request, auth, *args, **kwargs):
queryset = self.queryset if self.queryset else self.model.objects.all()
return queryset

Expand All @@ -396,7 +414,7 @@ class QueryModelResource(ModelResource):
def get_form(self, data=None):
return None

def get(self, request, *args, **kwargs):
def get(self, request, auth, *args, **kwargs):
queryset = self.queryset if self.queryset else self.model.objects.all()
return queryset

2 changes: 1 addition & 1 deletion flywheel/parsers.py → djangorestframework/parsers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from flywheel.response import status, ResponseException
from djangorestframework.response import status, ResponseException

try:
import json
Expand Down
4 changes: 2 additions & 2 deletions flywheel/resource.py → djangorestframework/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from django.core.urlresolvers import reverse
from django.http import HttpResponse

from flywheel import emitters, parsers, authenticators
from flywheel.response import status, Response, ResponseException
from djangorestframework import emitters, parsers, authenticators
from djangorestframework.response import status, Response, ResponseException

from decimal import Decimal
import re
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,4 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru
# Register urlize_quoted_links as a custom filter
# http://docs.djangoproject.com/en/dev/howto/custom-template-tags/
register = template.Library()
register.filter(urlize_quoted_links)
register.filter(urlize_quoted_links)
File renamed without changes.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import sys, os

sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'flywheel'))
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'djangorestframework'))
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'examples'))
import settings
from django.core.management import setup_environ
Expand Down
28 changes: 8 additions & 20 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ Requirements
Installation & Setup
--------------------

The django-rest-framework project is hosted as a `mercurial repository on bitbucket <https://bitbucket.org/tomchristie/flywheel>`_.
The django-rest-framework project is hosted as a `mercurial repository on bitbucket <https://bitbucket.org/tomchristie/django-rest-framework>`_.
To get a local copy of the repository use mercurial::

hg clone https://tomchristie@bitbucket.org/tomchristie/flywheel
hg clone https://tomchristie@bitbucket.org/tomchristie/django-rest-framework

To add django-rest-framework to a django project:

Expand All @@ -43,27 +43,15 @@ Getting Started
Often you'll want parts of your API to directly map to existing Models.
At it's simplest this looks something like this...

``views.py``::
``urls.py``

from djangorestframework.modelresource import ModelResource, ModelRootResource
from models import MyModel
.. include:: ../examples/simpleexample/urls.py
:literal:

class MyModelRootResource(ModelRootResource):
"""A create/list resource for MyModel."""
allowed_methods = ('GET', 'POST')
model = MyModel
``views.py``

class MyModelResource(ModelResource):
"""A read/update/delete resource for MyModel."""
allowed_methods = ('GET', 'PUT', 'DELETE')
model = MyModel

``urls.py``::

urlpatterns += patterns('myapp.views',
url(r'^mymodel/$', 'MyModelRootResource'),
url(r'^mymodel/([^/]+)/$', 'MyModelResource'),
)
.. include:: ../examples/simpleexample/views.py
:literal:


Examples
Expand Down
8 changes: 8 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Documentation requires Django & Sphinx, and their dependencies...

Django==1.2.4
Jinja2==2.5.5
Pygments==1.4
Sphinx==1.0.7
docutils==0.7
wsgiref==0.1.2
6 changes: 3 additions & 3 deletions examples/blogpost/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from flywheel.response import Response, status
from flywheel.resource import Resource
from flywheel.modelresource import ModelResource, RootModelResource
from djangorestframework.response import Response, status
from djangorestframework.resource import Resource
from djangorestframework.modelresource import ModelResource, RootModelResource
from blogpost.models import BlogPost, Comment

BLOG_POST_FIELDS = ('created', 'title', 'slug', 'content', 'absolute_url', 'comment_url', 'comments_url')
Expand Down
4 changes: 2 additions & 2 deletions examples/objectstore/views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.conf import settings

from flywheel.resource import Resource
from flywheel.response import Response, status
from djangorestframework.resource import Resource
from djangorestframework.response import Response, status

import pickle
import os
Expand Down
6 changes: 3 additions & 3 deletions examples/pygments_api/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from django.conf import settings

from flywheel.resource import Resource
from flywheel.response import Response, status
from flywheel.emitters import BaseEmitter
from djangorestframework.resource import Resource
from djangorestframework.response import Response, status
from djangorestframework.emitters import BaseEmitter

from pygments.formatters import HtmlFormatter
from pygments.lexers import get_lexer_by_name
Expand Down
6 changes: 6 additions & 0 deletions examples/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# For the examples we need Django, pygments and httplib2...

Django==1.2.4
wsgiref==0.1.2
Pygments==1.4
httplib2==0.6.0
9 changes: 5 additions & 4 deletions examples/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,10 @@
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.admin',
'flywheel',
'blogpost',
#'django.contrib.admin',
'djangorestframework',
'simpleexample',
'objectstore',
'pygments_api'
'pygments_api',
'blogpost',
)
Empty file.
23 changes: 23 additions & 0 deletions examples/simpleexample/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from django.db import models

MAX_INSTANCES = 20

class MyModel(models.Model):
foo = models.BooleanField()
bar = models.IntegerField(help_text='Must be an integer.')
baz = models.CharField(max_length=32, help_text='Free text. Max length 32 chars.')
created = models.DateTimeField(auto_now_add=True)

class Meta:
ordering = ('created',)

def save(self, *args, **kwargs):
"""For the purposes of the sandbox, limit the maximum number of stored models."""
while MyModel.objects.all().count() > MAX_INSTANCES:
MyModel.objects.all()[0].delete()
super(MyModel, self).save(*args, **kwargs)

@models.permalink
def get_absolute_url(self):
return ('simpleexample.views.MyModelResource', (self.pk,))

6 changes: 6 additions & 0 deletions examples/simpleexample/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.conf.urls.defaults import patterns, url

urlpatterns = patterns('simpleexample.views',
url(r'^$', 'MyModelRootResource'),
url(r'^([0-9]+)/$', 'MyModelResource'),
)
18 changes: 18 additions & 0 deletions examples/simpleexample/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from djangorestframework.modelresource import ModelResource, RootModelResource
from simpleexample.models import MyModel

FIELDS = ('foo', 'bar', 'baz', 'absolute_url')

class MyModelRootResource(RootModelResource):
"""A create/list resource for MyModel.
Available for both authenticated and anonymous access for the purposes of the sandbox."""
model = MyModel
allowed_methods = anon_allowed_methods = ('GET', 'POST')
fields = FIELDS

class MyModelResource(ModelResource):
"""A read/update/delete resource for MyModel.
Available for both authenticated and anonymous access for the purposes of the sandbox."""
model = MyModel
allowed_methods = anon_allowed_methods = ('GET', 'PUT', 'DELETE')
fields = FIELDS
27 changes: 20 additions & 7 deletions examples/urls.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
from django.conf.urls.defaults import patterns, include
from django.contrib import admin
#from django.contrib import admin
from djangorestframework.resource import Resource

#admin.autodiscover()

class RootResource(Resource):
allowed_methods = anon_allowed_methods = ('GET',)

def get(self, request, auth):
return {'simple example': self.reverse('simpleexample.views.MyModelRootResource'),
'pygments example': self.reverse('pygments_api.views.PygmentsRoot'),
'object store example': self.reverse('objectstore.views.ObjectStoreRoot'),
'blog post example': self.reverse('blogpost.views.BlogPostRoot'),}

admin.autodiscover()

urlpatterns = patterns('',
(r'^pygments-example/', include('pygments_api.urls')),
(r'^blog-post-example/', include('blogpost.urls')),
(r'^object-store-example/', include('objectstore.urls')),
(r'^$', RootResource),
(r'^simple-example/', include('simpleexample.urls')),
(r'^object-store/', include('objectstore.urls')),
(r'^pygments/', include('pygments_api.urls')),
(r'^blog-post/', include('blogpost.urls')),
(r'^accounts/login/$', 'django.contrib.auth.views.login'),
(r'^accounts/logout/$', 'django.contrib.auth.views.logout'),
(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/', include(admin.site.urls)),
#(r'^admin/doc/', include('django.contrib.admindocs.urls')),
#(r'^admin/', include(admin.site.urls)),
)
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Django and pip are required if installing into a virtualenv environment...

Django==1.2.4
distribute==0.6.14
wsgiref==0.1.2

0 comments on commit 42f2f9b

Please sign in to comment.