diff --git a/docs/emitters.rst b/docs/emitters.rst index fcea6151a..590ace0fa 100644 --- a/docs/emitters.rst +++ b/docs/emitters.rst @@ -1,8 +1,6 @@ :mod:`emitters` =============== -.. module:: emitters - The emitters module provides a set of emitters that can be plugged in to a :class:`.Resource`. An emitter is responsible for taking the output of a and serializing it to a given media type. A :class:`.Resource` can have a number of emitters, allow the same content to be serialized in a number of different formats depending on the requesting client's preferences, as specified in the HTTP Request's Accept header. .. automodule:: emitters diff --git a/docs/index.rst b/docs/index.rst index a6bdaab80..10e41f7a7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,8 +13,30 @@ Some of FlyWheel's features: * Optional support for forms as input validation. * Modular architecture - Easy to extend and modify. +Installation & Setup +-------------------- + +blah di blah + +Getting Started +--------------- + +Blah di blah + + +Examples +-------- + +Blah blah blah, examples here. + +Add a toctree for examples + + +Library Reference +----------------- + .. toctree:: - :maxdepth: 1 + :maxdepth: 2 resource modelresource diff --git a/examples/pygments_api/forms.py b/examples/pygments_api/forms.py index 66446c5b3..dc9927e26 100644 --- a/examples/pygments_api/forms.py +++ b/examples/pygments_api/forms.py @@ -15,57 +15,11 @@ class PygmentsForm(forms.Form): The code to be highlighted can be specified either in a text field, or by URL. We do some additional form validation to ensure clients see helpful error responses.""" - code_url = forms.URLField(required=False, label='Code URL', - help_text='eg. https://bitbucket.org/tomchristie/flywheel/raw/cc266285d879/flywheel/resource.py') - code_text = forms.CharField(widget=forms.Textarea, required=False, label='Code Text', - help_text='Either supply a URL for the code to be highlighted or copy and paste the code text here.') - title = forms.CharField(required=False, help_text='(Optional)') + code = forms.CharField(widget=forms.Textarea, label='Code Text', max_length=1000000, + help_text='(Copy and paste the code text here.)') + title = forms.CharField(required=False, help_text='(Optional)', max_length=100) linenos = forms.BooleanField(label='Show Line Numbers', required=False) lexer = forms.ChoiceField(choices=LEXER_CHOICES, initial='python') style = forms.ChoiceField(choices=STYLE_CHOICES, initial='friendly') - - def clean_code_url(self): - """Custom field validation. - Ensure that code URLs really are valid, and return the content they point to in the cleaned_data, - rather than returning the URL itself.""" - cleaned_data = self.cleaned_data - url = cleaned_data.get('code_url') - if not url: - return '' - - try: - http = httplib.Http('.cache') - resp, content = http.request(url) - except: - raise forms.ValidationError('The URL supplied cannot be reached') - - if int(resp.status/100) != 2: - raise forms.ValidationError('The URL supplied does not return successfully') - if not content: - raise forms.ValidationError('The URL supplied returns no content') - - return content - - - def clean(self): - """Custom form validation. - Ensure that only one of code_url and code_text is set, and return the content of whichever is set in 'code'.""" - cleaned_data = self.cleaned_data - code_url = cleaned_data.get('code_url') - code_text = cleaned_data.get('code_text') - - if not code_url and not code_text: - raise forms.ValidationError('Either the URL or the code text must be supplied') - if code_url and code_text: - raise forms.ValidationError('You may not specify both the URL and the code text') - - if code_url: - cleaned_data['code'] = code_url - del cleaned_data['code_url'] - else: - cleaned_data['code'] = code_text - del cleaned_data['code_text'] - - return cleaned_data diff --git a/examples/pygments_api/views.py b/examples/pygments_api/views.py index 02f541f3a..4493a8220 100644 --- a/examples/pygments_api/views.py +++ b/examples/pygments_api/views.py @@ -24,7 +24,7 @@ class HTMLEmitter(BaseEmitter): class PygmentsRoot(Resource): """This example demonstrates a simple RESTful Web API aound the awesome pygments library. - This top level resource is used to create """ + This top level resource is used to create highlighted code snippets.""" form = PygmentsForm allowed_methods = anon_allowed_methods = ('POST',) diff --git a/examples/urls.py b/examples/urls.py index b1dec13d5..48af39dee 100644 --- a/examples/urls.py +++ b/examples/urls.py @@ -7,6 +7,7 @@ urlpatterns = patterns('', (r'^pygments-example/', include('pygments_api.urls')), (r'^blog-post-example/', include('blogpost.urls')), (r'^object-store-example/', include('objectstore.urls')), + (r'^testarchive-example/', include('testarchive.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')), diff --git a/flywheel/emitters.py b/flywheel/emitters.py index d052d9653..57e95ec2f 100644 --- a/flywheel/emitters.py +++ b/flywheel/emitters.py @@ -32,6 +32,8 @@ class BaseEmitter(object): self.resource = resource def emit(self, output=NoContent, verbose=False): + """By default emit simply returns the ouput as-is. + Override this method to provide for other behaviour.""" if output is NoContent: return '' @@ -81,7 +83,8 @@ class DocumentingTemplateEmitter(BaseEmitter): provide a form that can be used to submit arbitrary content.""" # Get the form instance if we have one bound to the input form_instance = resource.form_instance - + print form_instance + # Otherwise if this isn't an error response # then attempt to get a form bound to the response object if not form_instance and resource.response.has_content_body: @@ -89,6 +92,8 @@ class DocumentingTemplateEmitter(BaseEmitter): form_instance = resource.get_form(resource.response.raw_content) except: pass + if form_instance and not form_instance.is_valid(): + form_instance = None # If we still don't have a form instance then try to get an unbound form if not form_instance: diff --git a/flywheel/resource.py b/flywheel/resource.py index 677bdfce4..2a8554f3f 100644 --- a/flywheel/resource.py +++ b/flywheel/resource.py @@ -58,14 +58,19 @@ class Resource(object): CSRF_PARAM = 'csrfmiddlewaretoken' # Django's CSRF token used in form params - def __new__(cls, request, *args, **kwargs): + def __new__(cls, *args, **kwargs): """Make the class callable so it can be used as a Django view.""" self = object.__new__(cls) - self.__init__(request) - return self._handle_request(request, *args, **kwargs) + if args: + request = args[0] + self.__init__(request) + return self._handle_request(request, *args[1:], **kwargs) + else: + self.__init__() + return self - def __init__(self, request): + def __init__(self, request=None): """""" # Setup the resource context self.request = request diff --git a/flywheel/templates/emitter.html b/flywheel/templates/emitter.html index 7959af176..4b0a7ce9b 100644 --- a/flywheel/templates/emitter.html +++ b/flywheel/templates/emitter.html @@ -30,9 +30,9 @@

{{ resource.name }}

{{ resource.description|linebreaksbr }}

{{ response.status }} {{ response.status_text }}{% autoescape off %}
-	{% for key, val in response.headers.items %}{{ key }}: {{ val|urlize_quoted_links }}
-	{% endfor %}
-	{{ content|urlize_quoted_links }}
{% endautoescape %} +{% for key, val in response.headers.items %}{{ key }}: {{ val|urlize_quoted_links }} +{% endfor %} +{{ content|urlize_quoted_links }}{% endautoescape %} {% if 'GET' in resource.allowed_methods %}
@@ -40,7 +40,7 @@