diff --git a/.gitignore b/.gitignore index 2255cd9aa..ae73f8379 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .* html/ +htmlcov/ coverage/ build/ dist/ diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 8cf995b38..5d6e0d91d 100755 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -355,6 +355,10 @@ HTTP digest authentication is a widely implemented scheme that was intended to r The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support, and works with Python 2.7 and Python 3.3+. The package is maintained by [Evonove][evonove] and uses the excelllent [OAuthLib][oauthlib]. The package is well documented, and comes as a recommended alternative for OAuth 2.0 support. +## Django OAuth2 Consumer + +The [Django OAuth2 Consumer][doac] library from [Rediker Software][rediker] is another package that provides [OAuth 2.0 support for REST framework][doac-rest-framework]. The package includes token scoping permissions on tokens, which allows finer-grained access to your API. + [cite]: http://jacobian.org/writing/rest-worst-practices/ [http401]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 [http403]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4 @@ -376,3 +380,6 @@ The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 supp [django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit [evonove]: https://github.com/evonove/ [oauthlib]: https://github.com/idan/oauthlib +[doac]: https://github.com/Rediker-Software/doac +[rediker]: https://github.com/Rediker-Software +[doac-rest-framework]: https://github.com/Rediker-Software/doac/blob/master/docs/markdown/integrations.md# diff --git a/docs/api-guide/routers.md b/docs/api-guide/routers.md index b74b6e13b..865829057 100644 --- a/docs/api-guide/routers.md +++ b/docs/api-guide/routers.md @@ -98,7 +98,23 @@ As with `SimpleRouter` the trailing slashs on the URL routes can be removed by s Implementing a custom router isn't something you'd need to do very often, but it can be useful if you have specific requirements about how the your URLs for your API are strutured. Doing so allows you to encapsulate the URL structure in a reusable way that ensures you don't have to write your URL patterns explicitly for each new view. -The simplest way to implement a custom router is to subclass one of the existing router classes. The `.routes` attribute is used to template the URL patterns that will be mapped to each viewset. +The simplest way to implement a custom router is to subclass one of the existing router classes. The `.routes` attribute is used to template the URL patterns that will be mapped to each viewset. The `.routes` attribute is a list of `Route` named tuples. + +The arguments to the `Route` named tuple are: + +**url**: A string representing the URL to be routed. May include the following format strings: + +* `{prefix}` - The URL prefix to use for this set of routes. +* `{lookup}` - The lookup field used to match against a single instance. +* `{trailing_slash}` - Either a '/' or an empty string, depending on the `trailing_slash` argument. + +**mapping**: A mapping of HTTP method names to the view methods + +**name**: The name of the URL as used in `reverse` calls. May include the following format string: + +* `{basename}` - The base to use for the URL names that are created. + +**initkwargs**: A dictionary of any additional arguments that should be passed when instantiating the view. Note that the `suffix` argument is reserved for identifying the viewset type, used when generating the view name and breadcrumb links. ## Example @@ -106,13 +122,21 @@ The following example will only route to the `list` and `retrieve` actions, and class ReadOnlyRouter(SimpleRouter): """ - A router for read-only APIs, which doesn't use trailing suffixes. + A router for read-only APIs, which doesn't use trailing slashes. """ routes = [ - (r'^{prefix}$', {'get': 'list'}, '{basename}-list'), - (r'^{prefix}/{lookup}$', {'get': 'retrieve'}, '{basename}-detail') + Route(url=r'^{prefix}$', + mapping={'get': 'list'}, + name='{basename}-list', + initkwargs={'suffix': 'List'}), + Route(url=r'^{prefix}/{lookup}$', + mapping={'get': 'retrieve'}, + name='{basename}-detail', + initkwargs={'suffix': 'Detail'}) ] +The `SimpleRouter` class provides another example of setting the `.routes` attribute. + ## Advanced custom routers If you want to provide totally custom behavior, you can override `BaseRouter` and override the `get_urls(self)` method. The method should insect the registered viewsets and return a list of URL patterns. The registered prefix, viewset and basename tuples may be inspected by accessing the `self.registry` attribute. diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index f8761cb2b..8e9de10e0 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -423,6 +423,49 @@ You can create customized subclasses of `ModelSerializer` or `HyperlinkedModelSe Doing so should be considered advanced usage, and will only be needed if you have some particular serializer requirements that you often need to repeat. +## Dynamically modifiying fields + +Once a serializer has been initialized, the dictionary of fields that are set on the serializer may be accessed using the `.fields` attribute. Accessing and modifying this attribute allows you to dynamically modify the serializer. + +Modifying the `fields` argument directly allows you to do interesting things such as changing the arguments on serializer fields at runtime, rather than at the point of declaring the serializer. + +### Example + +For example, if you wanted to be able to set which fields should be used by a serializer at the point of initializing it, you could create a serializer class like so: + + class DynamicFieldsModelSerializer(serializers.ModelSerializer): + """ + A ModelSerializer that takes an additional `fields` argument that + controls which fields should be displayed. + """ + + def __init__(self, *args, **kwargs): + # Don't pass the 'fields' arg up to the superclass + fields = kwargs.pop('fields', None) + + # Instatiate the superclass normally + super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs) + + if fields: + # Drop any fields that are not specified in the `fields` argument. + allowed = set(fields) + existing = set(self.fields.keys()) + for field_name in existing - allowed: + self.fields.pop(field_name) + +This would then allow you to do the following: + + >>> class UserSerializer(DynamicFieldsModelSerializer): + >>> class Meta: + >>> model = User + >>> fields = ('id', 'username', 'email') + >>> + >>> print UserSerializer(user) + {'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'} + >>> + >>> print UserSerializer(user, fields=('id', 'email')) + {'id': 2, 'email': 'jon@example.com'} + ## Customising the default fields The `field_mapping` attribute is a dictionary that maps model classes to serializer classes. Overriding the attribute will let you set a different set of default serializer classes. @@ -457,7 +500,7 @@ Note that the `model_field` argument will be `None` for reverse relationships. Returns the field instance that should be used for non-relational, non-pk fields. -## Example +### Example The following custom model serializer could be used as a base class for model serializers that should always exclude the pk by default. diff --git a/docs/img/apiary.png b/docs/img/apiary.png new file mode 100644 index 000000000..923d384eb Binary files /dev/null and b/docs/img/apiary.png differ diff --git a/docs/img/cerulean.png b/docs/img/cerulean.png new file mode 100644 index 000000000..e647d5e81 Binary files /dev/null and b/docs/img/cerulean.png differ diff --git a/docs/img/django-rest-swagger.png b/docs/img/django-rest-swagger.png new file mode 100644 index 000000000..96a6b2380 Binary files /dev/null and b/docs/img/django-rest-swagger.png differ diff --git a/docs/img/rest-framework-docs.png b/docs/img/rest-framework-docs.png new file mode 100644 index 000000000..736a00955 Binary files /dev/null and b/docs/img/rest-framework-docs.png differ diff --git a/docs/img/self-describing.png b/docs/img/self-describing.png new file mode 100644 index 000000000..ecbe4fe40 Binary files /dev/null and b/docs/img/self-describing.png differ diff --git a/docs/img/slate.png b/docs/img/slate.png new file mode 100644 index 000000000..31644eafe Binary files /dev/null and b/docs/img/slate.png differ diff --git a/docs/index.md b/docs/index.md index de4b01c61..99cd6b882 100644 --- a/docs/index.md +++ b/docs/index.md @@ -170,6 +170,7 @@ The API guide is your complete reference manual to all the functionality provide General guides to using REST framework. +* [Documenting your API][documenting-your-api] * [AJAX, CSRF & CORS][ajax-csrf-cors] * [Browser enhancements][browser-enhancements] * [The Browsable API][browsableapi] @@ -289,6 +290,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [status]: api-guide/status-codes.md [settings]: api-guide/settings.md +[documenting-your-api]: topics/documenting-your-api.md [ajax-csrf-cors]: topics/ajax-csrf-cors.md [browser-enhancements]: topics/browser-enhancements.md [browsableapi]: topics/browsable-api.md diff --git a/docs/template.html b/docs/template.html index 217710250..27bc10622 100644 --- a/docs/template.html +++ b/docs/template.html @@ -95,6 +95,7 @@