Commit 028851bf by Tom Christie

Fix up tests and examples after refactoring

parent 762a52ed
...@@ -74,3 +74,9 @@ class UserLoggedInAuthenticator(BaseAuthenticator): ...@@ -74,3 +74,9 @@ class UserLoggedInAuthenticator(BaseAuthenticator):
return request.user return request.user
return None return None
#class DigestAuthentication(BaseAuthentication):
# pass
#
#class OAuthAuthentication(BaseAuthentication):
# pass
...@@ -416,7 +416,7 @@ class RootModelResource(ModelResource): ...@@ -416,7 +416,7 @@ class RootModelResource(ModelResource):
queryset = self.queryset if self.queryset else self.model.objects.all() queryset = self.queryset if self.queryset else self.model.objects.all()
return queryset.filter(**kwargs) return queryset.filter(**kwargs)
put = delete = http_method_not_allowed put = delete = None
class QueryModelResource(ModelResource): class QueryModelResource(ModelResource):
"""Resource with default operations for list. """Resource with default operations for list.
...@@ -428,4 +428,4 @@ class QueryModelResource(ModelResource): ...@@ -428,4 +428,4 @@ class QueryModelResource(ModelResource):
queryset = self.queryset if self.queryset else self.model.objects.all() queryset = self.queryset if self.queryset else self.model.objects.all()
return queryset.filer(**kwargs) return queryset.filer(**kwargs)
post = put = delete = http_method_not_allowed post = put = delete = None
\ No newline at end of file \ No newline at end of file
...@@ -41,7 +41,7 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View): ...@@ -41,7 +41,7 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View):
authenticators.BasicAuthenticator ) authenticators.BasicAuthenticator )
# List of all permissions required to access the resource # List of all permissions required to access the resource
permissions = ( permissions.DeleteMePermission, ) permissions = ()
# Optional form for input validation and presentation of HTML formatted responses. # Optional form for input validation and presentation of HTML formatted responses.
form = None form = None
...@@ -54,7 +54,7 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View): ...@@ -54,7 +54,7 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View):
@property @property
def allowed_methods(self): def allowed_methods(self):
return [method.upper() for method in self.http_method_names if hasattr(self, method)] return [method.upper() for method in self.http_method_names if getattr(self, method, None)]
def http_method_not_allowed(self, request, *args, **kwargs): def http_method_not_allowed(self, request, *args, **kwargs):
"""Return an HTTP 405 error if an operation is called which does not have a handler method.""" """Return an HTTP 405 error if an operation is called which does not have a handler method."""
...@@ -96,6 +96,9 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View): ...@@ -96,6 +96,9 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View):
# Get the appropriate handler method # Get the appropriate handler method
if self.method.lower() in self.http_method_names: if self.method.lower() in self.http_method_names:
handler = getattr(self, self.method.lower(), self.http_method_not_allowed) handler = getattr(self, self.method.lower(), self.http_method_not_allowed)
# If a previously defined method has been disabled
if handler is None:
handler = self.http_method_not_allowed
else: else:
handler = self.http_method_not_allowed handler = self.http_method_not_allowed
...@@ -125,3 +128,4 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View): ...@@ -125,3 +128,4 @@ class Resource(RequestMixin, ResponseMixin, AuthMixin, View):
return self.emit(response) return self.emit(response)
...@@ -7,11 +7,13 @@ from django.utils import simplejson as json ...@@ -7,11 +7,13 @@ from django.utils import simplejson as json
from djangorestframework.compat import RequestFactory from djangorestframework.compat import RequestFactory
from djangorestframework.resource import Resource from djangorestframework.resource import Resource
from djangorestframework import permissions
import base64 import base64
class MockResource(Resource): class MockResource(Resource):
permissions = ( permissions.IsAuthenticated, )
def post(self, request): def post(self, request):
return {'a':1, 'b':2, 'c':3} return {'a':1, 'b':2, 'c':3}
......
...@@ -8,25 +8,21 @@ MAX_POSTS = 10 ...@@ -8,25 +8,21 @@ MAX_POSTS = 10
class BlogPosts(RootModelResource): class BlogPosts(RootModelResource):
"""A resource with which lists all existing blog posts and creates new blog posts.""" """A resource with which lists all existing blog posts and creates new blog posts."""
anon_allowed_methods = allowed_methods = ('GET', 'POST',)
model = models.BlogPost model = models.BlogPost
fields = BLOG_POST_FIELDS fields = BLOG_POST_FIELDS
class BlogPostInstance(ModelResource): class BlogPostInstance(ModelResource):
"""A resource which represents a single blog post.""" """A resource which represents a single blog post."""
anon_allowed_methods = allowed_methods = ('GET', 'PUT', 'DELETE')
model = models.BlogPost model = models.BlogPost
fields = BLOG_POST_FIELDS fields = BLOG_POST_FIELDS
class Comments(RootModelResource): class Comments(RootModelResource):
"""A resource which lists all existing comments for a given blog post, and creates new blog comments for a given blog post.""" """A resource which lists all existing comments for a given blog post, and creates new blog comments for a given blog post."""
anon_allowed_methods = allowed_methods = ('GET', 'POST',)
model = models.Comment model = models.Comment
fields = COMMENT_FIELDS fields = COMMENT_FIELDS
class CommentInstance(ModelResource): class CommentInstance(ModelResource):
"""A resource which represents a single comment.""" """A resource which represents a single comment."""
anon_allowed_methods = allowed_methods = ('GET', 'PUT', 'DELETE')
model = models.Comment model = models.Comment
fields = COMMENT_FIELDS fields = COMMENT_FIELDS
from djangorestframework.compat import View # Use Django 1.3's django.views.generic.View, or fall back to a clone of that if Django < 1.3 from djangorestframework.compat import View # Use Django 1.3's django.views.generic.View, or fall back to a clone of that if Django < 1.3
from djangorestframework.emitters import EmitterMixin, DEFAULT_EMITTERS from djangorestframework.mixins import ResponseMixin
from djangorestframework.emitters import DEFAULT_EMITTERS
from djangorestframework.response import Response from djangorestframework.response import Response
from django.conf.urls.defaults import patterns, url from django.conf.urls.defaults import patterns, url
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
class ExampleView(EmitterMixin, View): class ExampleView(ResponseMixin, View):
"""An example view using Django 1.3's class based views. """An example view using Django 1.3's class based views.
Uses djangorestframework's EmitterMixin to provide support for multiple output formats.""" Uses djangorestframework's EmitterMixin to provide support for multiple output formats."""
emitters = DEFAULT_EMITTERS emitters = DEFAULT_EMITTERS
......
...@@ -7,12 +7,10 @@ class MyModelRootResource(RootModelResource): ...@@ -7,12 +7,10 @@ class MyModelRootResource(RootModelResource):
"""A create/list resource for MyModel. """A create/list resource for MyModel.
Available for both authenticated and anonymous access for the purposes of the sandbox.""" Available for both authenticated and anonymous access for the purposes of the sandbox."""
model = MyModel model = MyModel
allowed_methods = anon_allowed_methods = ('GET', 'POST')
fields = FIELDS fields = FIELDS
class MyModelResource(ModelResource): class MyModelResource(ModelResource):
"""A read/update/delete resource for MyModel. """A read/update/delete resource for MyModel.
Available for both authenticated and anonymous access for the purposes of the sandbox.""" Available for both authenticated and anonymous access for the purposes of the sandbox."""
model = MyModel model = MyModel
allowed_methods = anon_allowed_methods = ('GET', 'PUT', 'DELETE')
fields = FIELDS fields = FIELDS
...@@ -41,26 +41,25 @@ class PygmentsRoot(Resource): ...@@ -41,26 +41,25 @@ class PygmentsRoot(Resource):
"""This example demonstrates a simple RESTful Web API aound the awesome pygments library. """This example demonstrates a simple RESTful Web API aound the awesome pygments library.
This top level resource is used to create highlighted code snippets, and to list all the existing code snippets.""" This top level resource is used to create highlighted code snippets, and to list all the existing code snippets."""
form = PygmentsForm form = PygmentsForm
allowed_methods = anon_allowed_methods = ('GET', 'POST',)
def get(self, request, auth): def get(self, request):
"""Return a list of all currently existing snippets.""" """Return a list of all currently existing snippets."""
unique_ids = [os.path.split(f)[1] for f in list_dir_sorted_by_ctime(HIGHLIGHTED_CODE_DIR)] unique_ids = [os.path.split(f)[1] for f in list_dir_sorted_by_ctime(HIGHLIGHTED_CODE_DIR)]
return [reverse('pygments-instance', args=[unique_id]) for unique_id in unique_ids] return [reverse('pygments-instance', args=[unique_id]) for unique_id in unique_ids]
def post(self, request, auth, content): def post(self, request):
"""Create a new highlighed snippet and return it's location. """Create a new highlighed snippet and return it's location.
For the purposes of the sandbox example, also ensure we delete the oldest snippets if we have > MAX_FILES.""" For the purposes of the sandbox example, also ensure we delete the oldest snippets if we have > MAX_FILES."""
unique_id = str(uuid.uuid1()) unique_id = str(uuid.uuid1())
pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id) pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)
lexer = get_lexer_by_name(content['lexer']) lexer = get_lexer_by_name(self.CONTENT['lexer'])
linenos = 'table' if content['linenos'] else False linenos = 'table' if self.CONTENT['linenos'] else False
options = {'title': content['title']} if content['title'] else {} options = {'title': self.CONTENT['title']} if self.CONTENT['title'] else {}
formatter = HtmlFormatter(style=content['style'], linenos=linenos, full=True, **options) formatter = HtmlFormatter(style=self.CONTENT['style'], linenos=linenos, full=True, **options)
with open(pathname, 'w') as outfile: with open(pathname, 'w') as outfile:
highlight(content['code'], lexer, formatter, outfile) highlight(self.CONTENT['code'], lexer, formatter, outfile)
remove_oldest_files(HIGHLIGHTED_CODE_DIR, MAX_FILES) remove_oldest_files(HIGHLIGHTED_CODE_DIR, MAX_FILES)
...@@ -70,20 +69,19 @@ class PygmentsRoot(Resource): ...@@ -70,20 +69,19 @@ class PygmentsRoot(Resource):
class PygmentsInstance(Resource): class PygmentsInstance(Resource):
"""Simply return the stored highlighted HTML file with the correct mime type. """Simply return the stored highlighted HTML file with the correct mime type.
This Resource only emits HTML and uses a standard HTML emitter rather than the emitters.DocumentingHTMLEmitter class.""" This Resource only emits HTML and uses a standard HTML emitter rather than the emitters.DocumentingHTMLEmitter class."""
allowed_methods = anon_allowed_methods = ('GET',)
emitters = (HTMLEmitter,) emitters = (HTMLEmitter,)
def get(self, request, auth, unique_id): def get(self, request, unique_id):
"""Return the highlighted snippet.""" """Return the highlighted snippet."""
pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id) pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)
if not os.path.exists(pathname): if not os.path.exists(pathname):
return Resource(status.HTTP_404_NOT_FOUND) return Response(status.HTTP_404_NOT_FOUND)
return open(pathname, 'r').read() return open(pathname, 'r').read()
def delete(self, request, auth, unique_id): def delete(self, request, unique_id):
"""Delete the highlighted snippet.""" """Delete the highlighted snippet."""
pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id) pathname = os.path.join(HIGHLIGHTED_CODE_DIR, unique_id)
if not os.path.exists(pathname): if not os.path.exists(pathname):
return Resource(status.HTTP_404_NOT_FOUND) return Response(status.HTTP_404_NOT_FOUND)
return os.remove(pathname) return os.remove(pathname)
...@@ -8,24 +8,22 @@ from resourceexample.forms import MyForm ...@@ -8,24 +8,22 @@ from resourceexample.forms import MyForm
class ExampleResource(Resource): class ExampleResource(Resource):
"""A basic read-only resource that points to 3 other resources.""" """A basic read-only resource that points to 3 other resources."""
allowed_methods = anon_allowed_methods = ('GET',)
def get(self, request, auth): def get(self, request):
return {"Some other resources": [reverse('another-example-resource', kwargs={'num':num}) for num in range(3)]} return {"Some other resources": [reverse('another-example-resource', kwargs={'num':num}) for num in range(3)]}
class AnotherExampleResource(Resource): class AnotherExampleResource(Resource):
"""A basic GET-able/POST-able resource.""" """A basic GET-able/POST-able resource."""
allowed_methods = anon_allowed_methods = ('GET', 'POST')
form = MyForm # Optional form validation on input (Applies in this case the POST method, but can also apply to PUT) form = MyForm # Optional form validation on input (Applies in this case the POST method, but can also apply to PUT)
def get(self, request, auth, num): def get(self, request, num):
"""Handle GET requests""" """Handle GET requests"""
if int(num) > 2: if int(num) > 2:
return Response(status.HTTP_404_NOT_FOUND) return Response(status.HTTP_404_NOT_FOUND)
return "GET request to AnotherExampleResource %s" % num return "GET request to AnotherExampleResource %s" % num
def post(self, request, auth, content, num): def post(self, request, num):
"""Handle POST requests""" """Handle POST requests"""
if int(num) > 2: if int(num) > 2:
return Response(status.HTTP_404_NOT_FOUND) return Response(status.HTTP_404_NOT_FOUND)
return "POST request to AnotherExampleResource %s, with content: %s" % (num, repr(content)) return "POST request to AnotherExampleResource %s, with content: %s" % (num, repr(self.CONTENT))
...@@ -24,9 +24,8 @@ class Sandbox(Resource): ...@@ -24,9 +24,8 @@ class Sandbox(Resource):
6. A blog posts and comments API. 6. A blog posts and comments API.
Please feel free to browse, create, edit and delete the resources in these examples.""" Please feel free to browse, create, edit and delete the resources in these examples."""
allowed_methods = anon_allowed_methods = ('GET',)
def get(self, request, auth): def get(self, request):
return [{'name': 'Simple Resource example', 'url': reverse('example-resource')}, return [{'name': 'Simple Resource example', 'url': reverse('example-resource')},
{'name': 'Simple ModelResource example', 'url': reverse('my-model-root-resource')}, {'name': 'Simple ModelResource example', 'url': reverse('my-model-root-resource')},
{'name': 'Simple Mixin-only example', 'url': reverse('mixin-view')}, {'name': 'Simple Mixin-only example', 'url': reverse('mixin-view')},
......
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