mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-27 03:54:01 +03:00
232 lines
7.6 KiB
Markdown
232 lines
7.6 KiB
Markdown
# Tutorial 7: Schemas & client libraries
|
||
|
||
A schema is a machine-readable document that describes the available API
|
||
endpoints, their URLS, and what operations they support.
|
||
|
||
Schemas can be a useful tool for auto-generated documentation, and can also
|
||
be used to drive dynamic client libraries that can interact with the API.
|
||
|
||
## Core API
|
||
|
||
In order to provide schema support REST framework uses [Core API][coreapi].
|
||
|
||
Core API is a document specification for describing APIs. It is used to provide
|
||
an internal representation format of the available endpoints and possible
|
||
interactions that an API exposes. It can either be used server-side, or
|
||
client-side.
|
||
|
||
When used server-side, Core API allows an API to support rendering to a wide
|
||
range of schema or hypermedia formats.
|
||
|
||
When used client-side, Core API allows for dynamically driven client libraries
|
||
that can interact with any API that exposes a supported schema or hypermedia
|
||
format.
|
||
|
||
## Adding a schema
|
||
|
||
REST framework supports either explicitly defined schema views, or
|
||
automatically generated schemas. Since we're using viewsets and routers,
|
||
we can simply use the automatic schema generation.
|
||
|
||
You'll need to install the `coreapi` python package in order to include an
|
||
API schema, and `pyyaml` to render the schema into the commonly used
|
||
YAML-based OpenAPI format.
|
||
|
||
$ pip install coreapi pyyaml
|
||
|
||
We can now include a schema for our API, by including an autogenerated schema
|
||
view in our URL configuration.
|
||
|
||
```python
|
||
from rest_framework.schemas import get_schema_view
|
||
|
||
schema_view = get_schema_view(title='Pastebin API')
|
||
|
||
urlpatterns = [
|
||
path('schema/', schema_view),
|
||
...
|
||
]
|
||
```
|
||
|
||
If you visit the `/schema/` endpoint in a browser you should now see `corejson`
|
||
representation become available as an option.
|
||
|
||
![Schema format](../img/corejson-format.png)
|
||
|
||
We can also request the schema from the command line, by specifying the desired
|
||
content type in the `Accept` header.
|
||
|
||
$ http http://127.0.0.1:8000/schema/ Accept:application/coreapi+json
|
||
HTTP/1.0 200 OK
|
||
Allow: GET, HEAD, OPTIONS
|
||
Content-Type: application/coreapi+json
|
||
|
||
{
|
||
"_meta": {
|
||
"title": "Pastebin API"
|
||
},
|
||
"_type": "document",
|
||
...
|
||
|
||
The default output style is to use the [Core JSON][corejson] encoding.
|
||
|
||
Other schema formats, such as [Open API][openapi] (formerly Swagger) are
|
||
also supported.
|
||
|
||
## Using a command line client
|
||
|
||
Now that our API is exposing a schema endpoint, we can use a dynamic client
|
||
library to interact with the API. To demonstrate this, let's use the
|
||
Core API command line client.
|
||
|
||
The command line client is available as the `coreapi-cli` package:
|
||
|
||
$ pip install coreapi-cli
|
||
|
||
Now check that it is available on the command line...
|
||
|
||
$ coreapi
|
||
Usage: coreapi [OPTIONS] COMMAND [ARGS]...
|
||
|
||
Command line client for interacting with CoreAPI services.
|
||
|
||
Visit https://www.coreapi.org/ for more information.
|
||
|
||
Options:
|
||
--version Display the package version number.
|
||
--help Show this message and exit.
|
||
|
||
Commands:
|
||
...
|
||
|
||
First we'll load the API schema using the command line client.
|
||
|
||
$ coreapi get http://127.0.0.1:8000/schema/
|
||
<Pastebin API "http://127.0.0.1:8000/schema/">
|
||
snippets: {
|
||
highlight(id)
|
||
list()
|
||
read(id)
|
||
}
|
||
users: {
|
||
list()
|
||
read(id)
|
||
}
|
||
|
||
We haven't authenticated yet, so right now we're only able to see the read only
|
||
endpoints, in line with how we've set up the permissions on the API.
|
||
|
||
Let's try listing the existing snippets, using the command line client:
|
||
|
||
$ coreapi action snippets list
|
||
[
|
||
{
|
||
"url": "http://127.0.0.1:8000/snippets/1/",
|
||
"id": 1,
|
||
"highlight": "http://127.0.0.1:8000/snippets/1/highlight/",
|
||
"owner": "lucy",
|
||
"title": "Example",
|
||
"code": "print('hello, world!')",
|
||
"linenos": true,
|
||
"language": "python",
|
||
"style": "friendly"
|
||
},
|
||
...
|
||
|
||
Some of the API endpoints require named parameters. For example, to get back
|
||
the highlight HTML for a particular snippet we need to provide an id.
|
||
|
||
$ coreapi action snippets highlight --param id=1
|
||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||
|
||
<html>
|
||
<head>
|
||
<title>Example</title>
|
||
...
|
||
|
||
## Authenticating our client
|
||
|
||
If we want to be able to create, edit and delete snippets, we'll need to
|
||
authenticate as a valid user. In this case we'll just use basic auth.
|
||
|
||
Make sure to replace the `<username>` and `<password>` below with your
|
||
actual username and password.
|
||
|
||
$ coreapi credentials add 127.0.0.1 <username>:<password> --auth basic
|
||
Added credentials
|
||
127.0.0.1 "Basic <...>"
|
||
|
||
Now if we fetch the schema again, we should be able to see the full
|
||
set of available interactions.
|
||
|
||
$ coreapi reload
|
||
Pastebin API "http://127.0.0.1:8000/schema/">
|
||
snippets: {
|
||
create(code, [title], [linenos], [language], [style])
|
||
delete(id)
|
||
highlight(id)
|
||
list()
|
||
partial_update(id, [title], [code], [linenos], [language], [style])
|
||
read(id)
|
||
update(id, code, [title], [linenos], [language], [style])
|
||
}
|
||
users: {
|
||
list()
|
||
read(id)
|
||
}
|
||
|
||
We're now able to interact with these endpoints. For example, to create a new
|
||
snippet:
|
||
|
||
$ coreapi action snippets create --param title="Example" --param code="print('hello, world')"
|
||
{
|
||
"url": "http://127.0.0.1:8000/snippets/7/",
|
||
"id": 7,
|
||
"highlight": "http://127.0.0.1:8000/snippets/7/highlight/",
|
||
"owner": "lucy",
|
||
"title": "Example",
|
||
"code": "print('hello, world')",
|
||
"linenos": false,
|
||
"language": "python",
|
||
"style": "friendly"
|
||
}
|
||
|
||
And to delete a snippet:
|
||
|
||
$ coreapi action snippets delete --param id=7
|
||
|
||
As well as the command line client, developers can also interact with your
|
||
API using client libraries. The Python client library is the first of these
|
||
to be available, and a Javascript client library is planned to be released
|
||
soon.
|
||
|
||
For more details on customizing schema generation and using Core API
|
||
client libraries you'll need to refer to the full documentation.
|
||
|
||
## Reviewing our work
|
||
|
||
With an incredibly small amount of code, we've now got a complete pastebin Web API, which is fully web browsable, includes a schema-driven client library, and comes complete with authentication, per-object permissions, and multiple renderer formats.
|
||
|
||
We've walked through each step of the design process, and seen how if we need to customize anything we can gradually work our way down to simply using regular Django views.
|
||
|
||
You can review the final [tutorial code][repo] on GitHub, or try out a live example in [the sandbox][sandbox].
|
||
|
||
## Onwards and upwards
|
||
|
||
We've reached the end of our tutorial. If you want to get more involved in the REST framework project, here are a few places you can start:
|
||
|
||
* Contribute on [GitHub][github] by reviewing and submitting issues, and making pull requests.
|
||
* Join the [REST framework discussion group][group], and help build the community.
|
||
* Follow [the author][twitter] on Twitter and say hi.
|
||
|
||
**Now go build awesome things.**
|
||
|
||
[coreapi]: https://www.coreapi.org/
|
||
[corejson]: https://www.coreapi.org/specification/encoding/#core-json-encoding
|
||
[openapi]: https://openapis.org/
|
||
[repo]: https://github.com/encode/rest-framework-tutorial
|
||
[sandbox]: https://restframework.herokuapp.com/
|
||
[github]: https://github.com/encode/django-rest-framework
|
||
[group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework
|
||
[twitter]: https://twitter.com/_tomchristie
|