From f269826a7d8a980536ffbce369be369c4df58d23 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 18 Nov 2014 16:26:45 +0000 Subject: Note on 3.0 beta --- docs/topics/3.0-announcement.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 90cbda4d..06fdc9fd 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -1,10 +1,12 @@ ## Pre-release notes: -The 3.0 release is now ready for some tentative testing and upgrades for early adopters. You can install the development version directly from GitHub like so: +The 3.0 release is now in beta and ready for final testing. You can install the development version directly from GitHub like so: - pip install https://github.com/tomchristie/django-rest-framework/archive/master.zip + pip install https://github.com/tomchristie/django-rest-framework/archive/3.0-beta.zip -See the [Version 3.0 GitHub issue](https://github.com/tomchristie/django-rest-framework/pull/1800) for more details on remaining work. +Currently the only known remaining blockers are documentation issues and tickets. Any critical bugs raised in the next week or two will be resolved for the 3.0 release, but otherwise consider this as code-complete. + +Please work through this document throughly in order to understand the API differences that exist between 2.4 and 3.0. **Your feedback on the upgrade process and 3.0 changes is hugely important!** -- cgit v1.2.3 From 51b7033e4aeeefe19012a77b09a0b23d4a52a5bc Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 19 Nov 2014 14:03:19 +0000 Subject: Further notes in 3.0 announcement --- docs/topics/3.0-announcement.md | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'docs') diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 90cbda4d..3c73881f 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -821,6 +821,11 @@ Or modify it on an individual serializer field, using the `coerce_to_string` key The default JSON renderer will return float objects for uncoerced `Decimal` instances. This allows you to easily switch between string or float representations for decimals depending on your API design needs. +## Miscellaneous notes. + +* The serializer `ChoiceField` does not currently display nested choices, as was the case in 2.4. This will be address as part of 3.1. +* Due to the new templated form rendering, the 'widget' option is no longer valid. This means there's no easy way of using third party "autocomplete" widgets for rendering select inputs that contain a large number of choices. You'll either need to use a regular select or a plain text input. We may consider addressing this in 3.1 or 3.2 if there's sufficient demand. + ## What's coming next. 3.0 is an incremental release, and there are several upcoming features that will build on the baseline improvements that it makes. -- cgit v1.2.3 From 928cbc640ef1db2c3fb96d352f69b8ffb66313e6 Mon Sep 17 00:00:00 2001 From: Raony Guimarães Date: Wed, 19 Nov 2014 13:53:36 -0200 Subject: small type --- docs/tutorial/quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index c2dc4bea..1c398c1f 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -19,7 +19,7 @@ Create a new Django project named `tutorial`, then start a new app called `quick pip install djangorestframework # Set up a new project with a single application - django-admin.py startproject tutorial . + django-admin.py startproject tutorial cd tutorial django-admin.py startapp quickstart cd .. -- cgit v1.2.3 From 04d2635b24f0699ed8ed24436a58c203ad6a9a11 Mon Sep 17 00:00:00 2001 From: Gil Gonçalves Date: Thu, 20 Nov 2014 11:33:42 +0000 Subject: Removed unused import from code snippet in tutorial --- docs/tutorial/5-relationships-and-hyperlinked-apis.md | 1 - 1 file changed, 1 deletion(-) (limited to 'docs') diff --git a/docs/tutorial/5-relationships-and-hyperlinked-apis.md b/docs/tutorial/5-relationships-and-hyperlinked-apis.md index 36473ce9..50552616 100644 --- a/docs/tutorial/5-relationships-and-hyperlinked-apis.md +++ b/docs/tutorial/5-relationships-and-hyperlinked-apis.md @@ -6,7 +6,6 @@ At the moment relationships within our API are represented by using primary keys Right now we have endpoints for 'snippets' and 'users', but we don't have a single entry point to our API. To create one, we'll use a regular function-based view and the `@api_view` decorator we introduced earlier. In your `snippets/views.py` add: - from rest_framework import renderers from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.reverse import reverse -- cgit v1.2.3 From 6a2023a362bcc10978ed725fa8816ddf08ea7c73 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 20 Nov 2014 13:52:00 +0000 Subject: Note on 3.1 and 3.2 releases. --- docs/topics/3.0-announcement.md | 3 +++ 1 file changed, 3 insertions(+) (limited to 'docs') diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 958be2d6..03e3e070 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -34,6 +34,9 @@ Notable features of this new release include: * Support for overriding how validation errors are handled by your API. * A metadata API that allows you to customize how `OPTIONS` requests are handled by your API. * A more compact JSON output with unicode style encoding turned on by default. +* Templated based HTML form rendering for serializers. This will be finalized as public API in the upcoming 3.1 release. + +Significant new functionality continues to be planned for the 3.1 and 3.2 releases. These releases will present simple upgrades, without the same level of fundamental API changes necessary for the 3.0 release. Below is an in-depth guide to the API changes and migration notes for 3.0. -- cgit v1.2.3 From 071c064d251bb2f268762fb34cf3f248b5ce4557 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 20 Nov 2014 14:22:53 +0000 Subject: Fill in TODOs for 3.0 beta release notes --- docs/topics/3.0-announcement.md | 47 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) (limited to 'docs') diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 03e3e070..7bbfba5b 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -36,7 +36,7 @@ Notable features of this new release include: * A more compact JSON output with unicode style encoding turned on by default. * Templated based HTML form rendering for serializers. This will be finalized as public API in the upcoming 3.1 release. -Significant new functionality continues to be planned for the 3.1 and 3.2 releases. These releases will present simple upgrades, without the same level of fundamental API changes necessary for the 3.0 release. +Significant new functionality continues to be planned for the 3.1 and 3.2 releases. These releases will correspond to the two [Kickstarter stretch goals](https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3) - "Feature improvements" and "Admin interface". Further 3.x releases will present simple upgrades, without the same level of fundamental API changes necessary for the 3.0 release. Below is an in-depth guide to the API changes and migration notes for 3.0. @@ -145,6 +145,16 @@ The corresponding code would now look like this: logging.info('Creating ticket "%s"' % name) serializer.save(user=request.user) # Include the user when saving. +#### Using `.is_valid(raise_exception=True)` + +The `.is_valid()` method now takes an optional boolean flag, `raise_exception`. + +Calling `.is_valid(raise_exception=True)` will cause a `ValidationError` to be raised if the serializer data contains validation errors. This error will be handled by REST framework's default exception handler, allowing you to remove error response handling from your view code. + +The handling and formatting of error responses may be altered globally by using the `EXCEPTION_HANDLER` settings key. + +This change also means it's now possible to alter the style of error responses used by the built-in generic views, without having to include mixin classes or other overrides. + #### Using `serializers.ValidationError`. Previously `serializers.ValidationError` error was simply a synonym for `django.core.exceptions.ValidationError`. This has now been altered so that it inherits from the standard `APIException` base class. @@ -356,6 +366,8 @@ The `ListSerializer` class has now been added, and allows you to create base ser You can also still use the `many=True` argument to serializer classes. It's worth noting that `many=True` argument transparently creates a `ListSerializer` instance, allowing the validation logic for list and non-list data to be cleanly separated in the REST framework codebase. +You will typically want to *continue to use the existing `many=True` flag* rather than declaring `ListSerializer` classes explicitly, but declaring the classes explicitly can be useful if you need to write custom `create` or `update` methods for bulk updates, or provide for other custom behavior. + See also the new `ListField` class, which validates input in the same way, but does not include the serializer interfaces of `.is_valid()`, `.data`, `.save()` and so on. #### The `BaseSerializer` class. @@ -673,7 +685,9 @@ The `UniqueTogetherValidator` should be applied to a serializer, and takes a `qu #### The `UniqueForDateValidator` classes. -**TODO: Needs documenting.** +REST framework also now includes explicit validator classes for validating the `unique_for_date`, `unique_for_month`, and `unique_for_year` model field constraints. These are used internally instead of calling into `Model.full_clean()`. + +These classes are documented in the [Validators](../api-guide/validators.md) section of the documentation. ## Generic views @@ -731,7 +745,34 @@ This makes it far easier to use a different style for `OPTIONS` responses throug ## Serializers as HTML forms -**TODO: Document this.** +REST framework 3.0 includes templated HTML form rendering for serializers. + +This API should not yet be considered finalized, and will only be promoted to public API for the 3.1 release. + +Significant changes that you do need to be aware of include: + +* Nested HTML forms are now supported, for example, a `UserSerializer` with a nested `ProfileSerializer` will now render a nested `fieldset` when used in the browsable API. +* Nested lists of HTML forms are not yet supported, but are planned for 3.1. +* Because we now use templated HTML form generation, **the `widget` option is no longer available for serializer fields**. You can instead control the template that is used for a given field, by using the `style` dictionary. + +#### The `style` keyword argument for serializer fields. + +The `style` keyword argument can be used to pass through additional information from a serializer field, to the renderer class. In particular, the `HTMLFormRenderer` uses the `base_template` key to determine which template to render the field with. + +For example, to use a `textarea` control instead of the default `input` control, you would use the following… + + additional_notes = serializers.CharField( + style={'base_template': 'text_area.html'} + ) + +Similarly, to use a radio button control instead of the default `select` control, you would use the following… + + color_channel = serializers.ChoiceField( + choices=['red', 'blue', 'green'], + style={'base_template': 'radio.html'} + ) + +This API should be considered provisional, and there may be minor alterations with the incoming 3.1 release. ## API style -- cgit v1.2.3 From 8e940a22fb292ed6b20b9e4b5da607ffca1dba2f Mon Sep 17 00:00:00 2001 From: Matthew Dapena-Tretter Date: Fri, 21 Nov 2014 15:58:31 -0500 Subject: Clarify how permission classes are composed all/every/AND or any/OR? all/every/AND! --- docs/api-guide/settings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 48af30a5..96d715ea 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -74,7 +74,7 @@ Default: #### DEFAULT_PERMISSION_CLASSES -A list or tuple of permission classes, that determines the default set of permissions checked at the start of a view. +A list or tuple of permission classes, that determines the default set of permissions checked at the start of a view. Permission must be granted by every class in the list. Default: -- cgit v1.2.3 From c94d1e6d3ea76eb8bdd28717364e42d14e6722d7 Mon Sep 17 00:00:00 2001 From: Tony Nguyen Date: Sun, 23 Nov 2014 22:40:40 +0700 Subject: Fix typo "serailizers" to "serializers" --- docs/topics/3.0-announcement.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'docs') diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 7bbfba5b..694ad8a5 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -189,13 +189,13 @@ You can either return `non_field_errors` from the validate method by raising a s def validate(self, attrs): # serializer.errors == {'non_field_errors': ['A non field error']} - raise serailizers.ValidationError('A non field error') + raise serializers.ValidationError('A non field error') Alternatively if you want the errors to be against a specific field, use a dictionary of when instantiating the `ValidationError`, like so: def validate(self, attrs): # serializer.errors == {'my_field': ['A field error']} - raise serailizers.ValidationError({'my_field': 'A field error'}) + raise serializers.ValidationError({'my_field': 'A field error'}) This ensures you can still write validation that compares all the input fields, but that marks the error against a particular field. @@ -303,7 +303,7 @@ Alternatively, specify the field explicitly on the serializer class: model = MyModel fields = ('id', 'email', 'notes', 'is_admin') -The `read_only_fields` option remains as a convenient shortcut for the more common case. +The `read_only_fields` option remains as a convenient shortcut for the more common case. #### Changes to `HyperlinkedModelSerializer`. @@ -364,7 +364,7 @@ The `ListSerializer` class has now been added, and allows you to create base ser class MultipleUserSerializer(ListSerializer): child = UserSerializer() -You can also still use the `many=True` argument to serializer classes. It's worth noting that `many=True` argument transparently creates a `ListSerializer` instance, allowing the validation logic for list and non-list data to be cleanly separated in the REST framework codebase. +You can also still use the `many=True` argument to serializer classes. It's worth noting that `many=True` argument transparently creates a `ListSerializer` instance, allowing the validation logic for list and non-list data to be cleanly separated in the REST framework codebase. You will typically want to *continue to use the existing `many=True` flag* rather than declaring `ListSerializer` classes explicitly, but declaring the classes explicitly can be useful if you need to write custom `create` or `update` methods for bulk updates, or provide for other custom behavior. @@ -436,7 +436,7 @@ Here's a complete example of our previous `HighScoreSerializer`, that's been upd def to_internal_value(self, data): score = data.get('score') player_name = data.get('player_name') - + # Perform the data validation. if not score: raise ValidationError({ @@ -450,7 +450,7 @@ Here's a complete example of our previous `HighScoreSerializer`, that's been upd raise ValidationError({ 'player_name': 'May not be more than 10 characters.' }) - + # Return the validated values. This will be available as # the `.validated_data` property. return { @@ -463,7 +463,7 @@ Here's a complete example of our previous `HighScoreSerializer`, that's been upd 'score': obj.score, 'player_name': obj.player_name } - + def create(self, validated_data): return HighScore.objects.create(**validated_data) @@ -471,7 +471,7 @@ Here's a complete example of our previous `HighScoreSerializer`, that's been upd The `BaseSerializer` class is also useful if you want to implement new generic serializer classes for dealing with particular serialization styles, or for integrating with alternative storage backends. -The following class is an example of a generic serializer that can handle coercing aribitrary objects into primitive representations. +The following class is an example of a generic serializer that can handle coercing aribitrary objects into primitive representations. class ObjectSerializer(serializers.BaseSerializer): """ @@ -542,7 +542,7 @@ The `default` argument is also available and always implies that the field is no #### Coercing output types. -The previous field implementations did not forcibly coerce returned values into the correct type in many cases. For example, an `IntegerField` would return a string output if the attribute value was a string. We now more strictly coerce to the correct return type, leading to more constrained and expected behavior. +The previous field implementations did not forcibly coerce returned values into the correct type in many cases. For example, an `IntegerField` would return a string output if the attribute value was a string. We now more strictly coerce to the correct return type, leading to more constrained and expected behavior. #### The `ListField` class. @@ -695,7 +695,7 @@ These classes are documented in the [Validators](../api-guide/validators.md) sec The view logic for the default method handlers has been significantly simplified, due to the new serializers API. -#### Changes to pre/post save hooks. +#### Changes to pre/post save hooks. The `pre_save` and `post_save` hooks no longer exist, but are replaced with `perform_create(self, serializer)` and `perform_update(self, serializer)`. @@ -887,4 +887,4 @@ The 3.2 release is planned to introduce an alternative admin-style interface to You can follow development on the GitHub site, where we use [milestones to indicate planning timescales](https://github.com/tomchristie/django-rest-framework/milestones). -[mixins.py]: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py \ No newline at end of file +[mixins.py]: https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/mixins.py -- cgit v1.2.3 From 790a651893c4bc6e68bc4d724d5df4ea3f883ced Mon Sep 17 00:00:00 2001 From: Gil Gonçalves Date: Mon, 24 Nov 2014 08:51:08 +0000 Subject: Fixed database update instructions --- docs/tutorial/4-authentication-and-permissions.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index adab1b55..4e4edeea 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -44,7 +44,9 @@ When that's all done we'll need to update our database tables. Normally we'd create a database migration in order to do that, but for the purposes of this tutorial, let's just delete the database and start again. rm tmp.db - python manage.py syncdb + rm -r snippets/migrations + python manage.py makemigrations snippets + python manage.py migrate You might also want to create a few different users, to use for testing the API. The quickest way to do this will be with the `createsuperuser` command. -- cgit v1.2.3 From 918b9cc6a605ee4701d77f73e93a62f04c2345b0 Mon Sep 17 00:00:00 2001 From: Gil Gonçalves Date: Mon, 24 Nov 2014 08:54:07 +0000 Subject: Added missing import in tutorial snippet --- docs/tutorial/6-viewsets-and-routers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/tutorial/6-viewsets-and-routers.md b/docs/tutorial/6-viewsets-and-routers.md index cf37a260..3fad509a 100644 --- a/docs/tutorial/6-viewsets-and-routers.md +++ b/docs/tutorial/6-viewsets-and-routers.md @@ -60,7 +60,7 @@ To see what's going on under the hood let's first explicitly create a set of vie In the `urls.py` file we bind our `ViewSet` classes into a set of concrete views. - from snippets.views import SnippetViewSet, UserViewSet + from snippets.views import SnippetViewSet, UserViewSet, api_root from rest_framework import renderers snippet_list = SnippetViewSet.as_view({ -- cgit v1.2.3 From 83e556ba1e129fac28a74b0a2784e4728f491a41 Mon Sep 17 00:00:00 2001 From: Marc Date: Tue, 25 Nov 2014 12:37:20 +0100 Subject: Missing quotes on validate_score example --- docs/topics/3.0-announcement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 694ad8a5..6a662326 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -170,7 +170,7 @@ We strongly recommend that you use the namespaced import style of `import serial The `validate_` method hooks that can be attached to serializer classes change their signature slightly and return type. Previously these would take a dictionary of all incoming data, and a key representing the field name, and would return a dictionary including the validated data for that field: def validate_score(self, attrs, source): - if attrs[score] % 10 != 0: + if attrs['score'] % 10 != 0: raise serializers.ValidationError('This field should be a multiple of ten.') return attrs -- cgit v1.2.3 From 2e726e22a394347b7337eb38a2a3a1b0ccde88bc Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 25 Nov 2014 11:42:43 +0000 Subject: request.DATA, request.FILES -> request.data --- docs/api-guide/exceptions.md | 4 ++-- docs/api-guide/parsers.md | 20 ++++++++++---------- docs/api-guide/requests.md | 21 ++++++++++++--------- docs/api-guide/settings.md | 2 +- docs/api-guide/viewsets.md | 2 +- docs/tutorial/2-requests-and-responses.md | 12 ++++++------ docs/tutorial/3-class-based-views.md | 4 ++-- 7 files changed, 34 insertions(+), 31 deletions(-) (limited to 'docs') diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index e61dcfa9..8a99abb9 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -100,7 +100,7 @@ For example, if your API relies on a third party service that may sometimes be u **Signature:** `ParseError(detail=None)` -Raised if the request contains malformed data when accessing `request.DATA` or `request.FILES`. +Raised if the request contains malformed data when accessing `request.data`. By default this exception results in a response with the HTTP status code "400 Bad Request". @@ -140,7 +140,7 @@ By default this exception results in a response with the HTTP status code "405 M **Signature:** `UnsupportedMediaType(media_type, detail=None)` -Raised if there are no parsers that can handle the content type of the request data when accessing `request.DATA` or `request.FILES`. +Raised if there are no parsers that can handle the content type of the request data when accessing `request.data`. By default this exception results in a response with the HTTP status code "415 Unsupported Media Type". diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index 72a4af64..a50b5240 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -12,7 +12,7 @@ REST framework includes a number of built in Parser classes, that allow you to a ## How the parser is determined -The set of valid parsers for a view is always defined as a list of classes. When either `request.DATA` or `request.FILES` is accessed, REST framework will examine the `Content-Type` header on the incoming request, and determine which parser to use to parse the request content. +The set of valid parsers for a view is always defined as a list of classes. When `request.data` is accessed, REST framework will examine the `Content-Type` header on the incoming request, and determine which parser to use to parse the request content. --- @@ -48,7 +48,7 @@ using the `APIView` class based views. parser_classes = (YAMLParser,) def post(self, request, format=None): - return Response({'received data': request.DATA}) + return Response({'received data': request.data}) Or, if you're using the `@api_view` decorator with function based views. @@ -58,7 +58,7 @@ Or, if you're using the `@api_view` decorator with function based views. """ A view that can accept POST requests with YAML content. """ - return Response({'received data': request.DATA}) + return Response({'received data': request.data}) --- @@ -92,7 +92,7 @@ Requires the `defusedxml` package to be installed. ## FormParser -Parses HTML form content. `request.DATA` will be populated with a `QueryDict` of data, `request.FILES` will be populated with an empty `QueryDict` of data. +Parses HTML form content. `request.data` will be populated with a `QueryDict` of data. You will typically want to use both `FormParser` and `MultiPartParser` together in order to fully support HTML form data. @@ -100,7 +100,7 @@ You will typically want to use both `FormParser` and `MultiPartParser` together ## MultiPartParser -Parses multipart HTML form content, which supports file uploads. Both `request.DATA` and `request.FILES` will be populated with a `QueryDict`. +Parses multipart HTML form content, which supports file uploads. Both `request.data` will be populated with a `QueryDict`. You will typically want to use both `FormParser` and `MultiPartParser` together in order to fully support HTML form data. @@ -108,7 +108,7 @@ You will typically want to use both `FormParser` and `MultiPartParser` together ## FileUploadParser -Parses raw file upload content. The `request.DATA` property will be an empty `QueryDict`, and `request.FILES` will be a dictionary with a single key `'file'` containing the uploaded file. +Parses raw file upload content. The `request.data` property will be a dictionary with a single key `'file'` containing the uploaded file. If the view used with `FileUploadParser` is called with a `filename` URL keyword argument, then that argument will be used as the filename. If it is called without a `filename` URL keyword argument, then the client must set the filename in the `Content-Disposition` HTTP header. For example `Content-Disposition: attachment; filename=upload.jpg`. @@ -126,7 +126,7 @@ If the view used with `FileUploadParser` is called with a `filename` URL keyword parser_classes = (FileUploadParser,) def put(self, request, filename, format=None): - file_obj = request.FILES['file'] + file_obj = request.data['file'] # ... # do some staff with uploaded file # ... @@ -139,7 +139,7 @@ If the view used with `FileUploadParser` is called with a `filename` URL keyword To implement a custom parser, you should override `BaseParser`, set the `.media_type` property, and implement the `.parse(self, stream, media_type, parser_context)` method. -The method should return the data that will be used to populate the `request.DATA` property. +The method should return the data that will be used to populate the `request.data` property. The arguments passed to `.parse()` are: @@ -161,7 +161,7 @@ By default this will include the following keys: `view`, `request`, `args`, `kwa ## Example -The following is an example plaintext parser that will populate the `request.DATA` property with a string representing the body of the request. +The following is an example plaintext parser that will populate the `request.data` property with a string representing the body of the request. class PlainTextParser(BaseParser): """ @@ -197,4 +197,4 @@ The following third party packages are also available. [juanriaza]: https://github.com/juanriaza [vbabiy]: https://github.com/vbabiy [djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack -[djangorestframework-camel-case]: https://github.com/vbabiy/djangorestframework-camel-case \ No newline at end of file +[djangorestframework-camel-case]: https://github.com/vbabiy/djangorestframework-camel-case diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md index 87425ed1..d659e17a 100644 --- a/docs/api-guide/requests.md +++ b/docs/api-guide/requests.md @@ -14,26 +14,29 @@ REST framework's `Request` class extends the standard `HttpRequest`, adding supp REST framework's Request objects provide flexible request parsing that allows you to treat requests with JSON data or other media types in the same way that you would normally deal with form data. -## .DATA +## .data -`request.DATA` returns the parsed content of the request body. This is similar to the standard `request.POST` attribute except that: +`request.data` returns the parsed content of the request body. This is similar to the standard `request.POST` and `request.FILES` attributes except that: +* It includes all parsed content, including *file and non-file* inputs. * It supports parsing the content of HTTP methods other than `POST`, meaning that you can access the content of `PUT` and `PATCH` requests. * It supports REST framework's flexible request parsing, rather than just supporting form data. For example you can handle incoming JSON data in the same way that you handle incoming form data. For more details see the [parsers documentation]. -## .FILES +## .query_params -`request.FILES` returns any uploaded files that may be present in the content of the request body. This is the same as the standard `HttpRequest` behavior, except that the same flexible request parsing is used for `request.DATA`. +`request.query_params` is a more correctly named synonym for `request.GET`. -For more details see the [parsers documentation]. +For clarity inside your code, we recommend using `request.query_params` instead of the Django's standard `request.GET`. Doing so will help keep your codebase more correct and obvious - any HTTP method type may include query parameters, not just `GET` requests. -## .QUERY_PARAMS +## .DATA and .FILES -`request.QUERY_PARAMS` is a more correctly named synonym for `request.GET`. +The old-style version 2.x `request.data` and `request.FILES` attributes are still available, but are now pending deprecation in favor of the unified `request.data` attribute. + +## .QUERY_PARAMS -For clarity inside your code, we recommend using `request.QUERY_PARAMS` instead of the usual `request.GET`, as *any* HTTP method type may include query parameters. +The old-style version 2.x `request.QUERY_PARAMS` attribute is still available, but is now pending deprecation in favor of the more pythonic `request.query_params`. ## .parsers @@ -43,7 +46,7 @@ You won't typically need to access this property. --- -**Note:** If a client sends malformed content, then accessing `request.DATA` or `request.FILES` may raise a `ParseError`. By default REST framework's `APIView` class or `@api_view` decorator will catch the error and return a `400 Bad Request` response. +**Note:** If a client sends malformed content, then accessing `request.data` may raise a `ParseError`. By default REST framework's `APIView` class or `@api_view` decorator will catch the error and return a `400 Bad Request` response. If a client sends a request with a content-type that cannot be parsed then a `UnsupportedMediaType` exception will be raised, which by default will be caught and return a `415 Unsupported Media Type` response. diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 96d715ea..ba470f8b 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -51,7 +51,7 @@ Default: #### DEFAULT_PARSER_CLASSES -A list or tuple of parser classes, that determines the default set of parsers used when accessing the `request.DATA` property. +A list or tuple of parser classes, that determines the default set of parsers used when accessing the `request.data` property. Default: diff --git a/docs/api-guide/viewsets.md b/docs/api-guide/viewsets.md index 9030e3ee..f60d4a47 100644 --- a/docs/api-guide/viewsets.md +++ b/docs/api-guide/viewsets.md @@ -124,7 +124,7 @@ For example: @detail_route(methods=['post']) def set_password(self, request, pk=None): user = self.get_object() - serializer = PasswordSerializer(data=request.DATA) + serializer = PasswordSerializer(data=request.data) if serializer.is_valid(): user.set_password(serializer.data['password']) user.save() diff --git a/docs/tutorial/2-requests-and-responses.md b/docs/tutorial/2-requests-and-responses.md index 136b0135..f377c712 100644 --- a/docs/tutorial/2-requests-and-responses.md +++ b/docs/tutorial/2-requests-and-responses.md @@ -5,10 +5,10 @@ Let's introduce a couple of essential building blocks. ## Request objects -REST framework introduces a `Request` object that extends the regular `HttpRequest`, and provides more flexible request parsing. The core functionality of the `Request` object is the `request.DATA` attribute, which is similar to `request.POST`, but more useful for working with Web APIs. +REST framework introduces a `Request` object that extends the regular `HttpRequest`, and provides more flexible request parsing. The core functionality of the `Request` object is the `request.data` attribute, which is similar to `request.POST`, but more useful for working with Web APIs. request.POST # Only handles form data. Only works for 'POST' method. - request.DATA # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods. + request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods. ## Response objects @@ -29,7 +29,7 @@ REST framework provides two wrappers you can use to write API views. These wrappers provide a few bits of functionality such as making sure you receive `Request` instances in your view, and adding context to `Response` objects so that content negotiation can be performed. -The wrappers also provide behaviour such as returning `405 Method Not Allowed` responses when appropriate, and handling any `ParseError` exception that occurs when accessing `request.DATA` with malformed input. +The wrappers also provide behaviour such as returning `405 Method Not Allowed` responses when appropriate, and handling any `ParseError` exception that occurs when accessing `request.data` with malformed input. ## Pulling it all together @@ -55,7 +55,7 @@ We don't need our `JSONResponse` class in `views.py` anymore, so go ahead and de return Response(serializer.data) elif request.method == 'POST': - serializer = SnippetSerializer(data=request.DATA) + serializer = SnippetSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) @@ -80,7 +80,7 @@ Here is the view for an individual snippet, in the `views.py` module. return Response(serializer.data) elif request.method == 'PUT': - serializer = SnippetSerializer(snippet, data=request.DATA) + serializer = SnippetSerializer(snippet, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) @@ -92,7 +92,7 @@ Here is the view for an individual snippet, in the `views.py` module. This should all feel very familiar - it is not a lot different from working with regular Django views. -Notice that we're no longer explicitly tying our requests or responses to a given content type. `request.DATA` can handle incoming `json` requests, but it can also handle `yaml` and other formats. Similarly we're returning response objects with data, but allowing REST framework to render the response into the correct content type for us. +Notice that we're no longer explicitly tying our requests or responses to a given content type. `request.data` can handle incoming `json` requests, but it can also handle `yaml` and other formats. Similarly we're returning response objects with data, but allowing REST framework to render the response into the correct content type for us. ## Adding optional format suffixes to our URLs diff --git a/docs/tutorial/3-class-based-views.md b/docs/tutorial/3-class-based-views.md index 382f078a..0a9ea3f1 100644 --- a/docs/tutorial/3-class-based-views.md +++ b/docs/tutorial/3-class-based-views.md @@ -24,7 +24,7 @@ We'll start by rewriting the root view as a class based view. All this involves return Response(serializer.data) def post(self, request, format=None): - serializer = SnippetSerializer(data=request.DATA) + serializer = SnippetSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) @@ -49,7 +49,7 @@ So far, so good. It looks pretty similar to the previous case, but we've got be def put(self, request, pk, format=None): snippet = self.get_object(pk) - serializer = SnippetSerializer(snippet, data=request.DATA) + serializer = SnippetSerializer(snippet, data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data) -- cgit v1.2.3 From a3c0c8fb90f084d494cdf46551c8a6228ca5ffd0 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 25 Nov 2014 12:04:35 +0000 Subject: Add missing period. --- docs/api-guide/generic-views.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index 49a5e58f..16ae8c55 100755 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -352,7 +352,7 @@ You can then simply apply this mixin to a view or viewset anytime you need to ap serializer_class = UserSerializer lookup_fields = ('account', 'username') -Using custom mixins is a good option if you have custom behavior that needs to be used +Using custom mixins is a good option if you have custom behavior that needs to be used. ## Creating custom base classes -- cgit v1.2.3 From c4dff54ecc487b192d17763e48adc0bfcaa620d3 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 25 Nov 2014 12:04:46 +0000 Subject: Docs on ValidationError --- docs/api-guide/exceptions.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'docs') diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index 8a99abb9..33eb74c8 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -152,5 +152,23 @@ Raised when an incoming request fails the throttling checks. By default this exception results in a response with the HTTP status code "429 Too Many Requests". +## ValidationError + +**Signature:** `ValidationError(detail)` + +The `ValidationError` exception is slightly different from the other `APIException` classes: + +* The `detail` argument is mandatory, not optional. +* The `detail` argument may be a list or dictionary of error details, and may also be a nested data structure. +* By convention you should import the serializers module and use a fully qualified `ValidationError` style, in order to differentiate it from Django's built-in validation error. For example. `raise serializers.ValidationError('This field must be an integer value.')` + +The `ValidationError` class should be used for serializer and field validation, and by validator classes. It is also raised when calling `serializer.is_valid` with the `raise_exception` keyword argument: + + serializer.is_valid(raise_exception=True) + +The generic views use the `raise_exception=True` flag, which means that you can override the style of validation error responses globally in your API. To do so, use a custom exception handler, as described above. + +By default this exception results in a response with the HTTP status code "400 Bad Request". + [cite]: http://www.doughellmann.com/articles/how-tos/python-exception-handling/index.html [authentication]: authentication.md -- cgit v1.2.3 From 83281254d1a4685535ab877fb9f9affeb93578bd Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 25 Nov 2014 12:06:27 +0000 Subject: Hypenate 'un-coerced' --- docs/topics/3.0-announcement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 694ad8a5..24b0923f 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -865,7 +865,7 @@ Or modify it on an individual serializer field, using the `coerce_to_string` key coerce_to_string=False ) -The default JSON renderer will return float objects for uncoerced `Decimal` instances. This allows you to easily switch between string or float representations for decimals depending on your API design needs. +The default JSON renderer will return float objects for un-coerced `Decimal` instances. This allows you to easily switch between string or float representations for decimals depending on your API design needs. ## Miscellaneous notes. -- cgit v1.2.3 From 3b40f8c1c110ef44d112a705652b9ef57a36d9c9 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 25 Nov 2014 12:15:48 +0000 Subject: Drop 0.x release notes --- docs/topics/release-notes.md | 122 ++----------------------------------------- 1 file changed, 4 insertions(+), 118 deletions(-) (limited to 'docs') diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 88780c3f..efc49ba1 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -442,7 +442,7 @@ The security vulnerabilities only affect APIs which use the `XMLParser` class, b * Bugfix: Validation errors instead of exceptions when related fields receive incorrect types. * Bugfix: Handle ObjectDoesNotExist exception when serializing null reverse one-to-one -**Note**: Prior to 2.1.16, The Decimals would render in JSON using floating point if `simplejson` was installed, but otherwise render using string notation. Now that use of `simplejson` has been deprecated, Decimals will consistently render using string notation. See [#582] for more details. +**Note**: Prior to 2.1.16, The Decimals would render in JSON using floating point if `simplejson` was installed, but otherwise render using string notation. Now that use of `simplejson` has been deprecated, Decimals will consistently render using string notation. See [ticket 582](ticket-582) for more details. ### 2.1.15 @@ -614,122 +614,7 @@ This change will not affect user code, so long as it's following the recommended * **Fix all of the things.** (Well, almost.) * For more information please see the [2.0 announcement][announcement]. ---- - -## 0.4.x series - -### 0.4.0 - -* Supports Django 1.5. -* Fixes issues with 'HEAD' method. -* Allow views to specify template used by TemplateRenderer -* More consistent error responses -* Some serializer fixes -* Fix internet explorer ajax behavior -* Minor xml and yaml fixes -* Improve setup (e.g. use staticfiles, not the defunct ADMIN_MEDIA_PREFIX) -* Sensible absolute URL generation, not using hacky set_script_prefix - ---- - -## 0.3.x series - -### 0.3.3 - -* Added DjangoModelPermissions class to support `django.contrib.auth` style permissions. -* Use `staticfiles` for css files. - - Easier to override. Won't conflict with customized admin styles (e.g. grappelli) -* Templates are now nicely namespaced. - - Allows easier overriding. -* Drop implied 'pk' filter if last arg in urlconf is unnamed. - - Too magical. Explicit is better than implicit. -* Saner template variable auto-escaping. -* Tidier setup.py -* Updated for URLObject 2.0 -* Bugfixes: - - Bug with PerUserThrottling when user contains unicode chars. - -### 0.3.2 - -* Bugfixes: - * Fix 403 for POST and PUT from the UI with UserLoggedInAuthentication (#115) - * serialize_model method in serializer.py may cause wrong value (#73) - * Fix Error when clicking OPTIONS button (#146) - * And many other fixes -* Remove short status codes - - Zen of Python: "There should be one-- and preferably only one --obvious way to do it." -* get_name, get_description become methods on the view - makes them overridable. -* Improved model mixin API - Hooks for build_query, get_instance_data, get_model, get_queryset, get_ordering - -### 0.3.1 - -* [not documented] - -### 0.3.0 - -* JSONP Support -* Bugfixes, including support for latest markdown release - ---- - -## 0.2.x series - -### 0.2.4 - -* Fix broken IsAdminUser permission. -* OPTIONS support. -* XMLParser. -* Drop mentions of Blog, BitBucket. - -### 0.2.3 - -* Fix some throttling bugs. -* ``X-Throttle`` header on throttling. -* Support for nesting resources on related models. - -### 0.2.2 - -* Throttling support complete. - -### 0.2.1 - -* Couple of simple bugfixes over 0.2.0 - -### 0.2.0 - -* Big refactoring changes since 0.1.0, ask on the discussion group if anything isn't clear. - The public API has been massively cleaned up. Expect it to be fairly stable from here on in. - -* ``Resource`` becomes decoupled into ``View`` and ``Resource``, your views should now inherit from ``View``, not ``Resource``. - -* The handler functions on views ``.get() .put() .post()`` etc, no longer have the ``content`` and ``auth`` args. - Use ``self.CONTENT`` inside a view to access the deserialized, validated content. - Use ``self.user`` inside a view to access the authenticated user. - -* ``allowed_methods`` and ``anon_allowed_methods`` are now defunct. if a method is defined, it's available. - The ``permissions`` attribute on a ``View`` is now used to provide generic permissions checking. - Use permission classes such as ``FullAnonAccess``, ``IsAuthenticated`` or ``IsUserOrIsAnonReadOnly`` to set the permissions. - -* The ``authenticators`` class becomes ``authentication``. Class names change to ``Authentication``. - -* The ``emitters`` class becomes ``renderers``. Class names change to ``Renderers``. - -* ``ResponseException`` becomes ``ErrorResponse``. - -* The mixin classes have been nicely refactored, the basic mixins are now ``RequestMixin``, ``ResponseMixin``, ``AuthMixin``, and ``ResourceMixin`` - You can reuse these mixin classes individually without using the ``View`` class. - ---- - -## 0.1.x series - -### 0.1.1 - -* Final build before pulling in all the refactoring changes for 0.2, in case anyone needs to hang on to 0.1. - -### 0.1.0 - -* Initial release. +For older release notes, [please see the GitHub repo](old-release-notes). [cite]: http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html [deprecation-policy]: #deprecation-policy @@ -742,5 +627,6 @@ This change will not affect user code, so long as it's following the recommended [staticfiles13]: https://docs.djangoproject.com/en/1.3/howto/static-files/#with-a-template-tag [2.1.0-notes]: https://groups.google.com/d/topic/django-rest-framework/Vv2M0CMY9bg/discussion [announcement]: rest-framework-2-announcement.md -[#582]: https://github.com/tomchristie/django-rest-framework/issues/582 +[ticket-582]: https://github.com/tomchristie/django-rest-framework/issues/582 [rfc-6266]: http://tools.ietf.org/html/rfc6266#section-4.3 +[old-release-notes]: https://github.com/tomchristie/django-rest-framework/blob/2.4.4/docs/topics/release-notes.md#04x-series -- cgit v1.2.3 From 3a648b9f0b0aa9a955065b96ea1a03376816ec00 Mon Sep 17 00:00:00 2001 From: Dougal Matthews Date: Thu, 9 Oct 2014 10:14:04 +0100 Subject: Migrate documentation to MkDocs proper --- docs/404.html | 201 ------------------------------------------ docs/template.html | 239 ------------------------------------------------- docs/theme/404.html | 201 ++++++++++++++++++++++++++++++++++++++++++ docs/theme/base.html | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 445 insertions(+), 440 deletions(-) delete mode 100644 docs/404.html delete mode 100644 docs/template.html create mode 100644 docs/theme/404.html create mode 100644 docs/theme/base.html (limited to 'docs') diff --git a/docs/404.html b/docs/404.html deleted file mode 100644 index 864247e7..00000000 --- a/docs/404.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - Django REST framework - 404 - Page not found - - - - - - - - - - - - - - - - - - - -
- - - -
-
- - - - -
-
-

