Rename to django-rest-framework, get simpleexample working

parent 8a470f03
# To install django-rest-framework... # To install django-rest-framework in a virtualenv environment...
#
# Requirements:
# python2.6
# virtualenv
hg clone https://tomchristie@bitbucket.org/tomchristie/django-rest-framework hg clone https://tomchristie@bitbucket.org/tomchristie/django-rest-framework
cd django-rest-framework/ cd django-rest-framework/
virtualenv --no-site-packages --distribute --python=python2.6 env virtualenv --no-site-packages --distribute --python=python2.6 env
source ./env/bin/activate source ./env/bin/activate
pip install -r ./requirements.txt pip install -r requirements.txt
python ./src/manage.py test
# To build the documentation... # 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
"""Emitters are used to serialize a Resource's output into specific media types. """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, 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. and providing forms and links depending on the allowed methods, emitters and parsers on the Resource.
""" """
...@@ -7,8 +7,8 @@ from django.conf import settings ...@@ -7,8 +7,8 @@ from django.conf import settings
from django.template import RequestContext, loader from django.template import RequestContext, loader
from django import forms from django import forms
from flywheel.response import NoContent from djangorestframework.response import NoContent
from flywheel.utils import dict2xml, url_resolves from djangorestframework.utils import dict2xml, url_resolves
from urllib import quote_plus from urllib import quote_plus
import string import string
...@@ -193,7 +193,7 @@ class XMLEmitter(BaseEmitter): ...@@ -193,7 +193,7 @@ class XMLEmitter(BaseEmitter):
class DocumentingHTMLEmitter(DocumentingTemplateEmitter): class DocumentingHTMLEmitter(DocumentingTemplateEmitter):
"""Emitter which provides a browsable HTML interface for an API. """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' media_type = 'text/html'
template = 'emitter.html' template = 'emitter.html'
......
...@@ -2,8 +2,8 @@ from django.forms import ModelForm ...@@ -2,8 +2,8 @@ from django.forms import ModelForm
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from django.db.models import Model from django.db.models import Model
from flywheel.response import status, Response, ResponseException from djangorestframework.response import status, Response, ResponseException
from flywheel.resource import Resource from djangorestframework.resource import Resource
import decimal import decimal
import inspect import inspect
...@@ -336,9 +336,12 @@ class ModelResource(Resource): ...@@ -336,9 +336,12 @@ class ModelResource(Resource):
return _any(data, self.fields) 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 # TODO: test creation on a non-existing resource url
all_kw_args = dict(content.items() + kwargs.items()) all_kw_args = dict(content.items() + kwargs.items())
if args:
instance = self.model(pk=args[-1], **all_kw_args)
else:
instance = self.model(**all_kw_args) instance = self.model(**all_kw_args)
instance.save() instance.save()
headers = {} headers = {}
...@@ -346,17 +349,27 @@ class ModelResource(Resource): ...@@ -346,17 +349,27 @@ class ModelResource(Resource):
headers['Location'] = self.add_domain(instance.get_absolute_url()) headers['Location'] = self.add_domain(instance.get_absolute_url())
return Response(status.HTTP_201_CREATED, instance, headers) return Response(status.HTTP_201_CREATED, instance, headers)
def get(self, request, *args, **kwargs): def get(self, request, auth, *args, **kwargs):
try: try:
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) instance = self.model.objects.get(**kwargs)
except self.model.DoesNotExist: except self.model.DoesNotExist:
raise ResponseException(status.HTTP_404_NOT_FOUND) raise ResponseException(status.HTTP_404_NOT_FOUND)
return instance 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 # 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: try:
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) instance = self.model.objects.get(**kwargs)
for (key, val) in content.items(): for (key, val) in content.items():
setattr(instance, key, val) setattr(instance, key, val)
...@@ -367,8 +380,13 @@ class ModelResource(Resource): ...@@ -367,8 +380,13 @@ class ModelResource(Resource):
instance.save() instance.save()
return instance return instance
def delete(self, request, *args, **kwargs): def delete(self, request, auth, *args, **kwargs):
try: try:
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) instance = self.model.objects.get(**kwargs)
except self.model.DoesNotExist: except self.model.DoesNotExist:
raise ResponseException(status.HTTP_404_NOT_FOUND, None, {}) raise ResponseException(status.HTTP_404_NOT_FOUND, None, {})
...@@ -382,7 +400,7 @@ class RootModelResource(ModelResource): ...@@ -382,7 +400,7 @@ class RootModelResource(ModelResource):
allowed_methods = ('GET', 'POST') allowed_methods = ('GET', 'POST')
queryset = None 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() queryset = self.queryset if self.queryset else self.model.objects.all()
return queryset return queryset
...@@ -396,7 +414,7 @@ class QueryModelResource(ModelResource): ...@@ -396,7 +414,7 @@ class QueryModelResource(ModelResource):
def get_form(self, data=None): def get_form(self, data=None):
return 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() queryset = self.queryset if self.queryset else self.model.objects.all()
return queryset return queryset
from flywheel.response import status, ResponseException from djangorestframework.response import status, ResponseException
try: try:
import json import json
......
...@@ -2,8 +2,8 @@ from django.contrib.sites.models import Site ...@@ -2,8 +2,8 @@ from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import HttpResponse from django.http import HttpResponse
from flywheel import emitters, parsers, authenticators from djangorestframework import emitters, parsers, authenticators
from flywheel.response import status, Response, ResponseException from djangorestframework.response import status, Response, ResponseException
from decimal import Decimal from decimal import Decimal
import re import re
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
import sys, os import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) 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')) sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(__file__)), 'examples'))
import settings import settings
from django.core.management import setup_environ from django.core.management import setup_environ
......
...@@ -26,10 +26,10 @@ Requirements ...@@ -26,10 +26,10 @@ Requirements
Installation & Setup 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:: 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: To add django-rest-framework to a django project:
...@@ -43,27 +43,15 @@ Getting Started ...@@ -43,27 +43,15 @@ Getting Started
Often you'll want parts of your API to directly map to existing Models. Often you'll want parts of your API to directly map to existing Models.
At it's simplest this looks something like this... At it's simplest this looks something like this...
``views.py``:: ``urls.py``
from djangorestframework.modelresource import ModelResource, ModelRootResource .. include:: ../examples/simpleexample/urls.py
from models import MyModel :literal:
class MyModelRootResource(ModelRootResource): ``views.py``
"""A create/list resource for MyModel."""
allowed_methods = ('GET', 'POST')
model = MyModel
class MyModelResource(ModelResource): .. include:: ../examples/simpleexample/views.py
"""A read/update/delete resource for MyModel.""" :literal:
allowed_methods = ('GET', 'PUT', 'DELETE')
model = MyModel
``urls.py``::
urlpatterns += patterns('myapp.views',
url(r'^mymodel/$', 'MyModelRootResource'),
url(r'^mymodel/([^/]+)/$', 'MyModelResource'),
)
Examples Examples
......
# 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
from flywheel.response import Response, status from djangorestframework.response import Response, status
from flywheel.resource import Resource from djangorestframework.resource import Resource
from flywheel.modelresource import ModelResource, RootModelResource from djangorestframework.modelresource import ModelResource, RootModelResource
from blogpost.models import BlogPost, Comment from blogpost.models import BlogPost, Comment
BLOG_POST_FIELDS = ('created', 'title', 'slug', 'content', 'absolute_url', 'comment_url', 'comments_url') BLOG_POST_FIELDS = ('created', 'title', 'slug', 'content', 'absolute_url', 'comment_url', 'comments_url')
......
from django.conf import settings from django.conf import settings
from flywheel.resource import Resource from djangorestframework.resource import Resource
from flywheel.response import Response, status from djangorestframework.response import Response, status
import pickle import pickle
import os import os
......
from django.conf import settings from django.conf import settings
from flywheel.resource import Resource from djangorestframework.resource import Resource
from flywheel.response import Response, status from djangorestframework.response import Response, status
from flywheel.emitters import BaseEmitter from djangorestframework.emitters import BaseEmitter
from pygments.formatters import HtmlFormatter from pygments.formatters import HtmlFormatter
from pygments.lexers import get_lexer_by_name from pygments.lexers import get_lexer_by_name
......
# For the examples we need Django, pygments and httplib2...
Django==1.2.4
wsgiref==0.1.2
Pygments==1.4
httplib2==0.6.0
...@@ -93,9 +93,10 @@ INSTALLED_APPS = ( ...@@ -93,9 +93,10 @@ INSTALLED_APPS = (
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.sites', 'django.contrib.sites',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.admin', #'django.contrib.admin',
'flywheel', 'djangorestframework',
'blogpost', 'simpleexample',
'objectstore', 'objectstore',
'pygments_api' 'pygments_api',
'blogpost',
) )
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,))
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('simpleexample.views',
url(r'^$', 'MyModelRootResource'),
url(r'^([0-9]+)/$', 'MyModelResource'),
)
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
from django.conf.urls.defaults import patterns, include 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('', urlpatterns = patterns('',
(r'^pygments-example/', include('pygments_api.urls')), (r'^$', RootResource),
(r'^blog-post-example/', include('blogpost.urls')), (r'^simple-example/', include('simpleexample.urls')),
(r'^object-store-example/', include('objectstore.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/login/$', 'django.contrib.auth.views.login'),
(r'^accounts/logout/$', 'django.contrib.auth.views.logout'), (r'^accounts/logout/$', 'django.contrib.auth.views.logout'),
(r'^admin/doc/', include('django.contrib.admindocs.urls')), #(r'^admin/doc/', include('django.contrib.admindocs.urls')),
(r'^admin/', include(admin.site.urls)), #(r'^admin/', include(admin.site.urls)),
) )
# Django and pip are required if installing into a virtualenv environment...
Django==1.2.4 Django==1.2.4
distribute==0.6.14 distribute==0.6.14
wsgiref==0.1.2 wsgiref==0.1.2
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment