|
| 1 | +<style> |
| 2 | +.promo li a { |
| 3 | + float: left; |
| 4 | + width: 130px; |
| 5 | + height: 20px; |
| 6 | + text-align: center; |
| 7 | + margin: 10px 30px; |
| 8 | + padding: 150px 0 0 0; |
| 9 | + background-position: 0 50%; |
| 10 | + background-size: 130px auto; |
| 11 | + background-repeat: no-repeat; |
| 12 | + font-size: 120%; |
| 13 | + color: black; |
| 14 | +} |
| 15 | +.promo li { |
| 16 | + list-style: none; |
| 17 | +} |
| 18 | +</style> |
| 19 | + |
| 20 | +# Django REST framework 3.5 |
| 21 | + |
| 22 | +The 3.5 release is the second in a planned series that is addressing schema |
| 23 | +generation, hypermedia support, API client libraries, and finally realtime support. |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## Funding |
| 28 | + |
| 29 | +The 3.5 release would not have been possible without our [collaborative funding model][funding]. |
| 30 | +If you use REST framework commercially and would like to see this work continue, |
| 31 | +we strongly encourage you to invest in its continued development by |
| 32 | +**[signing up for a paid plan][funding]**. |
| 33 | + |
| 34 | +<ul class="premium-promo promo"> |
| 35 | + <li><a href="http://jobs.rover.com/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rover_130x130.png)">Rover.com</a></li> |
| 36 | + <li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li> |
| 37 | + <li><a href="https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/stream-130.png)">Stream</a></li> |
| 38 | + <li><a href="http://www.machinalis.com/#services" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/Machinalis130.png)">Machinalis</a></li> |
| 39 | +</ul> |
| 40 | +<div style="clear: both; padding-bottom: 20px;"></div> |
| 41 | + |
| 42 | +*Many thanks to all our [sponsors][sponsors], and in particular to our premium backers, [Rover](http://jobs.rover.com/), [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), and [Machinalis](http://www.machinalis.com/#services).* |
| 43 | + |
| 44 | +--- |
| 45 | + |
| 46 | +## Improved schema generation |
| 47 | + |
| 48 | +Docstrings on views are now pulled through into schema definitions, allowing |
| 49 | +you to [use the schema definition to document your API][schema-docs]. |
| 50 | + |
| 51 | +There is now also a shortcut function, `get_schema_view()`, which makes it easier to |
| 52 | +[adding schema views][schema-view] to your API. |
| 53 | + |
| 54 | +For example, to include a swagger schema to your API, you would do the following: |
| 55 | + |
| 56 | +* Run `pip install django-rest-swagger`. |
| 57 | + |
| 58 | +* Add `'rest_framework_swagger'` to your `INSTALLED_APPS` setting. |
| 59 | + |
| 60 | +* Include the schema view in your URL conf: |
| 61 | + |
| 62 | +```py |
| 63 | +from rest_framework.schemas import get_schema_view |
| 64 | +from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer |
| 65 | + |
| 66 | +schema_view = get_schema_view( |
| 67 | + title='Example API', |
| 68 | + renderer_classes=[OpenAPIRenderer, SwaggerUIRenderer] |
| 69 | +) |
| 70 | + |
| 71 | +urlpatterns = [ |
| 72 | + url(r'^swagger/$', schema_view), |
| 73 | + ... |
| 74 | +] |
| 75 | +``` |
| 76 | + |
| 77 | +There have been a large number of fixes to the schema generation. These should |
| 78 | +resolve issues for anyone using the latest version of the `django-rest-swagger` |
| 79 | +package. |
| 80 | + |
| 81 | +Some of these changes do affect the resulting schema structure, |
| 82 | +so if you're already using schema generation you should make sure to review |
| 83 | +[the deprecation notes](#deprecations), particularly if you're currently using |
| 84 | +a dynamic client library to interact with your API. |
| 85 | + |
| 86 | +Finally, we're also now exposing the schema generation as a |
| 87 | +[publicly documented API][schema-generation-api], allowing you to more easily |
| 88 | +override the behaviour. |
| 89 | + |
| 90 | +## Requests test client |
| 91 | + |
| 92 | +You can now test your project using the `requests` library. |
| 93 | + |
| 94 | +This exposes exactly the same interface as if you were using a standard |
| 95 | +requests session instance. |
| 96 | + |
| 97 | + client = RequestsClient() |
| 98 | + response = client.get('http://testserver/users/') |
| 99 | + assert response.status_code == 200 |
| 100 | + |
| 101 | +Rather than sending any HTTP requests to the network, this interface will |
| 102 | +coerce all outgoing requests into WSGI, and call into your application directly. |
| 103 | + |
| 104 | +## Core API client |
| 105 | + |
| 106 | +You can also now test your project by interacting with it using the `coreapi` |
| 107 | +client library. |
| 108 | + |
| 109 | + # Fetch the API schema |
| 110 | + client = CoreAPIClient() |
| 111 | + schema = client.get('http://testserver/schema/') |
| 112 | + |
| 113 | + # Create a new organisation |
| 114 | + params = {'name': 'MegaCorp', 'status': 'active'} |
| 115 | + client.action(schema, ['organisations', 'create'], params) |
| 116 | + |
| 117 | + # Ensure that the organisation exists in the listing |
| 118 | + data = client.action(schema, ['organisations', 'list']) |
| 119 | + assert(len(data) == 1) |
| 120 | + assert(data == [{'name': 'MegaCorp', 'status': 'active'}]) |
| 121 | + |
| 122 | +Again, this will call directly into the application using the WSGI interface, |
| 123 | +rather than making actual network calls. |
| 124 | + |
| 125 | +This is a good option if you are planning for clients to mainly interact with |
| 126 | +your API using the `coreapi` client library, or some other auto-generated client. |
| 127 | + |
| 128 | +## Live tests |
| 129 | + |
| 130 | +One interesting aspect of both the `requests` client and the `coreapi` client |
| 131 | +is that they allow you to write tests in such a way that they can also be made |
| 132 | +to run against a live service. |
| 133 | + |
| 134 | +By switching the WSGI based client instances to actual instances of `requests.Session` |
| 135 | +or `coreapi.Client` you can have the test cases make actual network calls. |
| 136 | + |
| 137 | +Being able to write test cases that can exercise your staging or production |
| 138 | +environment is a powerful tool. However in order to do this, you'll need to pay |
| 139 | +close attention to how you handle setup and teardown to ensure a strict isolation |
| 140 | +of test data from other live or staging data. |
| 141 | + |
| 142 | +## RAML support |
| 143 | + |
| 144 | +We now have preliminary support for [RAML documentation generation][django-rest-raml]. |
| 145 | + |
| 146 | +![RAML Example][raml-image] |
| 147 | + |
| 148 | +Further work on the encoding and documentation generation is planned, in order to |
| 149 | +make features such as the 'Try it now' support available at a later date. |
| 150 | + |
| 151 | +This work also now means that you can use the Core API client libraries to interact |
| 152 | +with APIs that expose a RAML specification. The [RAML codec][raml-codec] gives some examples of |
| 153 | +interacting with the Spotify API in this way. |
| 154 | + |
| 155 | +## Validation codes |
| 156 | + |
| 157 | +Exceptions raised by REST framework now include short code identifiers. |
| 158 | +When used together with our customizable error handling, this now allows you to |
| 159 | +modify the style of API error messages. |
| 160 | + |
| 161 | +As an example, this allows for the following style of error responses: |
| 162 | + |
| 163 | + { |
| 164 | + "message": "You do not have permission to perform this action.", |
| 165 | + "code": "permission_denied" |
| 166 | + } |
| 167 | + |
| 168 | +This is particularly useful with validation errors, which use appropriate |
| 169 | +codes to identify differing kinds of failure... |
| 170 | + |
| 171 | + { |
| 172 | + "name": {"message": "This field is required.", "code": "required"}, |
| 173 | + "age": {"message": "A valid integer is required.", "code": "invalid"} |
| 174 | + } |
| 175 | + |
| 176 | +## Client upload & download support |
| 177 | + |
| 178 | +The Python `coreapi` client library and the Core API command line tool both |
| 179 | +now fully support file [uploads][uploads] and [downloads][downloads]. |
| 180 | + |
| 181 | +--- |
| 182 | + |
| 183 | +## Deprecations |
| 184 | + |
| 185 | +### Generating schemas from Router |
| 186 | + |
| 187 | +The router arguments for generating a schema view, such as `schema_title`, |
| 188 | +are now pending deprecation. |
| 189 | + |
| 190 | +Instead of using `DefaultRouter(schema_title='Example API')`, you should use |
| 191 | +the `get_schema_view()` function, and include the view in your URL conf. |
| 192 | + |
| 193 | +Make sure to include the view before your router urls. For example: |
| 194 | + |
| 195 | + from rest_framework.schemas import get_schema_view |
| 196 | + from my_project.routers import router |
| 197 | + |
| 198 | + schema_view = get_schema_view(title='Example API') |
| 199 | + |
| 200 | + urlpatterns = [ |
| 201 | + url('^$', schema_view), |
| 202 | + url(r'^', include(router.urls)), |
| 203 | + ] |
| 204 | + |
| 205 | +### Schema path representations |
| 206 | + |
| 207 | +The `'pk'` identifier in schema paths is now mapped onto the actually model field |
| 208 | +name by default. This will typically be `'id'`. |
| 209 | + |
| 210 | +This gives a better external representation for schemas, with less implementation |
| 211 | +detail being exposed. It also reflects the behaviour of using a ModelSerializer |
| 212 | +class with `fields = '__all__'`. |
| 213 | + |
| 214 | +You can revert to the previous behaviour by setting `'SCHEMA_COERCE_PATH_PK': False` |
| 215 | +in the REST framework settings. |
| 216 | + |
| 217 | +### Schema action name representations |
| 218 | + |
| 219 | +The internal `retrieve()` and `destroy()` method names are now coerced to an |
| 220 | +external representation of `read` and `delete`. |
| 221 | + |
| 222 | +You can revert to the previous behaviour by setting `'SCHEMA_COERCE_METHOD_NAMES': {}` |
| 223 | +in the REST framework settings. |
| 224 | + |
| 225 | +### DjangoFilterBackend |
| 226 | + |
| 227 | +The functionality of the built-in `DjangoFilterBackend` is now completely |
| 228 | +included by the `django-filter` package. |
| 229 | + |
| 230 | +You should change your imports and REST framework filter settings as follows: |
| 231 | + |
| 232 | +* `rest_framework.filters.DjangoFilterBackend` becomes `django_filters.rest_framework.DjangoFilterBackend`. |
| 233 | +* `rest_framework.filters.FilterSet` becomes `django_filters.rest_framework.FilterSet`. |
| 234 | + |
| 235 | +The existing imports will continue to work but are now pending deprecation. |
| 236 | + |
| 237 | +### CoreJSON media type |
| 238 | + |
| 239 | +The media type for `CoreJSON` is now `application/json+coreapi`, rather than |
| 240 | +the previous `application/vnd.json+coreapi`. This brings it more into line with |
| 241 | +other custom media types, such as those used by Swagger and RAML. |
| 242 | + |
| 243 | +The clients currently accept either media type. The old style-media type will |
| 244 | +be deprecated at a later date. |
| 245 | + |
| 246 | +### ModelSerializer 'fields' and 'exclude' |
| 247 | + |
| 248 | +ModelSerializer and HyperlinkedModelSerializer must include either a fields |
| 249 | +option, or an exclude option. The fields = '__all__' shortcut may be used to |
| 250 | +explicitly include all fields. |
| 251 | + |
| 252 | +Failing to set either `fields` or `exclude` raised a pending deprecation warning |
| 253 | +in version 3.3 and raised a deprecation warning in 3.4. Its usage is now mandatory. |
| 254 | + |
| 255 | +--- |
| 256 | + |
| 257 | +[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors |
| 258 | +[funding]: funding.md |
| 259 | +[uploads]: http://core-api.github.io/python-client/api-guide/utils/#file |
| 260 | +[downloads]: http://core-api.github.io/python-client/api-guide/codecs/#downloadcodec |
| 261 | +[schema-generation-api]: ../api-guide/schemas/#schemagenerator |
| 262 | +[schema-docs]: ../api-guide/schemas/#schemas-as-documentation |
| 263 | +[schema-view]: ../api-guide/schemas/#the-get_schema_view-shortcut |
| 264 | +[django-rest-raml]: https://github.com/tomchristie/django-rest-raml |
| 265 | +[raml-image]: ../img/raml.png |
| 266 | +[raml-codec]: https://github.com/core-api/python-raml-codec |
0 commit comments