404

-

Page not found

-

Try the homepage, or search the documentation.

-
-
-
-
- -
-
- - - - - - - - - - diff --git a/docs/template.html b/docs/template.html deleted file mode 100644 index f36cffc6..00000000 --- a/docs/template.html +++ /dev/null @@ -1,239 +0,0 @@ - - - - - {{ title }} - - - - - - - - - - - - - - - - - - - - -
- - - -
-
- - - - -
- -
- -
- - -
-
- -
- {{ content }} -
-
-
-
- -
-
- - - - - - - - - - - diff --git a/docs/theme/404.html b/docs/theme/404.html new file mode 100644 index 00000000..864247e7 --- /dev/null +++ b/docs/theme/404.html @@ -0,0 +1,201 @@ + + + + + Django REST framework - 404 - Page not found + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + + + +
+
+

404

+

Page not found

+

Try the homepage, or search the documentation.

+
+
+
+
+ +
+
+ + + + + + + + + + diff --git a/docs/theme/base.html b/docs/theme/base.html new file mode 100644 index 00000000..45e19cf3 --- /dev/null +++ b/docs/theme/base.html @@ -0,0 +1,244 @@ + + + + + {{ title }} + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+ + + + +
+ +
+ +
+ + +
+
+ +
+ {{ content }} +
+
+
+
+ +
+
+ + + + + + + + + + + -- cgit v1.2.3 From 261c4ce9aff6725a4e069cf45d0f57ec97a27bdb Mon Sep 17 00:00:00 2001 From: Dougal Matthews Date: Wed, 22 Oct 2014 21:13:40 +0100 Subject: Remove redundant requirements file --- docs/requirements.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 docs/requirements.txt (limited to 'docs') diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index a91fb978..00000000 --- a/docs/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -markdown>=2.1.0 -- cgit v1.2.3 From 84d9c4b46eacda54b31a3779c623554758f4dccc Mon Sep 17 00:00:00 2001 From: Dougal Matthews Date: Wed, 22 Oct 2014 21:36:11 +0100 Subject: Change site_dir to html to match mkdocs.py --- docs/topics/contributing.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/topics/contributing.md b/docs/topics/contributing.md index 52f6e287..5809af65 100644 --- a/docs/topics/contributing.md +++ b/docs/topics/contributing.md @@ -135,15 +135,15 @@ There are many great Markdown editors that make working with the documentation r ## Building the documentation -To build the documentation, simply run the `mkdocs.py` script. +To build the documentation, simply install MkDocs with `pip install mkdocs` and then run the following command. - ./mkdocs.py + mkdocs build This will build the html output into the `html` directory. -You can build the documentation and open a preview in a browser window by using the `-p` flag. +You can build the documentation and open a preview in a browser window by using the `serve` command. - ./mkdocs.py -p + mkdocs serve ## Language style -- cgit v1.2.3 From 2ddef2d3263b2187fd502e42eaaecc3a4f0ad2b2 Mon Sep 17 00:00:00 2001 From: Dougal Matthews Date: Thu, 23 Oct 2014 14:10:23 +0100 Subject: Drop simply from the mkdocs install lines It is still simple tho', honest ;) --- docs/topics/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/topics/contributing.md b/docs/topics/contributing.md index 5809af65..c7991a0f 100644 --- a/docs/topics/contributing.md +++ b/docs/topics/contributing.md @@ -135,7 +135,7 @@ There are many great Markdown editors that make working with the documentation r ## Building the documentation -To build the documentation, simply install MkDocs with `pip install mkdocs` and then run the following command. +To build the documentation, install MkDocs with `pip install mkdocs` and then run the following command. mkdocs build -- cgit v1.2.3 From d6b203f013890cc25f5454696805bc85c1ca2482 Mon Sep 17 00:00:00 2001 From: José Padilla Date: Tue, 28 Oct 2014 17:40:29 -0400 Subject: Use page_title instead of title in docs theme --- docs/theme/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/theme/base.html b/docs/theme/base.html index 45e19cf3..943a60e4 100644 --- a/docs/theme/base.html +++ b/docs/theme/base.html @@ -2,7 +2,7 @@ - {{ title }} + {{ page_title }} -- cgit v1.2.3 From 18712a5cbcbb25d935b93baac589cacfe1cbb754 Mon Sep 17 00:00:00 2001 From: Dougal Matthews Date: Wed, 29 Oct 2014 20:54:20 +0000 Subject: Fix the Navigation style --- docs/theme/base.html | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'docs') diff --git a/docs/theme/base.html b/docs/theme/base.html index 943a60e4..e5ad4377 100644 --- a/docs/theme/base.html +++ b/docs/theme/base.html @@ -188,15 +188,12 @@ a.fusion-poweredby {
+
-- cgit v1.2.3 From 49a493f61f4d5b4447d139d189d78995e65231b2 Mon Sep 17 00:00:00 2001 From: Dougal Matthews Date: Wed, 29 Oct 2014 20:54:31 +0000 Subject: Bring back the promo section --- docs/theme/base.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/theme/base.html b/docs/theme/base.html index e5ad4377..7ca7de14 100644 --- a/docs/theme/base.html +++ b/docs/theme/base.html @@ -191,7 +191,8 @@ a.fusion-poweredby {
  • {{ toc_item.title }}
  • {% endfor %}
    - {{ ad_block }} +
    +
    -- cgit v1.2.3 From 3c49b9fe4648d6fb291f0d34bf2e9ef4b72d45be Mon Sep 17 00:00:00 2001 From: Dougal Matthews Date: Wed, 29 Oct 2014 21:03:00 +0000 Subject: Add next and previous page. --- docs/theme/base.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/theme/base.html b/docs/theme/base.html index 7ca7de14..0f876cc1 100644 --- a/docs/theme/base.html +++ b/docs/theme/base.html @@ -57,8 +57,8 @@ a.fusion-poweredby {