Compare commits

..

1170 Commits

Author SHA1 Message Date
Ali Hassan
2ae8c117da
Add note to tutorial about required request in serializer context when using HyperlinkedModelSerializer (#9732)
* Fix : Updated documentation in tutorial 5 leading to error

* Updated docs/tutorial/5-relationships-and-hyperlinked-apis.md

Co-authored-by: Bruno Alla <browniebroke@users.noreply.github.com>

* Missing newline

---------

Co-authored-by: Bruno Alla <browniebroke@users.noreply.github.com>
2025-07-07 13:11:24 +02:00
Ryan
70e54f45ad
Revert docs back to djangorestframework-guardian (#9734) 2025-07-06 15:39:52 +01:00
Peter Thomassen
3038494705
Document that unique constraints cause required=True in ModelSerializer (#9725) 2025-06-26 18:39:51 +01:00
Dulat Kushibayev
4bb46c2949
Add Kazakh(kk) locale support (#9713)
* Add Kazakh(kk) locale support

* Header comment update

* Refined a translation for improved contextual accuracy
2025-06-25 08:30:54 +01:00
Konstantin Alekseev
e454758fb6
Fix regression in unique_together validation with SerializerMethodField (#9712) 2025-06-10 12:47:28 +01:00
Federico Bond
33d59fefaa
Update Spanish translations (#9701) 2025-05-25 11:07:43 +01:00
Rohit
c0202a0aa5
Update Django documentation links to use stable version (#9698)
Co-authored-by: Bruno Alla <browniebroke@users.noreply.github.com>
2025-05-13 15:10:21 +01:00
Rohit
985dd732e0
Fix broken Heroku JSON Schema link in schemas.md (#9693)
Replaced the outdated Heroku JSON Schema reference URL, which was returning a 404 error, with the updated working link from the official Heroku blog.
2025-05-01 13:44:34 +01:00
Tom Christie
78e97074e7
Drop HTML line breaks on long headers in browsable API (#9438)
* Drop HTML line breaks on long headers

* Remove related test

* Fix flake8

---------

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
Co-authored-by: Bruno Alla <alla.brunoo@gmail.com>
2025-04-28 04:08:48 +00:00
rezatn0934
376026ce35
Update persian translations (#9576) 2025-04-26 15:58:29 +01:00
Salman Saeed Albukhaitan
d375154d18
Update Arabic translations (#9595) 2025-04-26 15:42:44 +01:00
Josh Thomas
543996711d
Fix UniqueTogetherValidator to handle fields w/ source attr (#9688)
* Add failing test for `UniqueConstraint` validation with `source` attribute

* Fix `UniqueTogetherValidator` to handle fields with source attribute

* split inner sources logic out to tuple comprehension
2025-04-23 09:03:14 +00:00
Carlton Gibson
07d3e1ec8f
Updated funding page to represent current scope. (#9686) 2025-04-10 12:05:06 +02:00
Ülgen Sarıkavak
ea1da76196
Add pyupgrade to pre-commit hooks (#9682) 2025-04-09 06:24:18 +00:00
Yousef Abu Shanab
2fbfaae507
Add drf-restwind and update outdated images in browsable-api.md (#9680)
* add drf-restwind

* Add images of 3rd party customization packages
2025-04-08 08:32:04 +00:00
Bruno Alla
3c755794df
Cleanup dependencies and conditions for unsupported Python versions (#9681)
* Remove optional install backports.zoneinfo for unsupported Python versions and associated code

* Remove conditions in tests for unsupported Python versions

* Remove condition for unsupported Python versions
2025-04-08 08:29:40 +00:00
ren000thomas
c41314f1fc
Update Chinese translations (#9675) 2025-04-05 11:02:59 +01:00
JAEGYUN JUNG
5c21fa757c
Update test matrix to use Django 5.2 stable version (#9679) 2025-04-04 11:39:11 +01:00
Stefan
141ab8e585
Add missing & fix German translations (#9676) 2025-04-04 09:24:28 +01:00
JAEGYUN JUNG
3ba8ef967e
Update GitHub Actions to use Ubuntu 22.04 for testing (#9677) 2025-04-02 18:35:29 +01:00
JAEGYUN JUNG
9b1e8d2d43
Add missing & fix Korean translations (#9571)
* update django.po file

* update django.po translators

* Changed the translation for the word “User” from “유저” to “사용자” to make it consistent with Django's translation

reference: 5a91ad3d71/django/contrib/admin/locale/ko/LC_MESSAGES/django.po (L601)

* Add missing translation for the word “Token"

* Fix wrong translation for word "Created"

* Fix translation for "Tokens", just like django translation.

reference: 5a91ad3d71/django/contrib/auth/locale/ko/LC_MESSAGES/django.po (L235)

* Add missing translation for "Invalid Input"

* Add missing translation for throttling messages

* Add missing translation for CharField, BooleanField messages

* fix: remove unnecessary space

* Feat: add missing translation for SlugField error message

* Feat: add missing translation for UUIDField error message

* Fix: add (boolean) for booleanField message

* Feat: add missing translation for `integer to float` error message

* Feat: add & fix translation for DecimalField

* Feat: add & fix translation for DateTimeField

* Feat: add & fix translation for DurationField

* Feat: add & fix translation for Selection&FilePathField

* Feat: add & fix translation for DictField

* Feat: add missing translation for filters

* Feat: add missing translations for template

* Feat: Change end punctuation to the “~세요.” used by Django translations

* update django.po translators

* Feat: add compiled message file

* Update rest_framework/locale/ko_KR/LC_MESSAGES/django.po

Co-authored-by: taezero <51291185+overtae@users.noreply.github.com>

* Update rest_framework/locale/ko_KR/LC_MESSAGES/django.po

Co-authored-by: taezero <51291185+overtae@users.noreply.github.com>

* Feat: remove unnecessary multliline from django.po(kor translation)

* Feat: remove unnecessary multliline from django.po(kor translation)

* Feat: update Korean translations for authentication messages

* Feat: Remove unnecessary English parenthesis descriptions

* Feat: Remove unnecessary English parenthesis descriptions

* Feat: Remove unnecessary English parenthesis descriptions

* Feat: Update compiled message file for ko_KR

---------

Co-authored-by: taezero <51291185+overtae@users.noreply.github.com>
2025-04-02 18:17:04 +01:00
Michiel W. Beijen
ffadde930e
Removed reference to GitHub Issues and Discussions (#9660) 2025-03-31 15:22:15 +01:00
Matheus Oliveira
6f274ab862
Fix some typos in pt_BR translations (#9673) 2025-03-31 10:43:53 +01:00
Bruno Alla
ac50cec76c
Prepare v3.16, release notes, and announcement. (#9671)
* Start drafting release notes from 3.16 (Generated from GitHub)
* Reformat changes and split into sections
* Format GitHub PRs links for the docs
* Link new contributors in Markdown format
* Write up 3.16 announcement
* Bump version
* Add entry for removed Python 3.8 support
* Update release date to 28/03

* Minor rewording

* Add 3.16 announcement to the navbar and link to docs
2025-03-28 15:16:33 +01:00
Carlton Gibson
e96b8e49cd
Drop Python 3.8 as EOL (#9670)
Thanks to Bruno Alla for review.

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2025-03-28 13:56:54 +01:00
Paul FLORENCE
32dbd3525d
Add django-pyoidc as a third party authentication library (#9667) 2025-03-25 20:09:42 +00:00
Mike Manger
73cbb9cd4a
Fix typos (#9662)
* Fix typo of 'related' in tests

* Fix typo of permission_classes in coreapi test

* Fix some minor typos in docs

* Fix typos in tests

* Fix flake8 issue
2025-03-08 15:53:15 +06:00
Mike Manger
1e8ac7c23b
Update usage of open in setup.py (#9661) 2025-03-06 13:30:27 +00:00
Asif Saif Uddin
0e1c7d3613
Update django 5.2b1 (#9657) 2025-02-27 11:27:32 +00:00
Mojtaba A
fc98d3598d
Update relations.md (#9063)
add rest-framework-gm2m-relations package that provides read/write serialization for generic many to many field
2025-02-26 06:11:09 +00:00
Konstantin Alekseev
17e95604f5
Fix unique together validator doesn't respect condition's fields (#9360) 2025-02-17 14:01:32 +06:00
Asif Saif Uddin
f30c0e2eed
add django 5.2a1 initial support (#9634)
* add django 5.2a1 for initial testing

* declare django 5.2 support

* change in docs
2025-02-14 14:49:56 +06:00
Bruno Alla
28d0261afc
Add missing ignore_outcome=true for the Python 3.13 - Django main combination (#9637) 2025-02-01 12:24:43 +06:00
decadenza
8637b3d624
Improved description of allowed throttling rates (#9640) 2025-01-30 10:03:11 +00:00
Bruno Alla
038670a4cf
Drop deprecated AutoSchema._get_reference method (#9525)
As well the unused RemovedInDRF316Warning
2025-01-29 12:27:33 +06:00
exg1o
f8dbea1a45
Add note in 'Introspecting ViewSet actions' docs section (#9633)
* Fix `Introspecting ViewSet actions` docs section

* Update docs/api-guide/viewsets.md

---------

Co-authored-by: Bruno Alla <browniebroke@users.noreply.github.com>
2025-01-29 11:51:38 +06:00
Bruno Alla
e1c070aacc
Switch to codecov GHA (#9618)
Fix #7908
2025-01-29 11:50:08 +06:00
Tom Christie
78e0b84ac9
Update SECURITY.md (#9628)
* Update security contact
2025-01-21 15:00:02 +00:00
Deepak Angadi
b483179b93
Update strftime formats link in the documentation (#9624) 2025-01-17 12:32:29 +00:00
Oliver Sauder
4a1d773b8f
Fixed regression that tests using format still work (#9615)
* Fixed regression that tests using format still work

Error only occurred on tests which return no content and use
a renderer without charset (e.g. JSONRenderer)

* Fixed linting

* Used early return as before

* Move ret str check back to where it was
2025-01-11 00:56:36 +06:00
Julius Lange
a4f6059d50
Fix typo in renderers documentation (#9616)
It's called lUAlatex and not lAUlatex.
2025-01-07 19:19:39 +00:00
Terence Honles
089f6a6974
support django 2.1 test client json data automatically serialized (#6511) 2024-12-28 16:22:21 +06:00
Bruno Alla
a8595a8eae
Fix raising on nullable fields part of UniqueConstraint (#9531)
* Add test to reproduce problem with nullable fields part of a unique constraint

Ref #9378

* Simplify test case and add similar case for unique_together

* Add test for unique together in a better place

* Default nullable fields to null in unique constraints checks

* Remove redundant test and move other to more appropriate place
2024-12-14 15:08:22 +06:00
amansharma612
dbac145638
Removed extra <> in validators example (#9590)
Co-authored-by: Aman Sharma <210100011@iitb.ac.in>
2024-11-18 17:43:53 +06:00
Will Vincent
b31413d46d
Tutorial updates (#9589)
* update Django for APIs book cover

* remove retired course from Treehouse

* add DCUS2018 talk, update links from wsvincent.com tutorials to learndjango.com
2024-11-12 06:58:56 +01:00
chee hong
9016efe3fc
Fix docs typo in Serializers Validators (#9563) 2024-10-23 20:09:36 +06:00
Gabriel
d3dd45b3f4
Update 1-serialization.md (#9543)
Making explicit the http GET method of the httpie calls.
For some reason it is sending a POST instead of a GET request as it should be described here:
https://httpie.io/docs/cli/optional-get-and-post

Note:
I was following the docs and testing it within the Git Bash windows console app for making the requests and debugging the DRF projenct in pycharm.
2024-10-10 04:41:39 +06:00
Oliver Sauder
10b25e7d63
Use final version of Python 3.13 (#9556)
Final version of Python 3.13 has been released and is now also available on GitHub actions.
2024-10-10 04:39:36 +06:00
Gabriel Mitelman Tkacz
81613c0e51
Fixing and adding pt-br translations (#9535) 2024-09-20 11:34:37 +01:00
Peter Thomassen
9921c7554f
Fix Transifex link (#9541) 2024-09-19 14:11:31 +02:00
Bruno Alla
b25028ac8f
Add support for Python 3.13 (#9527)
* Add support for Python 3.13

* Fix extracting tox env with -dev Python versions

* Fix view description inspection in Python 3.13

Python 3.13 introduced docstrings for None: https://github.com/python/cpython/pull/117813

In Python 3.12, this is an empty string:

```
 ➜ python3.12
Python 3.12.6 (main, Sep 10 2024, 19:06:17) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> d = None
>>> d.__doc__
>>>
```

In Python 3.13, it's no longer empty:

```
 ➜ python3.13
Python 3.13.0rc2+ (heads/3.13:660baa1, Sep 10 2024, 18:57:50) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> d = None
>>> d.__doc__
'The type of the None singleton.'
>>>
```

Adding a check in the inspector that get the view description out the view function docstring to catch this edge case.
2024-09-11 15:39:52 +06:00
Bruno Alla
a59aa2dfe1
Add test covering Update view without queryset attribute (#9528) 2024-09-11 15:37:33 +06:00
Bruno Alla
61e33761eb
Docs: move path converter into a separate section (#9524)
And remove note regarding only working with Django 2.x or above, as it's been a while the feature is present, and DRF only supports Django 4.2+.

I was looking for this but couldn't see it in the docs, having it in a separate section would make it easier to find and link to.

Moreover, as it stands, one might think that the feature is limited to SimpleRouter, while it's also available for DefaultRouter.
2024-09-10 17:29:31 +06:00
Sina Amini
7141bdb2df
Spelling mistakes in Farsi language were corrected (#9521) 2024-09-07 17:30:13 +06:00
Bruno Alla
2ede857de0
Add official support for Django 5.1 (#9514)
* Add official support for Django 5.1

Following the supported Python versions:

https://docs.djangoproject.com/en/stable/faq/install/

* Add tests to cover compat with Django's 5.1 LoginRequiredMiddleware

* First pass to create DRF's LoginRequiredMiddleware

* Attempt to fix the tests

* Revert custom middleware implementation

* Disable LoginRequiredMiddleware on DRF views

* Document how to integrate DRF with LoginRequiredMiddleware

* Move login required tests under a separate test case

* Revert redundant change

* Disable LoginRequiredMiddleware on ViewSets

* Add some integrations tests to cover various view types
2024-09-07 17:21:18 +06:00
Bruno Alla
125ad42eb3
Accept integers as min/max values of DecimalField (#9515)
* Use Decimal for min/max values of DecimalField in tests

* Update docs to mention that min/max values should be Decimal objects

* Accept integer values for DecimalField min and max values

* Update expected error messages in tests

* Update expected warning message in tests
2024-09-07 17:07:28 +06:00
rafaelgramoschi
f593f5752c
Update browsable-api.md (#9509)
* Update browsable-api.md

Deprecated url(), use re_path(). Show imports.

* Update docs/topics/browsable-api.md

* Update docs/topics/browsable-api.md

---------

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2024-08-27 13:44:04 +06:00
Noam
5cc1028c2f
Fix "Converter is already registered" deprecation warning. (#9512) 2024-08-26 17:32:50 +02:00
akkuman
f6ea019bd9
Update django.po (#9505) 2024-08-26 10:31:07 +01:00
Pedro Schlickmann Mendes
2f28e7086d
Update jobs.md (#9480) 2024-08-26 10:28:15 +01:00
Dave Kalu
f113ab6b68
Update tutorials-and-resources.md (#9479)
Included the remaining parts (part 3 and 4) of Andrea Grandi's tutorial on creating production ready APIs with DRF.
2024-08-05 14:26:41 +01:00
Yuekui
518eb22e67
Fix unique_together validation with source (#9482) 2024-08-05 16:36:50 +06:00
James McHugh
8e304e1adb
Fixed AttributeError raised by data property being silently ignored (#9455)
Signed-off-by: James Riley McHugh <mchugh_james@bah.com>
Co-authored-by: James Riley McHugh <mchugh_james@bah.com>
2024-07-17 22:51:39 +06:00
Andrea Grandi
b6ea11028f
Update tutorials-and-resources.md (#9476) 2024-07-17 22:50:09 +06:00
Devid
f74185b6dd
Fix get_template_context to handle also lists (#9467) 2024-07-15 22:03:40 +06:00
Tom Christie
ccfe0a9637
Add Zuplo to sponsors (#9460) 2024-07-05 16:56:58 +01:00
Alvaro Vega
e9f3fd250a
Update release-notes.md (#9451) 2024-06-29 13:48:31 +06:00
Francesco Cataldo
4d0662663a
fix(release-notes): fix wronk link PR(#9435) on release-notes 3.15.2 (#9444)
Co-authored-by: Francesco <francesco.cataldo@spinforward.it>
2024-06-27 13:19:59 +01:00
Martijn Jacobs
7297f19701
Add adrf as a third party package for Django REST framework (#9198) 2024-06-24 10:31:49 +01:00
Devid
e13688f0c0
Remove long deprecated code from request wrapper (#9441) 2024-06-19 00:03:37 +06:00
Ivan Studinsky
1e9b5c15ec
Provide tests for hashing of OperandHolder (#9437) 2024-06-15 14:00:28 +06:00
Tom Christie
c7a7eae551
Version 3.15.2 (#9439) 2024-06-14 16:34:21 +01:00
Seokchan Yoon
3b41f01241
Fix potential XSS vulnerability in break_long_headers template filter (#9435)
The header input is now properly escaped before splitting and joining with <br> tags. This prevents potential XSS attacks if the header contains unsanitized user input.
2024-06-14 10:52:02 +01:00
Ivan Studinsky
fe92f0dd0d
Add __hash__ method for permissions.OperandHolder class (#9417)
`OperandHolder` is not hashable, so need to add `__hash__` method
2024-06-10 12:19:06 +06:00
wkwkhautbois
fbdab09c77
docs: Correct some evaluation results and a httpie option in Tutorial1 (#9421)
* Tutorial 1: Added --unsorted option to httpie calls to prevent automatic json key sorting

* Tutorial 1: Changed evaluation results accurate
2024-06-02 10:14:37 +06:00
Stanislav Levin
36d5c0e74f
tests: Check urlpatterns after cleanups (#9400)
According to docs:
https://docs.python.org/3/library/unittest.html#unittest.TestCase.addClassCleanup

> Add a function to be called after tearDownClass() to cleanup resources
  used during the test class. Functions will be called in reverse order to
  the order they are added (LIFO).

This was revealed with recent change in pytest (`8.2.0`):
> pytest-dev/pytest#11728: For unittest-based tests, exceptions during
  class cleanup (as raised by functions registered with
  TestCase.addClassCleanup) are now reported instead of silently failing.

`check_urlpatterns` is called before `cleanup_url_patterns` and fails
(problem was hidden by `pytest < 8.2.0`).

`doClassCleanups` can be used instead to check after-cleanup state:

https://docs.python.org/3/library/unittest.html#unittest.TestCase.doClassCleanups

> This method is called unconditionally after tearDownClass(), or after
  setUpClass() if setUpClass() raises an exception.

  It is responsible for calling all the cleanup functions added by
  addClassCleanup(). If you need cleanup functions to be called prior to
  tearDownClass() then you can call doClassCleanups() yourself.

Fixes: https://github.com/encode/django-rest-framework/issues/9399

Signed-off-by: Stanislav Levin <slev@altlinux.org>
2024-05-07 13:05:03 +06:00
Peter Thomassen
9d4ed054bf
Don't use Windows line endings 2024-04-30 18:28:27 +02:00
Peter Thomassen
b34bde47d7
Fix typo in setup.cfg setting 2024-04-30 18:28:26 +02:00
Peter Thomassen
ab681f2d5e
Update requirements in docs 2024-04-30 18:28:25 +02:00
Peter Thomassen
22377241a8
bump pygments (security hygiene)
Addresses https://github.com/encode/django-rest-framework/security/dependabot/9
2024-04-30 18:28:24 +02:00
Peter Thomassen
d58b8da591
Update deprecation hints 2024-04-30 18:28:23 +02:00
Peter Thomassen
d38aab39e4
Remove unused code 2024-04-30 18:28:22 +02:00
Peter Thomassen
82d91a85ff
Fix tox config 2024-04-30 18:28:21 +02:00
Peter Thomassen
1f2daaf53c
Drop support for Django < 4.2 and Python < 3.8
Discussion: https://github.com/encode/django-rest-framework/discussions/8814#discussioncomment-9237791
2024-04-30 18:28:19 +02:00
Peter Thomassen
91bbac1f67
bump mkdocs, no longer need to pin jinja2
Addresses https://github.com/encode/django-rest-framework/security/dependabot/11
2024-04-30 18:28:04 +02:00
Peter Thomassen
7900778fbe
Remove obsolete sentence from docs 2024-04-30 18:24:23 +02:00
Peter Thomassen
861b7ac42b
Adapt issue/PR template to better reflect contribution policy 2024-04-30 18:24:22 +02:00
Peter Thomassen
52bfe20dec
Adapt docs to reflect stability-focused contribution policy 2024-04-30 18:24:21 +02:00
Peter Thomassen
f642d85be2
Fix docs typo 2024-04-30 18:24:20 +02:00
Peter Thomassen
430de731e7
Clean up project management docs 2024-04-30 18:24:19 +02:00
Terence Honles
e596f43c4e
use warnings rather than logging a warning for DecimalField warnings (#9367) 2024-04-27 17:15:06 +06:00
Max Muoto
7f18ec1b53
Revert "Ensure CursorPagination respects nulls in the ordering field (#8912)" (#9381)
This reverts commit b1cec517ff.
2024-04-27 17:07:05 +06:00
Tom Christie
f96c065607
Update README.md (#9375)
Drop unnecessary self-serving promo text. (blergh) 😅
2024-04-27 16:58:44 +06:00
Jakub Szaredko
97c5617edc
Docs: Add Python 3.12 to the requirements (#9382) 2024-04-27 16:57:48 +06:00
Christian Bläul
f4daa98f48
Remove an unnecessary step from quickstart.md (#9387)
Since django is a dependency of djangorestframework, we don’t need to install it manually.
2024-04-26 13:18:16 +01:00
JAEGYUN JUNG
9864c47018
Removing live examples of tutorial code that are no longer hosted (#9363)
* docs: Removing live examples of tutorial code that are no longer hosted

* docs: Remove all references to tutorial links
2024-04-08 13:26:02 +02:00
Marcelo Galigniana
63063da082
Update renderers documentation example (#9362) 2024-04-04 10:12:19 +03:00
John-Anthony G. Thevos
085b7e166b
Apply black formatting to caching markdown (#9341)
It _looks_ like blacken-docs is failing on this file.
Running black locally fails with a failed to reformat.
This is because it expects python code, and  when it
hits the ">", there's invalid python.
2024-03-27 10:39:49 +00:00
John-Anthony G. Thevos
f4194c4684
Update docstring (#9340) 2024-03-22 19:37:20 +00:00
Bradley Wells
6df509863d
Add @api_view example to caching documentation (#9131) 2024-03-22 18:33:00 +00:00
Tom Christie
328591693d
Version 3.15.1 (#9339)
* Version 3.15.1
2024-03-22 11:47:50 +00:00
Tom Christie
eb361d289d
SearchFilter.get_search_terms returns list. (#9338) 2024-03-22 10:52:43 +00:00
Asif Saif Uddin
400b4c5441
Revert "Fix NamespaceVersioning ignoring DEFAULT_VERSION on non-None namespac…" (#9335)
This reverts commit 71f87a5864.
2024-03-22 09:39:30 +00:00
Tom Christie
4ef3aaf0ad
Revert #9030 (#9333)
* Revert #9030

* Fix test case
2024-03-22 09:40:34 +01:00
Tom Christie
4f10c4e43e
Revert "Fix Respect can_read_model permission in DjangoModelPermissions (#8…" (#9332)
This reverts commit 0618fa88e1.
2024-03-21 22:45:12 +00:00
Tom Christie
a4d58077a0
Revert "feat: Add some changes to ValidationError to support django style vad…" (#9330)
This reverts commit 4abfa28e08.
2024-03-21 22:26:50 +00:00
Asif Saif Uddin
da78a147f2
Revert "Re-prefetch related objects after updating (#8043)" (#9327)
This reverts commit 2b34aa4291.
2024-03-21 22:23:30 +00:00
Asif Saif Uddin
0e4ed81627
Revert "feat: Add some changes to ValidationError to support django style vad…" (#9326)
This reverts commit 4abfa28e08.

Co-authored-by: Tom Christie <tom@tomchristie.com>
2024-03-21 17:09:43 +01:00
Aristotelis Mikropoulos
56a5b354d0
Add drf-sendables to third-party-packages.md (#9261) 2024-03-21 14:10:10 +00:00
Alex Laird
d7c8dcfc7e
Revert PR that adds autocomplete_fields to TokenAdmin, as this break some use cases. (#9301) 2024-03-21 12:46:06 +00:00
Bruno Alla
77ef27f18f
Fix broken links in release notes for 3.15 (#9305)
* Fix broken links in release notes for 3.15

A few links aren't rendered properly in the docs, seems to be due to extra spaces.

* Remove duplicate mention of PR number
2024-03-19 08:24:55 +01:00
Bruno Alla
2f66c294e3
Make inflection package truly optional (#9303)
* Make inflection package truly optional

Fix #9291

* Make inflection compat layer consistent with the others

Co-authored-by: T. Franzel <13507857+tfranzel@users.noreply.github.com>

---------

Co-authored-by: T. Franzel <13507857+tfranzel@users.noreply.github.com>
2024-03-18 23:29:02 +01:00
Nguyễn Anh Bình
337ba211e8
- Update the message to be consistent with the Django HttpResponseBase class. (#9287) 2024-03-17 14:22:03 +01:00
Tom Christie
2d8e9ad819
3.15 Release (#9210)
* Release Notes for 3.15

- Add docs/community/3.15-announcement.md
- Update docs/community/release-notes.md
- Update mkdocs.yml

Co-authored-by: Bruno Alla <browniebroke@users.noreply.github.com>

* Release date pending

bump

* Changes to docs should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to docs should not be included in release notes.

* Fix typo

* Changes to tests should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to tests should not be included in release notes.

* Changes to tests should not be included in release notes.

* Fix typo in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to tests should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Improve changelog entry

* Changes to docs should not be included in release notes.

* Changes to docs should not be included in release notes.

* Changes to project workflow should not be included in release notes.

* Changes to docs should not be included in release notes.

* Update docs/community/3.15-announcement.md

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>

* Update docs/community/3.15-announcement.md

* Update docs/community/3.15-announcement.md

* Update docs/community/release-notes.md

* Update docs/community/release-notes.md

Co-authored-by: Christian Clauss <cclauss@me.com>

* Update docs/community/release-notes.md

Co-authored-by: Christian Clauss <cclauss@me.com>

* Update docs/community/3.15-announcement.md

Co-authored-by: JAEGYUN JUNG <twicegoddessana1229@gmail.com>

* Update docs/community/release-notes.md

* Update docs/community/release-notes.md

Co-authored-by: JAEGYUN JUNG <twicegoddessana1229@gmail.com>

* Update release version

* Update supported Python and Django versions

---------

Co-authored-by: Rodrigo <rodrigo@crowdbotics.com>
Co-authored-by: Bruno Alla <browniebroke@users.noreply.github.com>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
Co-authored-by: Christian Clauss <cclauss@me.com>
Co-authored-by: JAEGYUN JUNG <twicegoddessana1229@gmail.com>
2024-03-16 17:21:02 +00:00
Asif Saif Uddin
a677b09729
Revert "Fix validation for ListSerializer (#8979)" (#9283)
This reverts commit e2a4559c03.
2024-03-13 15:15:43 +00:00
TAKAHASHI Shuuji
09a0c551ca
Revert "Register Django urls (#8778)" (#9254)
This reverts commit 3bf611787a.
2024-03-10 12:50:53 +01:00
JAEGYUN JUNG
730d216794
fix: Remove the _delegate_text attribute, which is being removed in django 5.0 (#9278) 2024-03-08 13:14:27 +00:00
şuayip üzülmez
a2eabfc867
Improve integration with Django Debug Toolbar (#9213) 2024-03-07 10:58:59 +01:00
dependabot[bot]
4c7c693f15
Bump the github-actions group with 1 update (#9272)
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 3 to 4
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-06 16:06:24 +01:00
Christian Clauss
b7cccff943
Keep GitHub Actions up to date with GitHub's Dependabot (#9237)
* https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
* https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
2024-03-06 15:41:19 +01:00
Christian Clauss
6cbd4b7789
GitHub Actions: Upgrade pre-commit and drop the removed token (#9267)
* https://github.com/pre-commit/action/releases
* https://github.com/actions/checkout/releases
* https://github.com/actions/setup-python/releases

https://github.com/pre-commit/action#using-this-action-in-private-repositories explains why `token` was removed but is a bit difficult to understand.

Moving to running pre-commit on https://pre-commit.ci has proved to be the best solution on other projects.
2024-03-06 14:27:46 +01:00
Yaroslav Halchenko
fb03dd977e
Add codespell: config + workflow to detect new typos. Get some typos fixed (#9234)
* Do not ignore .codespellrc from git

* Add rudimentary codespell config

* Add pre-commit definition for codespell

* more custom skips for codespell - long lines, lines with ú etc

* [DATALAD RUNCMD] Do interactive fixing of some ambigous typos

=== Do not change lines below ===
{
 "chain": [],
 "cmd": "codespell -w -i 3 -C 2 ./docs/community/release-notes.md",
 "exit": 0,
 "extra_inputs": [],
 "inputs": [],
 "outputs": [],
 "pwd": "."
}
^^^ Do not change lines above ^^^

* BF: pre-commit needs to duplicate some of the skips for codespell

Known issue -- yet to be addressed:

https://github.com/codespell-project/codespell/issues/3196

* Move codespell configuration into setup.cfg
2024-02-28 12:01:49 +01:00
KanchiMoe
3c9490be22
resolve deprecation warnings for setup-python (#9266) 2024-02-28 11:57:33 +01:00
Rodrigo
d4016d8ec1
Add Django 5.0 support (#9233)
* Update tox.ini

* Update tests for Django 5.0

* Update documentation

* Update setup.py
2024-02-28 11:52:22 +01:00
willeM_ Van Onsem
a45432b54d
refactor removing parameters from kwargs when creating a ListSerializer (#9245)
* refactor removing parameters from kwargs when creating a ListSerializer

* insert child

* small rewrite

---------

Co-authored-by: Willem Van Onsem <willem.vanonsem@prosafco.be>
2024-02-20 15:08:19 +01:00
Rodrigo
37ec04d518
Add Python 3.12 support (#9230)
* added python 3.12 to CI

* Update setup.py

---------

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2024-02-20 14:16:03 +01:00
Yousef Abu Shanab
4773d737b9
docs: Update third-party-packages.md to rename customization packages (#9248)
* Add 2 customization packages, rest-framework-redesign and rest-framework-material

* docs: Update third-party-packages.md to rename customization packages
2024-02-20 14:14:13 +01:00
Asif Saif Uddin
336e7addb6
added python 3.12 to CI (#9157)
* added python 3.12 to CI

* Update tox.ini

* Update tox.ini

* Update tox.ini
2024-02-20 14:12:07 +01:00
şuayip üzülmez
2ef77b1833
Use POST method instead of GET to perform logout in browsable API (#9208)
* Use POST method instead of GET to perform logout in browsable API

* Add a test that checks the presence of the logout form
2024-02-19 23:28:04 +01:00
Victorien
df89f32b88
Fix typo in 3.14 announcement (#9255) 2024-02-14 11:02:02 +00:00
iamkorniichuk
5ad467aa2c
Remove read_only deprecated behaviour from documentation (#9239) 2024-01-29 09:30:29 +01:00
Yuekui
41edb3b9dd
Avoid unnecessary unique together checking (#9154) 2024-01-26 11:36:18 +01:00
Marcelo Galigniana
2797c0f216
Add missing import in /api-guide/viewsets/ example (#9235) 2024-01-25 12:01:06 +01:00
Christian Clauss
ab694eccde
Fix typo (#9231) 2024-01-24 23:17:01 +01:00
Christian Clauss
74689b1f44
pre-commit autoupdate (#9232) 2024-01-24 22:47:46 +01:00
Kien Dang
f85d8cb81a
Fix comment syntax error in doc that fails pre-commit blacken-docs (#9225)
* Fix comment syntax in doc

* Pre-commit
2024-01-24 22:44:46 +01:00
Kien Dang
552a67acde
Skip coreapi tests in GenerateSchemaTests if coreapi is not installed (#9229) 2024-01-19 11:10:56 +01:00
Viicos
c4f9d432dd
Update 3.11-announcement.md (#9227) 2024-01-18 15:35:57 +01:00
Kien Dang
21bb21b65b
Fix use of ip_address_validators for Django 5.1+ (#9180)
* Fix use of ip_address_validators for Django 5.0+

* Change affected django version to 5.1
2024-01-11 13:34:46 +01:00
Code Apprentice
047bec1288
Add documentation to show how to add authentication for the browseable api (#9137) 2024-01-04 14:16:57 +00:00
Matt George
f4175b4b07
Update quickstart.md (#9185)
add .order_by() to eliminate Pagination UnorderedObjectListWarning
2024-01-04 13:10:53 +00:00
Yousef Abu Shanab
530baa23cd
Add 2 customization packages, rest-framework-redesign and rest-framework-material (#9088) 2024-01-04 12:42:54 +00:00
HGZahn
4c231d5b97
Clarifying the file to edit (#9189) 2024-01-04 12:36:49 +00:00
Asif Saif Uddin
0f39e0124d
Update requirements-optionals.txt (#9181)
* Update requirements-optionals.txt

* Update requirements-optionals.txt
2023-12-06 22:44:47 +06:00
Krishna2864
0abb84fa39
removed hyperlink for web browsable API on homepage (#9174) 2023-11-30 11:07:36 +00:00
Tom Christie
06022e788e
Update README.md 2023-11-29 14:15:53 +00:00
Tom Christie
15f619ade0
Add Svix to sponsors (#9173) 2023-11-29 14:13:36 +00:00
Asif Saif Uddin
1db19f4b2d
Update pytest version in requirements-testing.txt (#9158) 2023-11-05 11:59:10 +06:00
Asif Saif Uddin
f56b85b7dd
Update pygments>=2.12.0,<2.14.0 in requirements-optionals (#9142)
* Update pygments>=2.12.0,<2.16.1 in requirements-optionals

* Update requirements/requirements-optionals.txt

* Update requirements/requirements-optionals.txt

* Update requirements/requirements-optionals.txt
2023-10-17 16:13:10 +06:00
Asif Saif Uddin
2c59206b3e
Update requirements-documentation.txt (#9141) 2023-10-17 15:40:12 +06:00
J.V. Zammit
e794e5e5e4
blacken-docs (#8906)
* blacken-docs: Manual fixes for command to pass without errors

* blacken-docs: Adds blacken-docs step to precommit hook.

* blacken-docs: Adds changes made by command itself.

* blacken-docs: Modifies blacken-docs step to only process files under "docs" directory

* blacken-docs: Updates pre-commit config file to exclude all directories other than "docs" to be compatible with "--all-files" flag.

* blacken-docs: Adds commas at the end to make it look identical to pre-black version
2023-10-13 12:44:45 +01:00
Viicos
18b02ce00e
Add missing DEFAULT_VERSIONING_CLASS entry to API docs (#9126) 2023-10-08 13:30:10 +06:00
Marko
8da6b696ab
docs: update django requirement to 4.2 (#9128) 2023-10-07 14:55:25 +06:00
Michael Herman
d181511155
add courses section to community resources (#8845) 2023-10-05 10:06:07 +01:00
Terence Honles
4296189283
fix dist test by moving --no-pkgroot to runtests.py (#9129)
This change fixes the dist test by moving the --no-pkgroot option from
pytest to the runtests script.

The current "filterwarnings" setting for pytest includes rest_framework,
which causes an early import of the module. As a result the current
--no-pkgroot behavior fails with an assertion error. Trying to remove
the module from sys.modules will cause the warning filter to not apply,
so this change moves this code before pytest parses the config and loads
the "filterwarnings".
2023-10-05 12:33:53 +06:00
Viicos
d32346bae5
Fix type name of FieldInfo namedtuple (#9124)
* Fix type name of `FieldInfo` namedtuple

* Add test
2023-10-04 23:03:10 +06:00
Marcelo Galigniana
605cc4f736
Updated links to CSRF/AJAX Django documentation (#9118) 2023-09-29 15:06:16 +06:00
Asif Saif Uddin
4bbfa8d455
Updated Checkout action version & Ubuntu OS version (#9097)
* Updated Checkout action version & Ubuntu OS version

* Update .github/workflows/main.yml
2023-09-09 13:55:32 +06:00
Asif Saif Uddin
b6e3a22f7c
added jQuery 3.7.1 support & dropped previous version (#9094)
* added jQuery 3.7.1 support & dropped previous version

* added jQuery 3.7.1 support & dropped previous version
2023-09-09 13:51:05 +06:00
Daniel
5a01a4c8a9
Update CONTRIBUTING.md (#9095)
Removed apostrophe from "it's".
2023-08-31 14:19:25 +06:00
Harald Nezbeda
40eccb0d6c
Fixes documentation link test (#9076) 2023-08-17 16:21:03 +06:00
Devid
5c07060ce0
Use str as default path converter (#9066) 2023-08-16 20:11:50 +06:00
Ori Roza
9e05aa5962
Update third-party-packages.md (#9026)
added https://github.com/Ori-Roza/drf-api-action to third packages docs
2023-08-15 11:58:06 +06:00
Pavel Král
a47adbcd0f
Document support for http.HTTPMethod in the @action decorator added in Python 3.11. (#9067)
* Implement tests for HTTPMethod from Python 3.11

* Update documentation to mention HTTPMethod support in @action
2023-08-15 11:50:02 +06:00
Denis Surkov
2843b925f9
Add note for HiddenField behavior (#9055)
* Add note for HiddenField behavior

* Update docs/api-guide/fields.md

* Update docs/api-guide/validators.md

---------

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2023-08-15 11:20:05 +06:00
Harald Nezbeda
a2430a8cce
Add docs validation to release process (#6967)
* Add ci stage to test for broken links in documentation

* Add docs validation to release process

* Update .github/workflows/main.yml

* Update .github/workflows/main.yml

---------

Co-authored-by: Ryan P Kilby <kilbyr@gmail.com>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2023-08-15 11:17:08 +06:00
rexes-aka
6ebe6f2600
Update exceptions.md (#9071) 2023-08-15 10:56:42 +06:00
Denis Orehovsky
da9288878b
Partial serializer should not have required fields (#7563) 2023-08-13 10:36:19 +06:00
rizwanshaikh
7a9db57eaf
Propagate 'default' from model_field to serializer field. (#9030)
* Propagate 'default' from model_field to serializer field

Fix #7469.

Co-authored-by: Nikhil Benesch <nikhil.benesch@gmail.com>

* updated field default on serializer according to openapi generation and added that to options action response

* added notes regarding default value propagation from model to serializer field

* updated note

* Update docs/api-guide/fields.md

* Update docs/api-guide/fields.md

* Update docs/api-guide/fields.md

* Update docs/api-guide/fields.md

* Update docs/api-guide/fields.md

* Update docs/api-guide/fields.md

---------

Co-authored-by: John Parton <john.parton.iv@gmail.com>
Co-authored-by: Nikhil Benesch <nikhil.benesch@gmail.com>
Co-authored-by: Rizwan Shaikh <rshaikh@ces-ltd.com>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2023-08-07 12:35:54 +06:00
Pierre Chiquet
589b5dca9e
Allow to override child.run_validation call in ListSerializer (#8035)
* Separated run_child_validation method in ListSerializer

* fix typo

* Add test_update_allow_custom_child_validation

---------

Co-authored-by: Pierre Chiquet <pierre.chiquet@ubikey.fr>
2023-07-26 10:27:49 +06:00
Devid
b99df0cf78
Align SearchFilter behaviour to django.contrib.admin search (#9017)
* Use subquery to remove duplicates in SearchFilter

* Align SearchFilter behaviour to django.contrib.admin

* Add compatibility with older django/python versions

* Allow search to split also by comma after smart split

* Use generator to build search conditions to reduce iterations

* Improve search documentation

* Update docs/api-guide/filtering.md

---------

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2023-07-25 19:01:23 +06:00
Amin Aminian
5c3b6e496c
class name added to unkown field error (#9019) 2023-07-25 13:51:25 +06:00
Sergey Klyuykov
7658ffd71d
Fix: Pagination response schemas. (#9049) 2023-07-15 15:26:56 +06:00
Burson
66d86d0177
Fix choices in ChoiceField to support IntEnum (#8955)
Python support Enum in version 3.4, but changed __str__ to int.__str__ until version 3.11 to better support the replacement of existing constants use-case.
[https://docs.python.org/3/library/enum.html#enum.IntEnum](https://docs.python.org/3/library/enum.html#enum.IntEnum)

rest_frame work support Python 3.6+, this commit will support the Enum in choices of Field.
2023-07-13 18:50:49 +06:00
Andrew
4f7e9ed3bb
Fix SearchFilter renders field with invalid value (#9023)
Co-authored-by: Andrii Tarasenko <andrii.tarasenko@py-t.com>
2023-07-02 13:57:20 +06:00
Samiul Sk
8dd4250d02
remove unnecessary line which was causing isort error (#9014) 2023-06-21 11:05:44 +06:00
Samiul Sk
8b7e6f2e34
Update pre-commit.yml (#9012) 2023-06-20 17:43:33 +06:00
rizwanshaikh
9cfa4bd7cc
Fix OpenAPI Schema yaml rendering for timedelta (#9007)
* fix OpenAPIRenderer for timedelta

* added test for rendering openapi with timedelta

* fix OpenAPIRenderer for timedelta

* added test for rendering openapi with timedelta

* Removed usage of field.choices that triggered full table load (#8950)

Removed the `{{ field.choices|yesno:",disabled" }}` block because this triggers the loading of full database table worth of objects just to determine whether the multi-select widget should be set as disabled or not.

Since this "disabled" marking feature is not present in the normal select field, then I propose to remove it also from the multi-select.

* Added Deprecation Warnings for CoreAPI (#7519)

* Added Deprecation Warnings for CoreAPI

* Bumped removal to DRF315

* Update rest_framework/__init__.py

* Update rest_framework/filters.py

* Update rest_framework/filters.py

* Update tests/schemas/test_coreapi.py

* Update rest_framework/filters.py

* Update rest_framework/filters.py

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update setup.cfg

* Update rest_framework/pagination.py

---------

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>

* Update copy right timeline

* Fix NamespaceVersioning ignoring DEFAULT_VERSION on non-None namespaces (#7278)

* Fix the case where if the namespace is not None and there's no match,
  NamespaceVersioning always raises NotFound even if DEFAULT_VERSION
  is set or None is in ALLOWED_VERSIONS

* Add test cases

* fix OpenAPIRenderer for timedelta

* added test for rendering openapi with timedelta

* added testcase for rendering yaml with minvalidator for duration field (timedelta)

---------

Co-authored-by: Rizwan Shaikh <rshaikh@ces-ltd.com>
Co-authored-by: Lenno Nagel <lenno@namespace.ee>
Co-authored-by: David Smith <39445562+smithdc1@users.noreply.github.com>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
Co-authored-by: Konstantin Kuchkov <konstantin.kuchkov@gmail.com>
2023-06-17 09:18:25 +06:00
Konstantin Kuchkov
71f87a5864
Fix NamespaceVersioning ignoring DEFAULT_VERSION on non-None namespaces (#7278)
* Fix the case where if the namespace is not None and there's no match,
  NamespaceVersioning always raises NotFound even if DEFAULT_VERSION
  is set or None is in ALLOWED_VERSIONS

* Add test cases
2023-06-14 19:24:09 +06:00
Asif Saif Uddin
aed7761a8d
Update copy right timeline 2023-06-13 15:01:29 +06:00
David Smith
a16dbfd110
Added Deprecation Warnings for CoreAPI (#7519)
* Added Deprecation Warnings for CoreAPI

* Bumped removal to DRF315

* Update rest_framework/__init__.py

* Update rest_framework/filters.py

* Update rest_framework/filters.py

* Update tests/schemas/test_coreapi.py

* Update rest_framework/filters.py

* Update rest_framework/filters.py

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update rest_framework/pagination.py

* Update rest_framework/pagination.py

* Update rest_framework/pagination.py

* Update rest_framework/pagination.py

* Update rest_framework/schemas/coreapi.py

* Update rest_framework/schemas/coreapi.py

* Update rest_framework/schemas/coreapi.py

* Update rest_framework/schemas/coreapi.py

* Update rest_framework/schemas/coreapi.py

* Update tests/schemas/test_coreapi.py

* Update setup.cfg

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update tests/schemas/test_coreapi.py

* Update rest_framework/pagination.py

---------

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2023-06-13 12:55:22 +06:00
Lenno Nagel
833313496c
Removed usage of field.choices that triggered full table load (#8950)
Removed the `{{ field.choices|yesno:",disabled" }}` block because this triggers the loading of full database table worth of objects just to determine whether the multi-select widget should be set as disabled or not.

Since this "disabled" marking feature is not present in the normal select field, then I propose to remove it also from the multi-select.
2023-06-13 10:27:37 +06:00
Nancy Eckenthal
a180bde0fd
Permit mixed casing of string values for BooleanField validation (#8970)
* be more permissive of mixed casing in validating strings for BooleanField values

* undo unnecessary change

* lint
2023-06-12 21:21:18 +06:00
Niyaz
02d9bfc2dd
Fixes BrowsableAPIRenderer for usage with ListSerializer. (#7530)
Renders list of items in raw_data_form and does not renders form in
template while using with `ListSerializer` (`many=True`).
2023-06-12 19:28:28 +06:00
Mathieu Dupuy
376a5cbbba
remove dependency on pytz (#8984)
* remove pytz

* Revert "remove pytz"

This reverts commit 393609dfaa.

* remove pytz, more subtly
2023-06-04 11:24:07 +06:00
Alasdair Nicol
03e2ecc9a5
Add NullBooleanField deprecation to docs (#8999) 2023-06-02 06:29:11 +06:00
Vladimir Kasatkin
ff5f647df0
Fix example of requires_context attribute (#8952) 2023-05-31 10:36:21 +06:00
Saad Aleem
e2a4559c03
Fix validation for ListSerializer (#8979)
* fix: Make the instance variable of child serializer point to the correct list object instead of the entire list when validating ListSerializer

* fix formatting issues for list serializer validation fix

* fix imports sorting for list serializer tests

* remove django 2.2 from docs index (#8982)

* Declared Django 4.2 support in README.md (#8985)

* Fix Links in Documentation to Django `reverse` and `reverse_lazy` (#8986)

* Fix Django Docs url in reverse.md

Django URLs of the documentation of `reverse` and `reverse_lazy` were wrong.

* Update reverse.md

* fix URLPathVersioning reverse fallback (#7247)

* fix URLPathVersioning reverse fallback

* add test for URLPathVersioning reverse fallback

* Update tests/test_versioning.py

---------

Co-authored-by: Jorn van Wier <jorn.van.wier@thunderbyte.ai>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>

* Make set_value a method within `Serializer` (#8001)

* Make set_value a static method for Serializers

As an alternative to #7671, let the method be overridden if needed. As
the function is only used for serializers, it has a better place in the
Serializer class.

* Set `set_value` as an object (non-static) method

* Add tests for set_value()

These tests follow the examples given in the method.

* fix: Make the instance variable of child serializer point to the correct list object instead of the entire list when validating ListSerializer

* Make set_value a method within `Serializer` (#8001)

* Make set_value a static method for Serializers

As an alternative to #7671, let the method be overridden if needed. As
the function is only used for serializers, it has a better place in the
Serializer class.

* Set `set_value` as an object (non-static) method

* Add tests for set_value()

These tests follow the examples given in the method.

* fix: Make the instance variable of child serializer point to the correct list object instead of the entire list when validating ListSerializer

* fix: Make the instance variable of child serializer point to the correct list object instead of the entire list when validating ListSerializer

* fix formatting issues for list serializer validation fix

* fix: Make the instance variable of child serializer point to the correct list object instead of the entire list when validating ListSerializer

* fix formatting issues for list serializer validation fix

* fix linting

* Update rest_framework/serializers.py

Co-authored-by: Sergei Shishov <sshishov@users.noreply.github.com>

* Update rest_framework/serializers.py

Co-authored-by: Sergei Shishov <sshishov@users.noreply.github.com>

* fix: instance variable in list serializer, remove commented code

---------

Co-authored-by: Mathieu Dupuy <deronnax@gmail.com>
Co-authored-by: Mehraz Hossain Rumman <59512321+MehrazRumman@users.noreply.github.com>
Co-authored-by: Dominik Bruhn <dominik@dbruhn.de>
Co-authored-by: jornvanwier <mail@jornvanwier.com>
Co-authored-by: Jorn van Wier <jorn.van.wier@thunderbyte.ai>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
Co-authored-by: Étienne Beaulé <beauleetienne0@gmail.com>
Co-authored-by: Sergei Shishov <sshishov@users.noreply.github.com>
2023-05-29 20:03:11 +06:00
Étienne Beaulé
d252d22343
Make set_value a method within Serializer (#8001)
* Make set_value a static method for Serializers

As an alternative to #7671, let the method be overridden if needed. As
the function is only used for serializers, it has a better place in the
Serializer class.

* Set `set_value` as an object (non-static) method

* Add tests for set_value()

These tests follow the examples given in the method.
2023-05-24 19:59:42 +06:00
jornvanwier
a25aac7d67
fix URLPathVersioning reverse fallback (#7247)
* fix URLPathVersioning reverse fallback

* add test for URLPathVersioning reverse fallback

* Update tests/test_versioning.py

---------

Co-authored-by: Jorn van Wier <jorn.van.wier@thunderbyte.ai>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2023-05-18 09:46:40 +06:00
Dominik Bruhn
332e9560ab
Fix Links in Documentation to Django reverse and reverse_lazy (#8986)
* Fix Django Docs url in reverse.md

Django URLs of the documentation of `reverse` and `reverse_lazy` were wrong.

* Update reverse.md
2023-05-17 11:46:48 +06:00
Mehraz Hossain Rumman
7bebe97724
Declared Django 4.2 support in README.md (#8985) 2023-05-15 21:02:17 +06:00
Mathieu Dupuy
001d6ec2c9
remove django 2.2 from docs index (#8982) 2023-05-14 06:00:13 +06:00
Ismael Jiménez Sánchez
99e8b4033e
feat: enforce Decimal type in min_value and max_value arguments of DecimalField (#8972)
* add warning when min_value and max_value are not decimal

* remove redundant module name in log

---------

Co-authored-by: ismaeljs <>
2023-05-09 20:50:29 +06:00
Saad Aleem
e08e606c82
Fix mapping for choice values (#8968)
* fix mapping for choice values

* fix tests for ChoiceField IntegerChoices

* fix imports

* fix imports in tests

* Check for multiple choice enums

* fix formatting

* add tests for text choices class
2023-05-03 13:08:07 +06:00
Mahdi Rahimi
d14eb7555d
Refactor read function to use context manager for file handling (#8967)
Co-authored-by: Mahdi <mahdi@Mahdis-MacBook-Pro.local>
2023-05-02 22:09:19 +06:00
fdomain
f1a11d41cb
fix: fallback on CursorPagination ordering if unset on the view (#8954)
* this commit fixes the usage of a CursorPagination combined with a view
  implementing an ordering filter, without a default ordering value.
* former behavior was to fetch the ordering value from the filter, and
  raises an error if the value was None, preventing the fallback on the
  ordering set on the CursorPagination class itself.
* we reversed the logic by getting first the value set on the class,
  and override it by the ordering filter if the parameter is present
2023-05-02 06:55:59 +06:00
suayip uzulmez
54307a4394
Replaced OrderedDict with dict (#8964) 2023-04-30 15:20:02 +06:00
Mahdi Rahimi
1ce0853ac5
Refactor get_field_info method to include max_digits and decimal_places attributes in SimpleMetadata class (#8943)
* Refactor get_field_info method to include max_digits and decimal_places attributes in SimpleMetadata class

* Add new test to check decimal_field_info_type

* Update rest_framework/metadata.py

---------

Co-authored-by: Mahdi <mahdi@Mahdis-MacBook-Pro.local>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2023-04-27 10:24:13 +06:00
Asif Saif Uddin
38a74b42da
Revert "test codecov gha (#8946)" (#8947)
This reverts commit 684522807f.
2023-04-15 12:11:35 +06:00
Asif Saif Uddin
684522807f
test codecov gha (#8946) 2023-04-13 21:48:45 +06:00
Maxwell Muoto
0d6ef034d2
Implement __eq__ for validators (#8925)
* Implement equality operator and add test coverage

* Add documentation on implementation
2023-04-09 14:53:47 +06:00
ddelange
b1cec517ff
Ensure CursorPagination respects nulls in the ordering field (#8912)
* Ensure CursorPagination respects nulls in the ordering field

* Lint

* Fix pagination tests

* Add test_ascending with nulls

* Push tests for nulls

* Test pass

* Add comment

* Fix test for django30
2023-04-08 16:42:28 +06:00
Maxwell Muoto
62abf6ac1f
Use ZoneInfo as primary source of timezone data (#8924)
* Use ZoneInfo as primary source of timezone data

* Update tests/test_fields.py

---------

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2023-04-08 15:16:00 +06:00
Nikita Reznikov
4842ad1b6a
Add username search field for TokenAdmin (#8927) (#8934)
* Add username search field for TokenAdmin (#8927)

* Sort imports in a proper order (#8927)
2023-04-08 14:56:49 +06:00
Arnab Kumar Shil
959085c145
Handle Nested Relation in SlugRelatedField when many=False (#8922)
* Update relations.py

Currently if you define the slug field as a nested relationship in a `SlugRelatedField` while many=False, it will cause an attribute error. For example:

For this code:
```
class SomeSerializer(serializers.ModelSerializer):
    some_field= serializers.SlugRelatedField(queryset=SomeClass.objects.all(), slug_field="foo__bar")
```
The POST request (or save operation) should work just fine, but if you use GET, then it will fail with Attribute error:

> AttributeError: 'SomeClass' object has no attribute 'foo__bar'

Thus I am handling nested relation here. Reference: https://stackoverflow.com/questions/75878103/drf-attributeerror-when-trying-to-creating-a-instance-with-slugrelatedfield-and/75882424#75882424

* Fixed test cases

* code comment changes related to slugrelatedfield

* changes based on pre-commit and removed comma which was added accidentally

* fixed primary keys of the mock object

* added more test cases based on review

---------

Co-authored-by: Arnab Shil <arnab.shil@thermofisher.com>
2023-04-08 12:27:14 +06:00
Christian Franke
ea03e95174
docs: Fix authentication / authorization mixup (#8930)
`IsAuthenticatedOrReadOnly` authorizes users that are not
authenticated for read-only access to resources.

Therefore, they are unauthenticated users, not unauthorized users.
2023-04-04 14:44:59 +06:00
Christian Franke
3428cec194
Use consistent spelling for "authorization" (#8929)
Apart from a few exceptions, django-rest-framework uses the American
English spelling "authorization"/"authorized".

    $ git grep -oi authorised | wc -l
    2
    $ git grep -oi authorized | wc -l
    30

Replace the few occurences of the British English spelling with the
American English one.
2023-04-04 13:38:23 +06:00
Asif Saif Uddin
b60fbf3374
test django 4.2 stable release (#8932) 2023-04-03 22:35:11 +06:00
Asif Saif Uddin
6b73acc173
Update requirements-packaging.txt (#8921) 2023-03-28 16:35:44 +06:00
Asif Saif Uddin
59430111bd
Update tox with django 4.2rc1 (#8920) 2023-03-28 16:08:27 +06:00
Asif Saif Uddin
29b6dd8ed2
Bump version of jQuery to 3.6.4 & updated ref links (#8909) 2023-03-28 15:43:25 +06:00
Mathieu Dupuy
c9e7b68a4c
minor documentation improvements and fixes (#8903)
* minor documentation improvements and fixes

* Update docs/api-guide/fields.md

---------

Co-authored-by: Tom Christie <tom@tomchristie.com>
2023-03-14 13:31:34 +00:00
Konstantin Alekseev
b7523f4b9f
Support UniqueConstraint (#7438) 2023-03-03 13:04:47 +06:00
Asif Saif Uddin
9882207c16
test django 4.2b1 (#8892) 2023-02-28 22:02:12 +06:00
Jayant
3f8ab538c1
docs: add missing renderer import in tutorial 6 (#8885) 2023-02-27 00:06:48 +06:00
Jameel Al-Aziz
15c613a9eb
Allow generic requests, responses, fields, views (#8825)
Allow Request, Response, Field, and GenericAPIView to be subscriptable.
This allows the classes to be made generic for type checking.

This is especially useful since monkey patching DRF can be problematic
as seen in this [issue][1].

[1]: https://github.com/typeddjango/djangorestframework-stubs/issues/299
2023-02-22 21:39:01 +06:00
Jameel Al-Aziz
390daf7a92
Upgrade isort version in pre-commit (#8882)
This fixes recent issues with installing isort via pre-commit that was
introduced in recent versions of poetry-core.

See https://github.com/PyCQA/isort/pull/2078
2023-02-22 12:05:45 +06:00
Özgür
34953774f3
docs: fix code example (#8880) 2023-02-16 12:48:34 +06:00
Ehsan200
4abfa28e08
feat: Add some changes to ValidationError to support django style vadation errors (#8863) 2023-02-06 17:30:48 +06:00
piotrszyma
22d206c1e0
Inherit from faked classes in tests to satisfy mypy (#8859)
* tests: inherit FakeResolverMatcher from django.urls.ResolverMatcher in tests/test_versioning.py

* tests: inherit from rest_framework.versioning.BaseVersioning in tests/test_reverse.py

* fix: isort

---------

Co-authored-by: Piotr Szyma <pszyma@opera.com>
2023-01-28 17:18:58 +06:00
Asif Saif Uddin
2db0c0bf0a
initial django 4.2a1 testing (#8846)
* initial django 4.2a1 testing

* django 4.2 in classifier
2023-01-19 20:47:50 +06:00
Manish Kumar Shah
0618fa88e1
Fix Respect can_read_model permission in DjangoModelPermissions (#8009)
* Fix Respect `can_read_model` permission in DjangoModelPermissions

FIXES: #6324

* Updated documentation and simplified code
2023-01-13 14:52:54 +06:00
Devid
2d19f233ab
Add SimplePathRouter (#6789)
* Allow usage of Django 2.x path in SimpleRouter

* Use path in Default router

* Update docs/api-guide/routers.md

Co-authored-by: Éric <merwok@netwok.org>

* Update docs/api-guide/routers.md

Co-authored-by: Éric <merwok@netwok.org>

* Add tests also for default router with path

* Use a more relevant attribute for lookup when using path converters

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
Co-authored-by: Éric <merwok@netwok.org>
2023-01-12 14:16:48 +06:00
Yuekui
2b34aa4291
Re-prefetch related objects after updating (#8043)
* Re-prefetch related objects after updating

* Fix flake8 format

* Use _prefetch_related_lookups and refine test cases

* Add more test cases and refine prefetch checking
2023-01-11 15:30:15 +06:00
totycro
bfce663a60
Update documentation regarding arguments of ValidationError (#8807)
The documentation used to state that the `detail` argument was
mandatory, but in fact it currently is not.
2023-01-10 00:53:49 +06:00
Radosław Kowalski
89d6ce7d43
fix FilePathField required argument (#8805) 2023-01-05 01:21:57 +06:00
johnthagen
069c701ebf
Update docs to maintained djangorestframework-guardian2 (#8817)
* Update docs to maintained django-rest-framework-guardian2

* Update to updated GitHub project name
2023-01-03 19:18:05 +06:00
Asif Saif Uddin
b3d2753308
Revert "Fix bug in validators documentation (#8779)" (#8811)
This reverts commit 614bd87b60.
2023-01-03 17:59:36 +06:00
Asif Saif Uddin
bf4c6e78d4
try update django-filter==22.1 (#8813)
* try update django-filter==22.1

* Update requirements/requirements-optionals.txt
2023-01-03 17:45:28 +06:00
Asif Saif Uddin
118543769f
upddate setup python action to v4 (#8806) 2023-01-03 17:41:40 +06:00
Asif Saif Uddin
dd81eec2fd
attrs==22.1.0 (#8828) 2023-01-03 10:30:04 +00:00
Waqas Ali
406988ba7b
- fix transifex-client version in packaging requirements. (#8827) 2023-01-03 14:31:30 +06:00
David Graves
48a21aa0eb
raise ImproperlyConfigured exception if basename is not unique (#8438)
* raise ImproperlyConfigured if basename already exists

* rename already_registered function; return True/False

* additional basename tests

* additional basename tests

* Update rest_framework/routers.py

Co-authored-by: David Graves <dgraves@lrtcapitalgroup.com>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2022-12-10 22:50:41 +06:00
kanazawa
b79099f7ba
Use PrimaryKeyRelatedField pkfield in openapi (#8315) 2022-12-10 22:48:43 +06:00
Adam Johnson
59ae95b22f
Upgrade to tox 4 (#8795) 2022-12-08 08:01:07 +00:00
Jakub Bodek
1355890f9f
replace partition with split in BasicAuthentication (#8790)
* replace partition with split in BasicAuthentication

* test if basic auth without provided password fails
2022-12-08 09:52:35 +06:00
Rodrigo
1fbe16a8d2
Fix BooleanField's allow_null behavior (#8614)
* Fix BooleanField's allow_null behavior

* Update rest_framework.fields

- Use .get with default value for 'allow_null' kwarg in BooleanField's
  init
2022-12-06 15:04:50 +06:00
Sigve Sebastian Farstad
ee15731cbc
Handle Django's ValidationErrors in ListField (#6423)
Without this, Django's ValidationErrors will bypass the error collection
from ListField's children.

Here is an example that illustrates this change.

Consider a Serializer that uses ListField like this:

```python
class SomeSerializer(serializers.Serializer):
    uuids = serializers.ListField(
	child=serializers.PrimaryKeyRelatedField(
	    queryset=Model.objects.something(),
	    validators=[SomeCustomValidator()]
	)
    )
```

Validating data that looks like this works fine:

```python
{uuids: ['some-valid-uuid', 'some-valid-uuid']}
```

Raising a DRF ValidationError for one of the children works fine, giving
an error object like:

```python
{'uuids': {0: ErrorDetail(string='Some validation error')}}
```

Raising a Django ValidationError for one of the children works
differently (which serializers.PrimaryKeyRelatedField can do in some
cases, like when the uuid is malformed). It gives an error object like:

```python
{'uuids': ["'X' is not a valid UUID."]}
```

Handling Django's ValidationErrors in ListField explicitly (like in this
pull request), will maintain a regular error interface in this case:

```python
{'uuids': {0: ErrorDetail(string="'X' is not a valid UUID.")}}
```
2022-12-04 20:37:47 +06:00
juspence
cc3c89a11c
Remove a bit of inline CSS. Add CSP nonce where it might be required and is available. (#8783)
Co-authored-by: Craig Anderson <craiga@craiga.id.au>
2022-12-02 11:47:04 +06:00
Tom Christie
a02bb79d87
Update admin.py (#8534)
Use `autocomplete_fields` to keep the select user field manageable.
2022-12-02 11:40:15 +06:00
Floris Hoogenboom
614bd87b60
Fix bug in validators documentation (#8779)
Function validators seem to have to return their value (which will become part of `validated_data`) as part of their signature.
2022-12-01 22:13:14 +06:00
juspence
1ae812ea20
Make browsable API compatbile with strong CSP (#8784)
Co-authored-by: Alexander Bliskovsky <abliskovsky@fusionbox.com>
2022-11-29 20:49:41 +00:00
Luka Jeran
6ec6ddea9b
Avoid inline script execution for injecting CSRF token (#7016)
Scripts with type="application/json" or "text/plain" are not executed, so we can
use them to inject dynamic CSRF data, without allowing inline-script execution
in Content-Security-Policy.
2022-11-29 16:10:32 +00:00
T. Franzel
f0095b4de2
Remove Core API mentions from docs (#8780)
* remove coreapi generator mentions & hidden docs

* remove coreapi doc & redirect broken links to github snapshot
2022-11-28 14:41:08 +01:00
T. Franzel
5435b2c9f0
mitigate global dependency on inflection #8017 (#8781) 2022-11-28 09:11:10 +06:00
Thomas Irgang
3bf611787a
Register Django urls (#8778)
Without adding the URLs manually, the users and groups APIs were not usable.

My env:
(venv) ➜  tutorial pip freeze
asgiref==3.5.2
astroid==2.12.13
autopep8==2.0.0
dill==0.3.6
Django==4.1.3
djangorestframework==3.14.0
isort==5.10.1
lazy-object-proxy==1.8.0
mccabe==0.7.0
platformdirs==2.5.4
pycodestyle==2.10.0
pylint==2.15.6
pylint-django==2.5.3
pylint-plugin-utils==0.7
pytz==2022.6
sqlparse==0.4.3
tomli==2.0.1
tomlkit==0.11.6
wrapt==1.14.1
2022-11-27 18:53:48 +06:00
Giebisch
4ef0fc1ca0
Implemented Verbose Name Translation for TokenProxy (#8713) 2022-11-27 16:45:54 +06:00
Peter Thomassen
52f4139674
Properly handle OverflowError in DurationField deserialization (#8042)
Related: https://github.com/django/django/pull/8870/files
2022-11-24 17:27:45 +06:00
Shinya Ohyanagi
9e328a9549
Fix OpenAPI operation name plural appropriately (#8017) 2022-11-24 13:48:05 +06:00
hashlash
ebde56b932
Represent SafeString as plain string on schema rendering. (#8429)
* Use SafeString.represent_str to represent SafeString as str

* Add SafeString yaml rendering test
2022-11-23 20:42:06 +06:00
Denny Biasiolli
c0d95cb967
Fix #8771 - Checking for authentication even if _ignore_model_permissions = True (#8772) 2022-11-22 20:21:16 +06:00
T. Franzel
b87699c034
Update schema generation doc & add deprecation notice #8453 (#8773)
* Update schema generation doc & add deprecation notice #8453

* Update docs/topics/documenting-your-api.md

Co-authored-by: Tom Christie <tom@tomchristie.com>

* Update docs/topics/documenting-your-api.md

Co-authored-by: Tom Christie <tom@tomchristie.com>

* Update docs/topics/documenting-your-api.md

Co-authored-by: Tom Christie <tom@tomchristie.com>

Co-authored-by: T. Franzel <13507857+tfranzel@users.noreply.github.com>
Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-11-22 19:53:54 +06:00
Géry Ogam
fd7d3a7b92
Update 6-viewsets-and-routers.md (#8590)
* Update 6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

* Update docs/tutorial/6-viewsets-and-routers.md

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2022-11-22 14:39:26 +06:00
Subin Kim
8175f05c89
Added pagination settings test case (#8362) 2022-11-22 14:18:47 +06:00
Shi Pengtao
0ae3323bd2
fix 404 when page query parameter is empty string (#8578)
* fix 404 when page query parameter is empty string

* Update pagination.py

* Update pagination.py

Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-11-22 12:37:31 +06:00
954
03c2ef1787
Fixes instance check in ListSerializer.to_representation (#8726) (#8727)
* Fixes 'RelatedManager' object is not iterable in ListSerializer.to_representation.(#8726)

* Change to only BaseManager

* Commit unit test

* Update tests/test_serializer_lists.py

* Update tests/test_serializer_lists.py

* Update tests/test_serializer_lists.py

* Update tests/test_serializer_lists.py

* Update tests/test_serializer_lists.py

* Update tests/test_serializer_lists.py

* Format import

* Format import

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2022-11-22 12:01:01 +06:00
Jason Joy Atsu Winmorre
9e56f54efb
FloatField will crash if the input is a number that is too big (#8725)
* FloatField will crash if the input is a number that is too big

* Added Unit test for float field overflow error catch

* Removed random import

* Removed additional imported ValidationError

* Update rest_framework/fields.py

* Update tests/test_fields.py

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
2022-11-22 11:15:25 +06:00
smt-insens
dc300aa4e0
[FIX] add missing DurationField to SimpleMetada label_lookup (#8702) 2022-11-21 20:33:19 +06:00
Asif Saif Uddin
751808c59b
converted assertion to pytest style in test status (#8769) 2022-11-21 11:32:07 +00:00
Paolo Melchiorre
2a2b092864
Fix #8751 - Add support to Python 3.11 (#8752) 2022-11-21 11:47:21 +01:00
Asif Saif Uddin
cac89ae65d
update minimum version to psycopg2-binary>=2.9.5 (#8767) 2022-11-18 15:32:10 +00:00
Asif Saif Uddin
21fdf066b4
pytest versions update (#8745)
* pytest versions update

* pytest>=7.0.0,<8.0

* pytest>=7.2.0,<8.0

* pytest>=6.2.0,<8.0
2022-11-18 11:09:05 +00:00
Manos
df60510db5
Add 3rd party entry for rest-framework-roles (#8755) 2022-11-17 14:13:18 +00:00
Ilaletdinov Almaz
3e052376ac
Added http 102, 103, 421, and 425 status codes in documentation (#8763) 2022-11-17 13:13:09 +00:00
Clemens Wolff
759fc6f42e
Make request consistently available in pagination classes (#8764)
* Store request in CursorPagination field

* Define request at start of pagination entrypoint
2022-11-17 12:47:47 +00:00
Henrik Wahlgren
d5f228dd00
Possibility to remove trailing zeros on DecimalFields representation (#6514)
* Added normalize parameter to DecimalField to be able to strip trailing zeros. Fixes #6151.

* Updated docs to include normalize option on DecimalField

* Fixed linting error in test_fields

* Removed comment and renamed normalize to normalize_output as suggested in code review

Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-11-16 14:31:50 +00:00
Stanislav Levin
78cdae6999
Fix Pytest's deprecation warnings about nose usage (#8758)
Pytest 7.2.0 deprecated plain `setup` and `teardown` functions and
methods as nose idioms:
https://docs.pytest.org/en/latest/changelog.html#pytest-7-2-0-2022-10-23

`setup` can be safely replaced with `setup_method`:
https://docs.pytest.org/en/stable/deprecations.html#setup-teardown

Fixes: https://github.com/encode/django-rest-framework/issues/8757
Signed-off-by: Stanislav Levin <slev@altlinux.org>

Signed-off-by: Stanislav Levin <slev@altlinux.org>
2022-11-15 12:29:15 +00:00
Lewis M. Kabui
ae7a2b0dfa
Remove extraneous word "Both" (#8740)
* Remove extraneous word "Both"

* Update Multiparser docs

Co-authored-by: Lewis Kabui <lewisemm@users.noreply.github.com>
2022-11-10 10:31:06 +00:00
Thomas
1142ee5fc1
Update jobs.md (#8737)
Update remoteok.io to remoteok.com
Add pyjobs.com
2022-11-02 11:10:45 +00:00
Géry Ogam
2510456817
Update quickstart.md (#8575)
* Update quickstart.md

* Use PEP 8 compliant import

* Remove unauthorized password by Django (too common)
2022-10-20 15:32:25 +01:00
Francisco Couzo
041b88f8bb
Improve style, fix some typos (#8405)
* Improve style, fix some typos

* Update docs/api-guide/fields.md

Co-authored-by: Tom Christie <tom@tomchristie.com>

Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-10-19 11:20:11 +01:00
Elton Maiyo
e354331743
Fixes typo (#8719) 2022-10-19 11:11:09 +01:00
Den
35c5be6ec2
Add a method for getting serializer field name (OpenAPI) (#7493)
* Add a method for getting serializer field name

* Add docs and test

Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-10-17 10:47:45 +01:00
Jan Lis
0cb693700f
add __eq__ method for OperandHolder class (#8710) 2022-10-17 10:20:59 +01:00
mka142
b221aa2cf6
Update schemas.md (#8707) 2022-10-17 09:54:48 +01:00
Ran Benita
9407833a83
Avoid importing django.test package when not testing (#8699)
Importing anything `rest_framework` causes `django.test` to be imported.
This is because DRF registers a receiver on the
`django.test_signals.setting_changed` signal.

This is not really a problem, but it is good to avoid this because it
bloats the memory with unnecessary modules (e.g. `django.test`,
`django.core.servers.basehttp`, `socketserver`) and increases the
startup time. It also doesn't feel right to import test code into
non-test code.

Try to import the signal from a core module if possible.

Note that there's another `django.test` import in `MultiPartRenderer`,
however this import is done lazily only if the functionality is used so
can be easily avoided.
2022-10-14 16:30:26 +01:00
Shyamkumar Yadav
1fd268ae2b
Docs: use asterisk for unordered list (#8697) 2022-10-14 11:22:19 +01:00
Shyamkumar Yadav
20d347a806
Docs: Convert all tabs into spaces (#8692) 2022-10-12 11:23:45 +01:00
Klaas van Schelven
56946fac8f
Preserve exception messages for wrapped Django exceptions (#8051)
* Preserve messages for wrapped Django exceptions

* Fix the test

* Update test_generics.py

* Update test_generics.py

Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-10-11 12:48:57 +00:00
Norbert Schuler
911b207fa1
Added examples to schema of CursorPagination (#8687)
* Added examples to schema of CursorPagination

Fix https://github.com/encode/django-rest-framework/issues/8686

Added missing examples for CursorPagination class to disable warnings in https://github.com/tfranzel/drf-spectacular and make it consistent with other pagination classes.

* Adapted test case for paginated response schema
2022-10-11 11:50:33 +01:00
Markus Legner
d507cd851c
Fix infinite recursion with deepcopy on Request (#8684) 2022-10-07 11:58:38 +01:00
Ahzam Ahmed
c10f226622
Refactor: Replace try/except with contextlib.suppress() (#8676) 2022-10-05 11:02:00 +01:00
mschmidm
99cf2c415f
Docs: Updated browsable-api.md (#8678)
- Replace the broken Bootswatch-Link with an Jsdelivr-Link as suggested at https://bootswatch.com/help/
- Updated the stated Bootstrap version
- Added a note that the Bootstrap version must match the default one

Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-10-04 12:15:51 +01:00
Sardorbek Imomaliev
e7777cb1ee
Add spaces to router example in 6-viewsets-and-routers.md (#8448) 2022-10-03 11:48:18 +01:00
Tom Christie
ca75300ae9
Update requirements-testing.txt (#8680)
* Update requirements-testing.txt

* Update requirements-testing.txt
2022-10-03 11:39:32 +01:00
manelbdacosta
79de112d62
Minor fix to SerializeMethodField docstring (#8629) 2022-10-03 10:36:51 +01:00
Ahzam Ahmed
9e398c59ab
Minor refactor: Unnecessary use of list() function (#8672) 2022-09-27 16:08:40 +01:00
Allie
3e51ba4d51
Update documentation on dependency installation (#8566)
We depend on pytz, but until late last year we got it implicitly through
depending on Django. Since their release 4.0, however, they no longer
depend on pytz; commit 250479dc3 added the dependency directly to our
metadata in setup.py, but the documentation about dependencies (most
importantly, the instructions for new contributors) was left untouched.

This commit updates the new contributor instructions to suggest an
"editable installation" of the project at the step that previously had
users manually install Django. In this mode, pip fetches and installs
the project dependencies automatically (so in the unlikely event we grow
another dependency, that doc doesn't need to be changed again) and makes
the project available to the virtualenv's python as a normal package,
but doesn't require reinstallation for mundane edits.
2022-09-27 13:54:52 +01:00
Ahzam Ahmed
73f4835a53
Unnecessary list comprehension (#8670) 2022-09-26 13:05:53 +01:00
David Cain
2de5081829
Use correct class to indicate present deprecation (#8665)
`PendingDeprecationWarning` means "we plan to deprecate, but haven't
yet." A feature that's to be deleted in the next release is not planned
to be deprecated; it **is** deprecated.

> Base class for warnings about features which are obsolete and expected
> to be deprecated in the future, but are not deprecated at the moment.
>
> This class is rarely used as emitting a warning about a possible
> upcoming deprecation is unusual, and DeprecationWarning is preferred for
> already active deprecations.

https://docs.python.org/3/library/exceptions.html#PendingDeprecationWarning

Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-09-22 14:07:43 -04:00
Tom Christie
2da473c8c8 Add 3.14 announcement to the docs 2022-09-22 12:37:51 +01:00
Tom Christie
58e0a698e3
Update setup.py to drop Django 2.2 and update release notes (#8666) 2022-09-22 12:31:43 +01:00
Gulshan Ramnath Prajapati
11bfda92ba
both statement have dupplicate bodies (#8633) 2022-09-22 10:50:56 +01:00
Aaron Taajik
058424c16a
docs: delete duplicate explanation (#8641) 2022-09-22 10:50:23 +01:00
Cihan Eran
eb88dfc4b4
Add --api-version CLI option to generateschema (#8663)
* Add --version CLI option to generateschema

* fix conflicting argument name
2022-09-22 10:36:01 +01:00
David Cain
f34f1562ff
Remove old deprecation classes for 3.14 release (#8664)
When DRF 3.14 is released, these exception classes will be meaningless,
so we can delete them (this has always been done).

A previous PR removed the last incidence of `RemovedInDRF313Warning`,
but didn't outright delete the class for fear of shipping a breaking
change: https://github.com/encode/django-rest-framework/pull/8589
2022-09-22 10:32:26 +01:00
Tom Christie
c6cafc9725
Update release-notes.md 2022-09-21 14:33:41 +01:00
Tom Christie
f8b3f38b57
Update supported versions for 3.14 release (#8662)
* Update supported versions for 3.14 release

* Fix up test case for Django 3.0
2022-09-21 14:32:02 +01:00
Tim Schilling
b658915846
Version 3.14.0 proposal (#8599)
* Version 3.14.0

* Update docs/community/release-notes.md to use proper links.

Co-authored-by: Adam Johnson <me@adamj.eu>

* Add community announcement page for version 3.14

* Remove deprecated NullBooleanField.

* Change openapi _get_reference removal to 3.15

This deprecation was never released in the 3.13.x series and therefore
can't be removed at the same time the replacement is released.

* Removing deprecated openapi methods.

Co-authored-by: Adam Johnson <me@adamj.eu>
2022-09-21 14:08:12 +01:00
Tom Christie
51f1aff162
Revert 8552 (#8661) 2022-09-21 14:03:39 +01:00
Cihan Eran
3401ef56f8
Add --version CLI option to generateschema (#8552) 2022-09-21 13:08:21 +01:00
David Smith
4aea8dd65a
Change semantic of OR of two permission classes (#7522)
* Change semantic of OR of two permission classes

The original semantic of OR is defined as: the request pass either of the two has_permission() check, and pass either of the two has_object_permission() check, which could lead to situations that a request passes has_permission() but fails on has_object_permission() of Permission Class A, fails has_permission() but passes has_object_permission() of Permission Class B, passes the OR permission check. This should not be the desired permission check semantic in applications, because such a request should fail on either Permission Class (on Django object permission) alone, but passes the OR or the two.

My code fix this by changing the semantic so that the request has to pass either class's has_permission() and has_object_permission() to get the Django object permission of the OR check.

* Update rest_framework/permissions.py

* Update setup.cfg

Co-authored-by: Mark Yu <markyu98@outlook.com>
Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-09-21 12:19:33 +01:00
willbeaufoy
354ae73ffb
Make APIClient.force_authenticate() work with user=None (#8212)
* Fix testing with token

* Add unit test

* Split unit test into 3

* Fix linting error
2022-09-15 09:35:48 +01:00
Aaron Taajik
acf6582de4
Docs: edit headings in Authentication (#8644) 2022-09-09 15:27:15 +01:00
Aaron Taajik
5b616c503f
docs: fix level of some headings (#8636) 2022-09-05 13:02:12 +01:00
Aaron Taajik
1ca1583513
docs: add the missing module name (#8635) 2022-09-05 11:20:23 +01:00
gabn88
54d52c66fd
Fixes that namespaced views now also appear in the extra actions (#8598)
* Fixes that namespaced views now also appear in the extra actions

Before this fix, namespaced views would not appear in the extra actions. With this fix they do.

* Flake fix
2022-08-31 11:17:19 +01:00
Daian Gan
c7acdd6006
Use .get() to find correct kwargs field and avoid KeyError (#8607)
In the "Creating custom mixins" documentation, the code example recommends using
```python
if self.kwargs[field]
```
However, if the correct field is not present in kwargs, a KeyError arises.
A more secure option is tu use .get() to validate that the field is contained in the kwargs dictionary:
```python
if self.kwargs.get(field)
```
2022-08-31 10:18:17 +01:00
Géry Ogam
5bf338ea88
Update README.md (#8592)
* Update README.md

* revert ViewSet change

Co-authored-by: Adam Johnson <me@adamj.eu>
2022-08-30 12:30:42 +01:00
Aaron Taajik
72e66e4d67
fix minor typo (#8626) 2022-08-30 12:27:48 +01:00
WillowP
dca4d7c027
Docs: Clarify model used in DjangoModelPermissions (#8615)
I found it unclear how the model was determined for `DjangoModelPermissions`. The docs say you need a `queryset` or `get_queryset`, but not that the value returned from those is what determines the model that is used.
2022-08-22 12:32:54 +01:00
MaertHaekkinen
0a10556548
Update README.md (#8611)
Update twitter of the project's author
2022-08-22 11:35:23 +01:00
Youngkwang Yang
9043df6be7
Add trailing slash (#8604) 2022-08-22 10:52:34 +01:00
Jonas Lundberg
df584350b4
Prevent head method mapping to coerce action name (#7729) 2022-08-12 12:00:55 +01:00
ProstoMaxim
791d48c690
Enforce is_valid(raise_exception=False) as a keyword-only argument. (#7952)
* make raise_exception a keyword-only argument

* make raise_exception keyword-only in metaclass
2022-08-10 14:00:30 +01:00
Adam Johnson
35a6d65e22
Fix setuptools warning about license_files (#8595) 2022-08-10 13:47:39 +01:00
Adam Johnson
20d106d8a3
Upgraded Bootstrap to 3.4.1 and added CSS source maps (#8591) 2022-08-10 11:53:21 +01:00
David Cain
8b2ccccbe5
Stop calling set_context, planned for 3.13 drop (#8589)
Per the deprecation warnings (which have been raised since DRF 3.11),
`set_context()` was planned not to be supported in DRF 3.13. I think we
can safely delete it, in favor of `requires_context`.

From the 3.11 announcement:

> Previous our approach to this was that implementations could include a
> `set_context` method, which would be called prior to validation. However
> this approach had issues with potential race conditions. We have now
> move this approach into a pending deprecation state. It will continue to
> function, but will be escalated to a deprecated state in 3.12, and
> removed entirely in 3.13.

Why keep `RemovedInDRF313Warning` around?
=========================================
It's a bit odd that version 3.13 includes an exception class describing
things which are to be deleted in 3.13, but I've opted to keep the (now
unreferenced) class around, for fear of breaking others' setup.

(For example, if projects have a `filterwarnings` setup meant to
intercept `rest_framework.RemovedInDRF313Warning`, an error will be
thrown due to an unresolvable reference).
2022-08-08 11:18:49 +01:00
Łukasz Wieczorek
fd8adb32ce
Refactor short names in exceptions (#8585) 2022-08-01 16:28:05 +01:00
Allan Lewis
224168a28f
exceptions.ErrorDetail: Handle NotImplemented correctly in __ne__ (#8538)
PR #7531 resolved issue #7433 by updating `ErrorDetails.__eq__` to correctly
handle the `NotImplemented` case. However, Python 3.9 continues to issue the
following warning:

    DeprecationWarning: NotImplemented should not be used in a boolean context

This is because `__ne__` still doesn't handle the `NotImplemented` case
correctly. In order to avoid this warning, this commit makes the same change
for `__ne__` as previously made for `__eq__`.
2022-08-01 15:18:22 +01:00
Sergey Lyapustin
a1b35bb44b
Use example.com domain in tests. (#8571)
* Use example.com domain for the samples.

* Fixed typo.
2022-07-25 10:28:41 +01:00
Carlton Gibson
ad282da97c
Replaced parse_header with parse_header_parameters. (#8556)
Add a backwards compatibility shim for Django versions that have no (or an incompatible)
django.utils.http.parse_header_parameters implementation.

Thanks to Shai Berger for review. 

Co-authored-by: Jaap Roes <jroes@leukeleu.nl>
2022-07-14 14:20:36 +02:00
Stanislav Khlud
101aff6c43
Make autogenerated read only fields to be able to be nullable (#8536) 2022-06-28 15:22:46 +01:00
Burak Kadir Er
9f07d9edeb
Make minor corrections in docs (#8525) 2022-06-24 14:21:51 +01:00
Felix Viernickel
129890ab1b
Fix error in throttling when request.user is None (#8370)
Check to see if request.user is set before proceeding with further
authentication checks.
2022-06-24 13:02:11 +01:00
Yuekui
2051a79da3
Fix "`" typo (#8529) 2022-06-24 12:08:18 +01:00
Stian Jensen
dba9493a90
Don't evaluate default_timezone unless needed (#8531)
If you set a custom timezone for a DateTimeField, the function
self.default_timezone() is still called, since fallback params to
getattr are still evaluated.

This rewrites to use hasattr, so the fallback case is only executed if
it will actually be used. If you render a lot of DateTimeFields in a
serializer, the time spent evaluating default_timezone() once for each
of them can accumulate to quite a bit, which is just unused work in the
case where timezone is already specified on the field.
2022-06-24 11:28:00 +01:00
Tom Christie
fa9d516ee2
Update docstring test for more recent pygments version (#8530)
* Update docstring test for more recent pygments version

* Drop unused import
2022-06-20 10:44:27 +01:00
Burak Kadir Er
2506d0b4f2
Update include and namespace URLs (#8520) 2022-06-09 15:30:47 +01:00
Alessandro
82475c232b
Made relative URLs clickable as well. (#8464) 2022-06-08 15:03:00 +01:00
Stephen Finucane
5185cc9348
Handle unset fields with 'many=True' (#7574)
* Handle unset fields with 'many=True'

The docs note:

  When serializing fields with dotted notation, it may be necessary to
  provide a `default` value if any object is not present or is empty
  during attribute traversal.

However, this doesn't work for fields with 'many=True'. When using
these, the default is simply ignored.

The solution is simple: do in 'ManyRelatedField' what we were already
doing for 'Field', namely, catch possible 'AttributeError' and
'KeyError' exceptions and return the default if there is one set.

Signed-off-by: Stephen Finucane <stephen@that.guru>
Closes: #7550

* Add test cases for #7550

Signed-off-by: Stephen Finucane <stephen@that.guru>
2022-06-08 14:46:19 +01:00
Marti Raudsepp
26830c3d2d
Fix QueryDict type error in test (#8475)
QueryDict takes a `str` argument. Discovered while working on
djangorestframework-stubs.
2022-06-08 14:37:46 +01:00
itsdkey
e7af8d662b
tests for #5127 (#7715)
* tests for #5127

* Resolves #5127
2022-06-08 13:41:26 +01:00
Patrick Daley
f8a03b096b
Remove pluralisation from basenames (#8517)
HyperlinkIdentityFields in serializers reference 'snippet-highlight' and 'snippet-detail', router basenames updated to match.
2022-06-07 12:35:01 +01:00
Grigory
1396f6886a
Respect model error_messages for relation (#7599) 2022-06-06 13:53:42 +01:00
Alan Crosswell
563a20a040
make get_reference public (#7515) 2022-06-06 13:44:02 +01:00
Daniel Gilge
bb7dcef19b
Update get_schema in docs (#7402) 2022-06-06 13:31:00 +01:00
Krukov D
281fc074ba
improve performance for noncallble attributes (#8502)
Co-authored-by: Dima Kryukov <dmitry.kryukov@pandadoc.com>
2022-06-06 12:54:57 +01:00
ghazi-git
292ead1fe0
add drf-standardized-errors to third party packages (#8487)
Co-authored-by: Tom Christie <tom@tomchristie.com>
2022-06-06 12:46:11 +01:00
Leonardo Gregianin
5471f8a1d9
Added django-requestlogs in third party packages (#8497) 2022-06-06 12:39:36 +01:00
Mariusz Felisiak
333f1ffb94
Confirmed support for Django 4.1. (#8498) 2022-06-06 12:39:06 +01:00
Tom Christie
7069083b0f Promote Spacinov to premium sponsorship 2022-06-06 11:07:25 +01:00
Tom Christie
ce21454a43 Update homepage sponsors 2022-06-06 11:00:01 +01:00
Tom Christie
e5fb9af0ea Add FEZTO as a premium sponsor 2022-05-26 11:19:09 +01:00
Tom Christie
449ce6cc75 Resize sponsor images 2022-05-26 10:48:08 +01:00
Tom Christie
ed00e11cc5 Add FEZTO 2022-05-26 10:40:46 +01:00
Tom Christie
33b86a8e53
Recommend Django REST Knox (#8490)
* Recommend Django REST Knox

* Pin jinja2 to fix docs builds
2022-05-18 13:10:38 +01:00
Q_back
cdc956a96c
Update description of docs/api-guide/fields.md -> required (#8476)
fix: Documentation did not point out that default value of `required`
`Field` parameter is `False` depending on the Django's `Model.field`.
2022-05-03 11:10:37 +01:00
Aarni Koskela
b1004a4733
docs: Add a note on concurrency and races (#6950)
Refs #5181

Co-authored-by: Adam Johnson <me@adamj.eu>
2022-04-24 23:16:18 +01:00
Kojo Idrissa
86673a337a
corrected grammar to improve clarity (#8466) 2022-04-14 21:00:38 +01:00
hashlash
df92e57ad6
Added test client support for HTTP 307 and 308 redirects (#8419)
* Add retain test data on follow=True

* Simplify TestAPITestClient.test_follow_redirect

Inspired from Django's ClientTest.test_follow_307_and_308_redirect

* Add 307 308 follow redirect test
2022-03-24 09:57:42 +00:00
Tom Christie
df4d16d2f1
Add StaleBot (#8423) 2022-03-24 09:23:16 +00:00
Wagner de Lima
7e4e6d2070
docs: include drf-social-oauth2 to docs. (#8310)
django-rest-framework-social-oauth2 is not a maintained library anymore.
2022-03-23 12:09:05 +00:00
Shivendra Pratap Kushwaha
4464ce7270
Link added for Test Case Classes and corrected stable link for Refresh from DB (#8381)
Link added for Test Case Classes and corrected stable link for Refresh from DB.
2022-03-23 12:07:44 +00:00
Tom Christie
a4334a8126
Update contribution guidelines (#8422) 2022-03-23 11:52:45 +00:00
Tom Christie
75f1998123
Update throttling docs (#8424) 2022-03-23 11:52:26 +00:00
Mariusz Felisiak
0b88583a10
Bumped versions in Github actions configuration to v3. (#8414) 2022-03-23 11:28:46 +00:00
Tom Christie
070c32f4a6
Update SECURITY.md (#8412) 2022-03-16 12:12:25 +00:00
baseplate-admin
b521160c92
Fix code block in README.md (#8408)
Hi there,

The code block below show imply `Python` as it lives in `settings.py`

```
INSTALLED_APPS = [
    ...
    'rest_framework',
]
```

This pull request essentially fixes that.
2022-03-16 11:35:24 +00:00
Tom Christie
b3083d83ae
Update index.md (#8411)
Update security email.
2022-03-16 11:35:04 +00:00
Tom Christie
0e3bc2b1e0
Throttling disclaimer (#8403)
* Throttling disclaimer

* Expand throttling disclaimer.
2022-03-11 10:58:59 +00:00
Timothy Allen
a53e523f93
We've renamed the drf-renderer-xlsx package to drf-excel. (#8396) 2022-03-08 10:39:16 +00:00
Josh
efc7c1d664
Update accepted_media_type argument in Renderer docs (#8364) 2022-02-12 16:21:59 +00:00
Partho Kumar Rajvor
5bea22f321
Added http 102, 103, 421, and 425 status codes (#8350) 2022-02-03 11:57:47 +00:00
Bhuwan Panta
c26ec5a3b8
Update 6-viewsets-and-routers.md (#8349)
# Basename key missing in the tutorial
```diff
+router.register(r'snippets', views.SnippetViewSet,basename="snippets")
+router.register(r'users', views.UserViewSet,basename="users")
-router.register(r'snippets', views.SnippetViewSet)
-router.register(r'users', views.UserViewSet)
```
2022-02-01 13:48:22 +00:00
Tom Christie
a5d741aba4
Update renderers.py 2022-02-01 09:42:43 +00:00
Sevdimali
f378f98a40
if else optimization (#8340)
Removed redundant parentheses
2022-01-27 15:02:20 +00:00
denniskloyn
02eeb6fa00
Change MIDDLEWARE_CLASSES to MIDDLEWARE (#8333)
The `MIDDLEWARE_CLASSES` setting got changed to `MIDDLEWARE` in [Django 1.10](https://docs.djangoproject.com/en/1.10/topics/http/middleware/).
2022-01-18 08:52:11 +00:00
Shivendra Pratap Kushwaha
94eb804abe
Update filtering.md (#8331) 2022-01-17 09:41:23 +00:00
Tom Christie
c5be86a6db
Update sponsor URL (#8328)
* Update sponsor URL

* Update index.md
2022-01-11 13:01:25 +00:00
Suntae Kim
f9ccbad4d9
minor update on tutorial serialization (#8323) 2022-01-06 13:55:44 +00:00
kaushik kothiya
5b2abbed25
Correct variable name (#8306)
urlpatterns name variable name in space remove.
2021-12-22 15:17:57 +00:00
Luke Plant
bce9df9b5e
Make ReturnDict support dict union operators on Python 3.9 and later (#8302)
Fixes issue #8301
2021-12-22 15:08:58 +00:00
Guilouf
45082b3936
Fixed missing "fields" meta argument in docs (#8243)
* Fixed missing "fields" meta argument in docs, leading to an assertion error

* Update docs/api-guide/serializers.md

Co-authored-by: Tom Christie <tom@tomchristie.com>

Co-authored-by: Tom Christie <tom@tomchristie.com>
2021-12-17 15:20:14 +00:00
Tom Christie
f4cf0260bf Version 3.13.1 2021-12-15 15:18:24 +00:00
Tom Christie
a780e80deb
Revert "Make api_view respect standard wrapper assignments (#8291)" (#8297)
This reverts commit 9c97946531.
2021-12-15 15:16:38 +00:00
juliangeissler
2d52c9e8bc
Update Tutorial - quickstart (#7943)
* Tutorial - Adjust quickstart

Add asgi.py file
Also add paragraph for the second user, which is later displayed

* Tutorial - Adjust quickstart

It seems that there is no CLI command to easily create a user
Remove the second user from the Markdown
Image next

* Tutorial - quickstart - Update browsable API image

Only show the admin user
New Image has similar width and is compressed
2021-12-13 14:08:55 +00:00
Abhineet
f3bb5b9cdc
Add missing commas in pagination response samples (#8185) 2021-12-13 14:04:04 +00:00
Jameel Al-Aziz
b3beb15b00
Fix CursorPagination parameter schema type (#7708)
The CursorPagination's cursor query parameter expects a string and not
an integer.

Fixes #7691
2021-12-13 14:03:09 +00:00
Tom Christie
7a84dc749c
Version 3.13 (#8285)
* Version 3.12.5

* Version 3.13

* Version 3.13
2021-12-13 13:10:17 +00:00
tim-mccurrach
9c97946531
Make api_view respect standard wrapper assignments (#8291) 2021-12-13 13:08:40 +00:00
Tom Christie
d0bb4d877f
Tweak test_description (#8293) 2021-12-13 09:33:03 +00:00
Alexander Clausen
ba25869045
Fix REQUIRED_PYTHON in setup.py (#8292)
Just a left-over from #8288 to sync the "Unsupported Python version" message with `python_requires`.
2021-12-13 08:57:55 +00:00
Paolo Melchiorre
773f479719
Python/Django compatibility updates (#8288)
* Update python and django versions in tox.ini

* Update  python requires in setup.py

* Update tox.ini

Co-authored-by: Tom Christie <tom@tomchristie.com>
2021-12-10 15:31:01 +00:00
Tom Christie
217b0bf3af
Add Python 3.10 to test matrix (#8287)
* Add Python 3.10 to test matrix

* Update README, docs homepage to properly reflect Python versions that we test against
2021-12-10 12:04:27 +00:00
Tom Christie
16ca0c24d3 Add 3.10 to tox.ini and setup.py 2021-12-10 11:53:48 +00:00
Jet Li
1cb3fa2e81
Test Django 4.0 (#8280)
* Test Django 4.0

Django 4.0 released today.

* Test Django 4.0

* Test Django 4.0

* Test Django 4.0
2021-12-10 09:31:05 +00:00
Tom Christie
c05998f5dd Add CryptAPI to docs homepage 2021-12-08 15:11:55 +00:00
Tom Christie
d1bab643ab
Update README.md 2021-12-08 14:53:45 +00:00
Tom Christie
6e0cb8a7aa
Add CryptAPI sponsorship (#8283) 2021-12-08 14:53:06 +00:00
Chen Wen Kang
47ee3fc9a9
Update docs related to coreapi to include deprecation notice (#8186)
* Update docs related to coreapi to include deprecation notice

* Update docs to use reference to version 3.10 release notes instead of 3.9
2021-12-08 14:38:42 +00:00
Alexander Klimenko
b0d407fd63
Made api_setting.UNICODE_JSON/ensure_ascii affecting json schema (#7991) 2021-12-08 14:37:32 +00:00
Matthew Pull
3a762d9aac
Update permissions.md (#8260)
I might just be misunderstanding something (always a strong possibility!), but it seems to me that the table on the Permissions page is slightly inaccurate.

For `permission_classes`, wouldn't it have global-level permissions for list actions (rather than no permission control, as is currently listed)?
2021-12-08 14:35:06 +00:00
Jeremy Langley
37b73ef46e
IsAdmin permissions changed to IsAdminUser (#8227)
Documentation change to keep up with the code permission changes.

Co-authored-by: Jeremy Langley <jlangley2code@gmail.com>
2021-12-08 14:33:41 +00:00
Jaap Roes
dabf2216c3
Update django-cors-headers links (#8176) 2021-12-08 14:30:34 +00:00
Yecine Megdiche
380ac8e79d
Remove old-style super calls (#8226) 2021-12-06 15:32:33 +00:00
Asif Saif Uddin
580bf45ccf
test v4 beta 1 (#8222)
* test v4 beta 1

* django 4 rc1
2021-11-22 10:48:58 +00:00
Dmytro Litvinov
0d5250cffa
Fix link to installation of httpie (#8257)
Right now httpie moved to "httpie" organization (https://github.com/httpie/httpie) and they don't have "installation" at their GitHub. Instead of that, they have "Getting started" section with link to "Installation instructions".
2021-11-15 08:54:19 +00:00
Anton Burnashev
060a3b632f
Docs: fix broken link (#8245) 2021-11-10 16:31:15 +00:00
Sébastien Lavoie
781890b7df
docs(api-guide-testing): Fix typo 'CRSF' and plural of word (#8238) 2021-11-08 09:59:32 +00:00
rgermain
00cd4ef864
add third packages nested-multipart-parser (#8208) 2021-10-15 15:13:20 +01:00
Uzair Ali
ddc5cd7e4b
Imported Response (#8207) 2021-10-07 15:52:44 +01:00
Edmund
53a0585dac
Update permissions.md to fix garden path sentences (#8206) 2021-10-07 09:09:00 +01:00
thetarby
6ea95b6ad1
Highlight select_related and prefetch_related usage in documentation (#7610)
* docs updated to highlight use of select_related and prefetch related to avoid n+1 problems

* Apply suggestions from code review

cosmetic changes

Co-authored-by: Xavier Ordoquy <xordoquy@linovia.com>

* cosmetic changes

Co-authored-by: Xavier Ordoquy <xordoquy@linovia.com>
2021-10-05 15:33:55 +01:00
Phil Leggetter
605a624da6
Add PostHog as premium sponsors (#8193)
* Add PostHog as premium sponsors

* Adding 275x250 PostHog image
2021-10-05 14:02:34 +01:00
Akhil Kokani
1fa5bc31c0
Update serializers.md (#8189)
* Update serializers.md

Removed unwanted word, "neither".

* Update docs/api-guide/serializers.md

Co-authored-by: Tom Christie <tom@tomchristie.com>
2021-09-27 10:01:47 +01:00
Carlton Gibson
c62e3ca764 Added Django 4.0 to test matrix. 2021-09-23 11:57:03 +02:00
Carlton Gibson
f46c33e4e2 Fixed TestDefaultTZDateTimeField to allow multiple tzinfo implementations.
zoneinfo was made the default time zone implementation in
306607d5b9.
2021-09-23 11:57:03 +02:00
Carlton Gibson
19b6091554 Adjusted authentication test for internal CSRF changes.
Private _get_new_csrf_token() was removed in
231de683d8.
2021-09-23 11:57:03 +02:00
Carlton Gibson
4916854492 Removed USE_L10N setting from Django 4.0.
USE_L10N defaults to True from Django 4.0, and will be removed in Django 5.0.
2021-09-23 11:57:03 +02:00
Carlton Gibson
2d9eee5d02 Adjusted URLPatternsTestCase to use addClassCleanup() from Django 4.0.
Refs faba5b702a.

addClassCleanup() is available from Python 3.8, which is the minimum supported
Python from Django 4.0.
2021-09-22 10:23:47 +02:00
Carlton Gibson
f651878df3 Adjusted DateTimeField docs for zoneinfo. 2021-09-22 10:23:46 +02:00
Carlton Gibson
250479dc37 Added pytz to install_requires.
pytz will not automatically be installed with Django from v4.0.
2021-09-22 09:57:17 +02:00
Dan Lousqui
f0a5b958a1
Add max_length and min_length options to ListSerializer (#8165) 2021-09-14 13:45:55 +01:00
Tom Christie
761f56ef40 Update stream.io link 2021-09-10 14:45:06 +01:00
Tom Christie
73f3325f80
Update stream.io link (#8161) 2021-09-10 11:32:27 +01:00
Tom Christie
9ce541e909
Revert "Fix arguments (#7995)" (#8156)
This reverts commit 9716b1b6b7.
2021-09-06 12:19:20 +01:00
Ivan Trushin
9716b1b6b7
Fix arguments (#7995)
`path()` has no argument `namespace`, it has `name` argument
2021-09-06 12:18:13 +01:00
Peter Uittenbroek
655e803adf
#7157: Fix RemoteUserAuthentication calling django authenticate with request argument (#7158) 2021-09-03 14:37:03 +01:00
Anthony Randall
96001c5de6
Added an article - implementing rest apis with embedded privacy from doordash engineering blog (#7956)
* Update tutorials-and-resources.md

* Update tutorials-and-resources.md
2021-09-03 13:23:19 +01:00
Juan Benitez
cb206e4701
fix: change View class to Throttle class on SimpleRateThrottle Docstring (#8147) 2021-09-03 13:00:23 +01:00
Ryan Nowakowski
4632b5daae
Fix subtitle of schemas for filtering (#8145)
Fix a likely copy/paste error
2021-08-31 14:18:49 +01:00
Aditya Mitra
6b392a46ea
[FIX] Typo in api-guide/authentication (#8144) 2021-08-31 13:57:02 +01:00
Asif Saif Uddin
88666629a7
stop testing django 3.0 as its EOL (#8136) 2021-08-31 13:56:08 +01:00
jefcolbi
c927053d4b
Replacing django-rest-auth with dj-rest-auth (#8146) 2021-08-31 12:51:47 +01:00
Mark
c5d9144aef
fix typo (#8122)
Co-authored-by: mgold <mgold@iponweb.net>
2021-08-11 11:30:09 +01:00
juliangeissler
cdd53c7de9
Update Tutorial - Relationships & Hyperlinked APIs (#7950)
unnecessary import, because it is already added in the previous section
2021-08-08 14:45:00 +01:00
Ben Hampson
e95e91ccf2
Use correct link for httpie (#8005)
Before it was linking to a fork of a fork of httpie. I've changed it to the right URL.
2021-08-06 16:49:41 +01:00
Thomas Grainger
b824b33dc3
add changelog project_url (#8085) 2021-08-06 16:46:57 +01:00
Paul Wayper
c4404f3d5d
We now use Libera.chat rather than Freenode for IRC (#8049)
Signed-off-by: Paul Wayper <paulway@redhat.com>

Co-authored-by: Tom Christie <tom@tomchristie.com>
2021-08-06 16:46:26 +01:00
Paul Wayper
cba24464e8
Botbot has been acquired, all paths now point to startupresources (#8050)
Signed-off-by: Paul Wayper <paulway@redhat.com>
2021-08-06 16:45:15 +01:00
Ma77heus
2942590ee3
fix: broken cite (#8086)
Co-authored-by: MattheusHenrique <mattheushenrique@gmail.com>
2021-08-06 16:39:58 +01:00
Aarni Koskela
fdb4931475
Make Field constructors keyword-only (#7632) 2021-08-06 10:14:52 +01:00
Nikhil Benesch
b215375125
Propagate nullability in ModelSerializer (#8116)
Propagate the nullability of underlying model fields in ModelSerializer
when those fields are marked as read only. This ensures the correct
generation of OpenAPI schemas.

Fix #8041.
2021-08-06 10:10:58 +01:00
Evgeny Panfilov
98e56e0327
fix empty string as a value for a validated DecimalField (#8064) (#8067) 2021-07-01 15:04:44 +01:00
Nikita Sobolev
d2977cff98
Fixes inconsistent headers in serializer docs (#8056)
Some headers were using `.`, some - were not.
Now, all of them are the same with `.`, because it was easier to fix.
2021-06-28 13:07:41 +01:00
Burak Kadir Er
c8a9c856c2
fix a small typo (#8060) 2021-06-28 12:51:21 +01:00
Adam Johnson
e92016ac2e
Stop ignoring test outcome for Django 3.2 (#7927) 2021-06-21 11:33:43 +01:00
Finn Gundlach
24a938abaa
Update documentation to include Django 3.2 as supported version (#8037) 2021-06-16 14:53:29 +01:00
Ian De Bie
61e7a993bd
fix comments by using correct css comment syntax (#8019)
these intended comments were causing errors in sonarqube scans due to using wrong css comment syntax
2021-06-07 10:30:23 +01:00
Abduaziz
9d149f2317
Fixed some punctuation marks & small typos (#8015) 2021-06-02 10:02:11 +01:00
Mariusz Felisiak
bc075212cb
Fix running runtests.py without arguments. (#7954)
Regression in aa12a5f967.
2021-05-24 09:47:44 +02:00
Ishu Kumar
3875d3284e
Punctuations and missing "to" preposition (#7966)
Changes made in lines 221, 222, 223, and 224 for better readability.
2021-05-10 12:26:26 +01:00
Julien Palard
a0083f7f98
FIX: Broken cite. (#7951) 2021-04-26 09:30:41 +01:00
Łukasz Skarżyński
431f7dfa3d
fix typo in packaging requirements (#7949) 2021-04-23 09:34:58 +01:00
Denis Orehovsky
8812394ed8
Add distinction between request and response serializers for OpenAPI (#7424)
* Add distinction between request and response serializers

* Add docs

* document new functions in schemas.md

* add a test case for different request vs response objects

* Correct formatting for flake8

Co-authored-by: Shaun Gosse <shaun.gosse@emburse.com>
2021-04-20 15:03:16 +01:00
Adam Johnson
010c8d4f08
Use tox-py in CI (#7925) 2021-04-16 17:59:27 +01:00
Adam Johnson
67b5093ca5
Fix pytest warnings (#7928)
* Use `--strict-markers` instead of `--strict`, as per this warning:

  ```
  /.../_pytest/config/__init__.py:1183: PytestDeprecationWarning: The --strict option is deprecated, use --strict-markers instead.
  ```

* Remove config option 'testspath' - pytest is logging a warning about this being unknown:

  ```
  /.../_pytest/config/__init__.py:1233: PytestConfigWarning: Unknown config option: testspath
  ```

  I can't find any reference to it in the pytest docs or changelog.
2021-04-16 17:47:21 +01:00
Terence Honles
a0a2c5cb37
Fix tests with mock timezone (#7911)
After django/django#13877, Django no longer checks for `hasattr(timezone, 'localize')` and instead does an inheritance check.
2021-04-16 17:27:22 +01:00
Adam Johnson
f628db383a
Fix GitHub Actions to run on 'master' branch (#7926)
The config I copied in #7903 was from a repo with the new name 'main', so tests have not been running on master since.
2021-04-16 17:23:18 +01:00
Terence Honles
1c494e3d94
Update references to Travis CI after moving to Github Actions (#7909)
x-ref: https://github.com/encode/django-rest-framework/pull/7903
2021-04-12 13:14:26 +01:00
Lalit Suthar
9bdd6125a1
fix broken article link (#7918)
Co-authored-by: lalit97 <lalit.suthar@redhuntlabs.com>
2021-04-12 11:59:58 +01:00
Adam Johnson
fd017d00f9
Move CI to GitHub Actions (#7903)
* Recreate all the jobs on GitHub Actions
* Upgrade to Ubuntu 20.04
* Upgrade base/docs/dist to Python 3.9
2021-04-06 18:34:18 +01:00
Adam Johnson
90635c138f
Update pre-commit for flake8 move (#7907)
See: https://twitter.com/codewithanthony/status/1378746934928699396
2021-04-06 17:49:17 +01:00
Adam Johnson
37ef62b0e6
Remove link to third party cookiecutter template (#7902)
The template has not been maintained for six years, so it's out of date on versions and various "best practices" (e.g. pre-commit). I also think any template should be documented on its own repo rather than here, especially if it's not an official maintained project.
2021-04-05 18:18:35 +01:00
Adam Johnson
aa12a5f967
Lint with pre-commit (#7900)
Following [my comment here](https://github.com/encode/django-rest-framework/pull/7589#issuecomment-813301322) and [Django's own move to pre-commit](https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/#pre-commit-checks).

* Add pre-commit config file to run flake8 and isort.
* Add extra "common sense" hooks.
* Run pre-commit on GitHub actions using the [official action](https://github.com/pre-commit/action/). This is a good way to get up-and-running but it would be better if we activated [pre-commit.ci](https://pre-commit.ci/), which is faster and will auto-update the hooks for us going forwards.
* Remove `runtests.py` code for running linting tools.
* Remove `runtests.py --fast` flag, since that would now just run `pytest -q`, which can be done with `runtests.py -q` instead.
* Remove tox configuration and requirements files for linting.
* Update the contributing guide to mention setting up pre-commit.
2021-04-05 12:08:52 +01:00
Adam Johnson
846fe70cff
De-duplicate contributing guide (#7901)
The contributing guide from `docs/community/contributing.md` was copy-pasted to `CONTRIBUTING.md` and the two have drifted apart over time. The docs page seems to have been updated a bit more so let's leave only that version.
2021-04-05 11:12:28 +01:00
David Smith
d82519bf8a
Updated dependencies (#7589) 2021-04-05 10:28:03 +01:00
dependabot[bot]
78da1a824f
Bump pygments from 2.4.2 to 2.7.4 in /requirements (#7886)
Bumps [pygments](https://github.com/pygments/pygments) from 2.4.2 to 2.7.4.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.4.2...2.7.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-04-01 16:52:19 +01:00
Tom Christie
406e6a2f35
Update MANIFEST.in (#7893) 2021-04-01 14:15:53 +01:00
David Smith
96885dd9a7
Fixed markdown test (#7892)
The pygments rendering of invalid json changed in  pygments>=2.7.3
2021-04-01 09:49:47 +01:00
Tom Christie
0323d6f895
Linting fixes (#7874)
* Fixed code quality issues

- Added '.deepsource.toml' file for continuous analysis on bug risk

- Remove `return` from `__init__()` method

- Remove duplicate dictionary key(s)

- Use `max` built-in to get the maximum of two values

- Remove redundant `None` default

- Remove unnecessary comprehension

Signed-off-by: ankitdobhal <dobhal.ankit@protonmail.com>

* Delete .deepsource.toml

* Delete test_fields.py

* Reintroduce file from accidental deletion

Co-authored-by: ankitdobhal <dobhal.ankit@protonmail.com>
2021-03-26 12:27:10 +00:00
Tom Christie
f83620dcc9
Version 3.12.4 (#7873)
* Version 3.12.4

* Tweak release notes
2021-03-26 09:27:01 +00:00
Tom Christie
72c155d8f4
Revert "pick deque instead of list (#7849)" (#7872)
This reverts commit ebcb8d5310.
2021-03-26 09:17:47 +00:00
Tom Christie
dffa612134
Fix release notes typo 2021-03-25 12:30:45 +00:00
Tom Christie
83ad265e13
Version 3.12.3 (#7866) 2021-03-25 12:23:23 +00:00
Jack
ebcb8d5310
pick deque instead of list (#7849)
Co-authored-by: Jack Zhang <jack.zhang@aspiraconnect.com>
2021-03-25 10:47:44 +00:00
Joe Michelini
71e6c30034
update SerializerMethodField example in docs (#7858)
* update SerializerMethodField example

* fix formatting
2021-03-22 12:08:19 +00:00
Mohammad Ashraful Islam
7e3dd9cd1b
Added fast-drf as a thirdparty package for making API development faster. (#7857) 2021-03-22 12:07:48 +00:00
Hasan Talha Yazıcı
0cddf097ca
Fix typo in docs (#7853) 2021-03-21 09:53:09 +00:00
Anton Zaslavskiy
b25ac6c5e3
Don't hit db to access user_id in TokenProxy (#7852) 2021-03-19 11:46:09 +00:00
Aristotelis Mikropoulos
67ebdd32cd
Reject PrimaryKeyRelatedField bool lookup values (#7597)
* Reject PrimaryKeyRelatedField bool lookup values

* Test PrimaryKeyRelatedField bool lookup rejection

* Fix indentation in test
2021-03-17 13:28:38 +00:00
Tom Christie
7b53960c3b
Revert "made Browsable API base template cachable: omit CSRF token when unnecessary (#7717)" (#7847)
This reverts commit 9c9ffb18f4.
2021-03-17 13:24:55 +00:00
Tom Christie
3e274146fc
Fix WSGI signature for DjangoTestAdapter (#7846)
Closes https://github.com/encode/django-rest-framework/issues/7132
2021-03-17 13:24:38 +00:00
Yuekui
a40bce50cd
No need to explictitly set None as default (#7373) 2021-03-16 13:29:13 +00:00
Jesse London
9c9ffb18f4
made Browsable API base template cachable: omit CSRF token when unnecessary (#7717)
HTML responses generated by the Browsable API otherwise generate
inconsistent ETAGs -- due to the presence of CSRF tokens in the response
-- even when the API is read-only, (and as such when the response
contains no resource-modifying forms, i.e. neither POST nor PUT forms,
which might require the CSRF token).

While the template was appropriately including CSRF tokens only within
POST and PUT forms, its AJAX overlay included the CSRF token in *every*
response, regardless of whether it would be needed.

This change brings the logic of the `script` block into line with that
of the rest of the template -- and such that read-only APIs (and really
the Browsable API pages of *any* read-only resources) will not
needlessly include the CSRF token, and will now be safely cachable -- by
both back-end systems and by the user agent.
2021-03-16 13:25:21 +00:00
Jeff Baumes
b0ca248d88
Correct the use of "to" (#7696) 2021-03-16 12:57:04 +00:00
Ömer Faruk Abacı
ce1568322a
Ordering filter bug with model property serializer field (#7609)
* Add failing tests for ordering filter with model property

* Fix get_default_valid_fields of OrderingFilter

* Filter model properties in get_default_valid_fields of OrderingFilter
2021-03-16 12:53:39 +00:00
Alex Hedlund
b256c46cb1
Render JSON fields with proper indentation in browsable API forms. (#6243)
* Fix JSONBoundField usage on nested serializers (#6211)

* Unify JSONBoundField as_form_field output between py2 and py3

When using json.dumps with indenting, in python2 the default formatting
prints whitespace after commas (,) and python3 does not. This can be
unified with the separators keyword argument.
2021-03-15 10:44:03 +00:00
Henryk Plötz
ff625ecff5
Document object level permissions gotchas (#7446)
* Document the limitation that object level permissions do not apply to object creation. See for example #6409.

* Add overview of three different ways to restrict access
2021-03-15 10:28:45 +00:00
Ömer Faruk Abacı
883f6fe814
Rename django-extra-fields to drf-extra-fields (#7833) 2021-03-11 11:39:06 +00:00
Carlton Gibson
f070619061
Updated tox/travis to point to Django main branch. (#7827) 2021-03-11 10:26:11 +00:00
Tom Christie
39a98c80a6 Fix 'get_page_number' implementation 2021-03-11 09:21:22 +00:00
Tom Christie
c05cbe2da2
Update pagination.py
Include `last_page_strings` logic *inside* the `get_page_number method.
2021-03-10 12:50:59 +00:00
Max Morlocke
ffe11d41bd
upgrade pytest+pytest-django to eliminate dependencies on six (#7672)
* upgrade to latest version of pytest+pytest-django to eliminate dependency on six

* rollback pytest to 6.1 as py35 is dropped in 6.2

Co-authored-by: Tom Christie <tom@tomchristie.com>
2021-03-10 12:45:47 +00:00
Feanil Patel
c78f992176
Make the doc on overriding the default permission classes more clear. (#7661) 2021-03-10 12:44:17 +00:00
Eshaan Bansal
4f3cd8c7b0
add django-rest-durin to 3rd party auth libs [docs] (#7615)
Co-authored-by: Tom Christie <tom@tomchristie.com>
2021-03-10 12:40:45 +00:00
John Alexis Munera
cef74d1726
Add rest-framework-actions to Third Party Packages (#7688)
This pull request adds rest-framework-actions to Third Party Packages, under Views

rest-framework-actions can be found on PyPi here: https://pypi.org/project/rest-framework-actions/

Co-authored-by: Tom Christie <tom@tomchristie.com>
2021-03-10 12:37:06 +00:00
sarath ak
6f6d402d04
Allow 'get_page' method for overriding #7626 (#7652) 2021-03-10 12:32:10 +00:00
Pierre Chiquet
c603b98403
Fix OpenAPISchema rendering for timedelta (#7641)
* Add failing test when rendering to json a schema with timedelta

* Fix JSONOpenAPIRenderer for fields with default=timedelta()

* fix isort

* fix test for python 3.5

Co-authored-by: Pierre Chiquet <pierre.chiquet@ubikey.fr>
2021-03-10 12:03:15 +00:00
PaulGilmartin
c69e2e4eaa
Add graphwrap to third-party-packages.md (#7819)
* Add graphwrap to third-party-packages documentation

* Fix typo in third party packages docs

* Remove additional newline

Co-authored-by: Paul Gilmartin <paulgilmartin@Pauls-MacBook-Pro.local>
Co-authored-by: Tom Christie <tom@tomchristie.com>
2021-03-10 09:02:38 +00:00
Dmitry Mugtasimov
a3ae8ea77e
Do not do SELECT count(*) FROM ... if pagination is not requested (#6098)
* Do not do `SELECT count(*) FROM ...` if pagination is not requested

* Update pagination.py

Co-authored-by: Tom Christie <tom@tomchristie.com>
2021-03-09 12:06:12 +00:00
Romain Rigaux
750bad0a58
Actually use the loginUser arguments in the example (#7714) 2021-03-09 12:00:51 +00:00
Vitor Hugo
4e0d6c4118
Update default.css (#7643)
When I apply a theme to the bootstrap used in the project, boolean inputs are out of line with the rest of the form. With this small payment, this no longer occurs.
2021-03-09 11:54:58 +00:00
Celia Oakley
747fef6134
Add django-rest-authemail to Third Party Packages (#7679)
* Add django-rest-authemail to Authentication

* Add django-rest-authemail to Third Party Packages
2021-03-09 11:51:52 +00:00
Chris Guo
82b8a64a02
docs: add example for caching (#7118) 2021-03-09 11:49:19 +00:00
Berkant
95ae92ef23
Fix #7706 (#7724)
Handle non-dict values for NestedSerializer during BrowsableAPI
rendering.
2021-03-09 11:34:18 +00:00
David Kerkeslager
05512160ab
Respect allow_null=True on DecimalFields (#7718)
* Handle None in to_representation()
* Return None as '' in to_representation() when coerce_to_string=True
* Handle '' as None in to_internal_value(), for symmetry with
  to_representation(), and because the empty concept doesn't make sense
  for Decimal.
2021-03-09 10:49:03 +00:00
Nathan Glover
a89a6427d3
#7703 adding deprecations to release notes (#7716)
* #7703 adding deprecations to release notes

* #7703 - update link for gh6687
2021-03-09 10:22:37 +00:00
Cas Ebbers
393f867995
Overlooked translation in search.html (#7551) 2021-03-09 10:21:11 +00:00
kuter
e9a54e38e1
add support for Yes/No literals with BooleanField (#7701) 2021-03-09 10:17:30 +00:00
Igor Polyakov
b463878132
Commas added in README (#7730)
To make it more comfortable for users to copy and paste snippets
2021-03-09 10:16:19 +00:00
Alex Cotsarelis
e32ebc4199
Docs: DjangoModelPermissions works on views with get_queryset() method. (#7693)
Sentinel querysets not needed after v3.1.2
2021-03-08 12:09:17 +00:00
Jean-Pierre Merx
234527959d
Have options example in documenting-your-api.md to return a Response (#7639)
It was returning data which is not correct. Closes #7638.

Co-authored-by: Jean-Pierre Merx <jean-pierre.merx@aictivate.com>
2021-03-08 12:08:26 +00:00
arcanemachine
ef112f5017
Provide example for dict in ValidationError detail (#7788)
Added a sentence describing the use of a dictionary as the `detail` argument of a ValidationError, and how it can be used to add field-level errors during object-level validation.
2021-03-08 11:46:35 +00:00
Tom Christie
ec29ff8a80
Delete ISSUE_TEMPLATE.md 2021-03-03 15:45:40 +00:00
Tom Christie
ee51145574
Update config.yml 2021-03-03 15:43:57 +00:00
Tom Christie
37b8d2018d
Create 1-issue.md 2021-03-03 15:42:38 +00:00
Tom Christie
db0bb5ef42
Update config.yml 2021-03-03 15:39:22 +00:00
Tom Christie
c9a00bdb2c
Update config.yml 2021-03-03 15:33:14 +00:00
Tom Christie
344235ab37
Create config.yml 2021-03-03 15:32:19 +00:00
Tom Christie
1deb8ae370
Update FUNDING.yml 2021-03-03 15:06:42 +00:00
Jonathan Mortensen
de7468d0b4
support multi db atomic_requests (#7739) 2021-03-03 11:15:39 +00:00
Usoof Mansoor
8f6d2d2f9c
Update docs link to Django OAuth Toolkit. (#7737) 2021-03-02 08:26:31 +01:00
Asif Saif Uddin
1ec0f86b58
Dj32 (#7713)
adds django 3.2 line to the build matrix
2021-02-16 13:17:29 +01:00
Tonye Jack
3e956df6eb Fixed test 2021-02-16 11:28:38 +01:00
Sebastian Jordan
19655edbf7
Handle tuples same as lists in ValidationError detail context (#7647) 2021-01-06 13:13:34 +00:00
Adrian Coveney
3db8877889 Clarify documentation for TemplateHTMLRenderer
Clarify that the response from a view may need to be modified to provide TemplateHTMLRenderer with a dict for it to use.
2020-12-30 09:11:38 +01:00
Tom Christie
8351747d98
Update index.md 2020-12-21 16:41:12 +00:00
Erwin Junge
bb133522ef Small documentation fix 2020-11-22 12:21:30 +01:00
babaroga
3ab8d4706e changed unicode to str 2020-11-21 18:25:55 +01:00
Karol Onyśko
96993d817a
Changed url to django docs so it points to the stable version (#7628)
Co-authored-by: Karol Onyśko <karol.onysko@cic.com>
2020-11-12 18:42:42 +01:00
Xavier Ordoquy
2b266897c9
Merge pull request #7634 from ge0rg/parser-docs
docs: outline the difference between JSON and form parsers. Fix #7633
2020-11-12 11:52:21 +01:00
Georg Lukas
6da94e5700 docs: outline the difference between JSON and form parsers. Fix #7633 2020-11-12 09:48:18 +01:00
Xavier Ordoquy
3578683a69
Merge pull request #7593 from encode/version-3.12.2
Version 3.12.2
2020-11-05 23:15:45 +01:00
bhealy-indeed
80444a0afb
nit: Typo fix (#7629) 2020-11-05 22:21:30 +01:00
Megan Gross
606df83885
Update throttling.md (#7606)
There were recent updates to the `@action` decorator calling a little more attention to the kwargs it accepts. 
I thought it would be useful to also provide an example in the throttling section of how those kwargs can be used to define/override throttle_classes through the action decorator as well.
2020-11-05 09:43:45 +01:00
James S Blachly, MD
56e4508123
Fix #7612 (#7622) 2020-11-02 09:45:43 +01:00
Jon Dufresne
9c29f5013f Use Python 3.9 release in Travis configuration 2020-11-01 20:36:08 +01:00
Xavier Ordoquy
47cfbdac97 Translations updated from transifex and compiled 2020-10-13 22:05:24 +02:00
Xavier Ordoquy
a0115e66d4 restore the transifex configuration
This reverts commit 6957aaae85.
2020-10-13 21:30:05 +02:00
David Smith
04e0c2b9ab
Bumped Markdown version to 3.3 (#7590) 2020-10-13 17:27:08 +01:00
Tom Christie
3799633cde Version 3.12.2 2020-10-13 14:17:53 +01:00
Pawel
95f0b0867a
Documentation: improve the action decorator documentation (#7316) (#7380)
* Documentation: improve the action decorator documentation (#7316)
2020-10-13 08:32:38 +02:00
Aarni Koskela
0bdd537cc4
Ignore derivations of BrowsableAPIRenderer in OpenAPI schema (#7497)
* Ignore derivations of BrowsableAPIRenderer in OpenAPI schema
* Improve test_renderer_mapping test

Co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es>
2020-10-12 16:40:26 +02:00
Thomas Leese
eff97efa28
Don't catch exceptions in get_queryset (#7480)
In the `to_internal_value` method of the primary key and slug related fields, `TypeError`s and `ValueError`s are caught from `self.get_queryset().get(...)` and presented to the user. This works fine for most cases, but can cause problems if the exception is coming from `self.get_queryset()` rather than from the `.get(...)`.

It means errors in the `get_queryset` method can be hidden and presented back to the user as though, for example, the input provided to the `to_internal_value` was the wrong type, whereas in reality there's a bug in the `get_queryset` method and therefore it should bubble up and be exposed as a server error.

I've decided to fix this because twice now I've had to debug why I'm seeing `invalid_type` errors from my serializer (errors like `wrong pk type - int` when the `pk` type on my model is `int`) when the real problem was a bug in my custom `get_queryset` method.
2020-10-10 18:02:21 +01:00
Adam Johnson
fd5e1a745a
Fixed some documentation headings to use a space (#7364) 2020-10-10 17:42:59 +01:00
zach valenta
ffde169102
Add docs link to to_internal_value() (#7476) 2020-10-10 17:36:15 +01:00
Thomas Riccardi
1ef192811c
Add missing quoting for data keyword argument in serializer doc (#7587) 2020-10-10 17:34:39 +01:00
Adam Johnson
563b043768
Error on deprecation and pending deprecation warnings (#7586)
Erroring on deprecation or pending deprecation warnings means they are caught early. This will avoid the cycle of releasing with 'support for Django X', then chasing all the deprecation warnings one-by-one. Instead, when a new Django version is added to the test matrix, it will fail until all the relevant warnings are fixed. This avoids passing these warnings on to users, some of whom don't upgrade until they are all fixed.
2020-10-10 17:34:00 +01:00
David Smith
79c37d0dc3
Return NotImplemented sooner for ErrorDetail equality test (#7531)
The test suite raises warnings when tested against Python 3.9
`DeprecationWarning: NotImplemented should not be used in a boolean context`

Where `r` returns `NotImplemented` then this change returns `NotImplemented` first to avoid the comparison test.
2020-10-09 12:21:22 +01:00
Kryštof Pilnáček
79daf315c4
Fix: authtoken.TokenProxy cannot be proxy when not installed (#7571)
closes https://github.com/encode/django-rest-framework/issues/7442
2020-10-09 12:16:15 +01:00
Adam Johnson
931b34e7de
Remove tox-venv from Travis setup (#7585)
This was added in #6139. However it seems [tox-venv is no longer maintained](https://github.com/tox-dev/tox-venv), the related [virtualenv issue has been closed](https://github.com/pypa/virtualenv/issues/355), and I suspect with the virtualenv rewrite fixed the problem with site.py and the warnings referred to for the DRF tests.
2020-10-09 11:09:34 +01:00
Adam Johnson
7921e9af43
Fix RemovedInDjango40Warning for middleware get_resopnse() (#7513)
Fixes #7417.

Fixes all these issues seen with `tox -e py38-django31`:

```
  /Users/chainz/Documents/Projects/django-rest-framework/tests/test_request.py:208: RemovedInDjango40Warning: Passing None for the middleware get_response argument is deprecated.
    SessionMiddleware().process_request(self.wrapped_request)

tests/test_requests_client.py: 1 test with warning
tests/test_testing.py: 4 tests with warnings
tests/test_throttling.py: 1 test with warning
tests/authentication/test_authentication.py: 4 tests with warnings
tests/browsable_api/test_browsable_api.py: 4 tests with warnings
  /Users/chainz/Documents/Projects/django-rest-framework/rest_framework/authentication.py:139: RemovedInDjango40Warning: Passing None for the middleware get_response argument is deprecated.
    check = CSRFCheck()
```
2020-10-09 10:48:03 +01:00
Mopsan
5e23b559f8
Fix example override of SchemaGenerator.get_schema() 2020-10-09 09:38:11 +01:00
Xavier Ordoquy
2e721cdbc8
Merge pull request #7436 from markstory/patch-1
Fix broken links in documenting API section
2020-10-06 22:26:22 +02:00
Xavier Ordoquy
ebc1ebf0c4
Merge pull request #7481 from smithdc1/app-config
default_app_config application variable is deprecated in Django 3.2
2020-10-06 22:16:29 +02:00
Xavier Ordoquy
fdf277a782
Merge pull request #6843 from max-wittig/patch-1
docs(tutorial): add missing permission import in viewsets
2020-10-06 21:42:30 +02:00
स्पर्श
6a45a6a36f
Fix broken machinalis links (#7580)
#7572 #7423 #7573  all are related to this
2020-10-06 13:14:11 +01:00
Xavier Ordoquy
d635bc9c71
Merge pull request #7539 from verhovsky/patch-2
Correct indentation
2020-10-06 13:04:08 +02:00
Xavier Ordoquy
9dc10d2af7
Merge pull request #7577 from Exifers/patch-1
Documentation: use retrieve instead of read for Viewset
2020-10-05 21:54:33 +02:00
Xavier Ordoquy
a849627f88 Fixes #7538 - use retrieve action name instead of detail 2020-10-05 21:48:07 +02:00
Emmanuel Meric de Bellefon
86ec3da2da
Update 6-viewsets-and-routers.md 2020-10-05 20:56:42 +02:00
Adam Johnson
91916a4db1
Fix NullBooleanField warning (#7565)
The argument to Field is 'allow_null'.
2020-09-30 13:47:06 +01:00
Tom Christie
be87eb43b3 Update release notes with 3.11.1, 3.11.2 2020-09-30 09:44:31 +01:00
Tom Christie
a03c85225f
Update test_templatetags.py 2020-09-30 09:10:36 +01:00
Xavier Ordoquy
c7ba30825a
Merge pull request #7559 from AliMirlou/patch-1
Fix typo in release notes
2020-09-29 10:48:51 +02:00
Ali Mirlou
9edd5dfe5d
Fix typo in release notes 2020-09-28 23:15:30 +03:30
Tom Christie
05b3865838 Version 3.12.1 2020-09-28 16:18:23 +01:00
Hugo Rodger-Brown
995188f8c5
Add missing TokenProxy migration (#7557)
Fixes #7554
2020-09-28 16:16:18 +01:00
Tom Christie
68b23075a2
Add date to 3.12 release. 2020-09-28 10:54:52 +01:00
Tom Christie
6f7aad8ffa
Placeholder for 3.12 release (#7379)
* Placeholder for 3.12 release

* Updating release notes

* Updating release notes

* Updating release notes

* Update release notes

* Fix typo

* Basic structure for release announcement

* 3.12 release notes

* Version 3.12.0
2020-09-28 10:47:50 +01:00
Esieboma Jeremiah
9ee67bbff7
corrects typographical error in line 118 (#7553) 2020-09-28 08:52:17 +01:00
Tom Christie
ae649336b1
Drop urlize_quoted_links (#7548) 2020-09-23 15:39:06 +01:00
T. Franzel
c6e24521da
Add third-party schema library drf-spectacular to docs (#7540)
Co-authored-by: T. Franzel <13507857+tfranzel@users.noreply.github.com>
2020-09-21 11:39:35 +01:00
Борис Верховский
98761e4ebb
Correct indentation 2020-09-16 09:43:27 -04:00
johnthagen
e17779c47b
Make it more clear to add django_filters to INSTALLED_APPS in docs. (#7535) 2020-09-14 19:46:51 +02:00
Mohammad Amin Haghpanah
04f39c42ee
Add drf-psq package to docs (#7451)
* Add drf-psq to third party packages

* Add drf-psq to permissions.md

this package is an extension that gives support for having action-based **permission_classes**, **serializer_class**, and **queryset** dependent on permission-based rules.

Co-authored-by: Salar Nasiri <salarnasiri@users.noreply.github.com>
2020-09-09 08:54:05 +01:00
Rafael Henter
327cbef299
Add Django API Client to the third party packages (#7440) 2020-09-08 15:44:03 +01:00
Francisco Couzo
6b632c15b1
Remove unnecessary type conversions (#7526) 2020-09-08 15:42:01 +01:00
Michael K
ddcd8b539b
Run tests against Python 3.9 (#7517)
3.9.0 final is expected on Monday, 2020-10-05
See https://www.python.org/dev/peps/pep-0596/#schedule

Also mention Django 3.1 compat where missing.
2020-09-08 15:40:21 +01:00
Adam Johnson
410575dace
Replace all url() calls with path() or re_path() (#7512)
* url() is deprecated in Django 3.1

* update given feedbacks on url() is deprecated in Django 3.1

* Fix test_urlpatterns.py to continue testing mixed re_path() and path()

* Fix one missed reference

Co-authored-by: sanjusci <sanju.sci9@gmail.com>
2020-09-08 15:32:27 +01:00
David Smith
9990b59281
Dropped test compatibility shims for Django <2.2. (#7523) 2020-09-07 20:00:17 +02:00
David Smith
d5461e93fe
Bump flake8 to 3.8.3 (#7521) 2020-09-05 10:02:27 +02:00
David Smith
b8ab30683a default_app_config application variable is deprecated in Django 3.2 2020-09-03 21:57:41 +01:00
Charles
35c0abf24e
Change Token.generate_key to a Classmethod (#7502)
* adds classmethod decorator to generate_key and test to confirm change is acceptable

* self -> cls
2020-09-03 11:51:03 +01:00
Ryan P Kilby
f323049ecc
Fix pk-only optimization for properties (#7142)
* Add callable/prop tests for pk-only optimization

* Fix related field pk-only optimization for props
2020-09-03 11:49:15 +01:00
Bob Thomas
b3e02592d0
Add support for Django 3.1 JSONField (#7467)
Django 3.1 adds a new generic JSONField to replace the PostgreSQL-specific one. This adds support for the new field type, which should behave the same as the existing PostgreSQL field.

Django's new JSONField also includes support for a custom "decoder", so add support for that in the serializer field.
2020-09-03 11:47:11 +01:00
johnthagen
7f3a3557a0
Add drf_ujson2 reference (#7494) 2020-08-25 15:15:17 -07:00
Vlad
e215db206a
Updated url()'s with path() and re_path() (#7492) 2020-08-25 13:50:02 +02:00
Justin Duke
48c327c681
Fix schema typo (#7491) 2020-08-24 03:44:34 -07:00
Борис Верховский
374c0d4142
Punctuation fix (#7488)
* Punctuation fix

* more punctuation
2020-08-20 13:23:59 +01:00
David Smith
355afcf64b
isort v5 (#7484) 2020-08-17 13:26:56 -07:00
Vibhu Agarwal
3d708ac700
Fix broken docs link (#7473) 2020-08-11 16:36:23 -07:00
Ryan P Kilby
1e383f103a
Check extra action func.__name__ (#7098) 2020-08-05 21:29:47 -07:00
Michael K
0d2bbd3177
Fix Request docstring kwarg names (#7443) 2020-08-05 16:51:06 -07:00
Masked Man
17f2b39bdb
Fix docs issue (#7418) 2020-08-05 15:33:30 -07:00
Tom Christie
7d5155e0eb
Resize sponsor images for new GitHub layout (#7465) 2020-08-05 14:13:01 +01:00
Paul Watts
559088463b
Update an example to not use oppressive language (#7439)
* Update an example to use less oppressive language

For reference: https://tools.ietf.org/id/draft-knodel-terminology-00.html

* Code review update

Blocklisted -> blocked.
2020-07-29 20:21:13 +01:00
Mark Story
30ca04df83
Fix broken links in documenting API section
The changed links were not working on the documentation site. I'm not 100% sure that these changes are correct but they generate working links in the GitHub previews.
2020-07-29 09:58:53 -04:00
Tom Christie
c252c3dfa5
Update sponsors (#7434)
* Adjusted token admin to map to user ID.

Closes #6131.

* Adds a proxy model for Token that uses the user.pk, rather than it's own.
* Adjusts Admin to map back from User ID to token instance.

* Update sponsors

Co-authored-by: Carlton Gibson <carlton.gibson@noumenal.es>
2020-07-29 14:55:10 +01:00
John Vandenberg
599e2b183d
urlpatterns: Remove unnecessary branching (#7405)
Functions path and register_converter are constants.
2020-07-23 19:26:35 +02:00
Anirudh Bagri
1e164c5eeb
Just smalling cleaning up, causing confusion (#7426) 2020-07-23 17:34:34 +02:00
Mariusz Felisiak
4b06e0a5a1
Fix tests crash on SQLite without JSON1 extension. (#7409) 2020-07-12 11:08:40 +02:00
Anton Agestam
76232437d4
Allow type checkers to make serializers generic (#7385) 2020-07-07 10:05:36 +01:00
Minjae Kim
d46d5cbaaa
Not include charset when charset is None (#7400) 2020-07-07 09:58:32 +01:00
Oğuzhan Çelikarslan
36bd1b30d8
drf-encrypt-content added into third party list in documentation's serializer page (#7398) 2020-07-06 11:56:46 +01:00
Xavier Ordoquy
28983cb28b
Merge pull request #7290 from encode/xordoquy/fix_action_namespace
Fix viewsets action urls with namespaces (#7287)
2020-07-03 20:18:18 +02:00
Dhaval Mehta
5ce237e004
Corrected regex serialization for OpenAPI. (#7389)
* replace \Z by \z in regex

* fix test cases for Django >= 3.0

* fix isort

* Added comment for why `\z`.

Co-authored-by: Carlton Gibson <carlton@noumenal.es>
2020-06-28 14:28:59 +02:00
Ngô Thanh Lợi (Leonn)
19915d1917
Fix docs typo (#7387) 2020-06-22 14:24:50 -07:00
w
7a04269209
Fixed docs typo (#7382) 2020-06-19 10:29:41 -07:00
Carlton Gibson
e18e40d6ae
Updated Schema docs. (#7268) 2020-06-16 13:33:48 +02:00
Carlton Gibson
e2bd3b6a57
Adjusted token admin to map to user ID. (#7341)
Closes #6131.

* Adds a proxy model for Token that uses the user.pk, rather than it's own.
* Adjusts Admin to map back from User ID to token instance.
2020-06-15 11:43:09 +01:00
Rignon Noël
b677b7b15d
Update link to dry-rest-permissions (#7374)
dry-rest-permissions was no maintain since 2018, so FJNR-inc just got a new PyPi version on their fork
2020-06-11 18:33:04 +01:00
Nikhil Kumar
9dc7021770
Fixed h4 rendering 2020-06-01 14:03:10 -04:00
Nikhil Kumar
505a69cf43
Fixed heading markdown 2020-06-01 13:49:43 -04:00
Asif Saif Uddin
acbd9d8222
django 3.1 alpha on matrix (#7334)
* django 3.1 alpha on matrix

* django 3.1 alpha on matrix
2020-05-15 08:40:47 +01:00
Jair Henrique
bb795674f8
Drop all compat support to Django < 2 urls (#7337) 2020-05-14 20:31:38 +02:00
Jair Henrique
65add6679d
Remove unnecessary test skips (#7336) 2020-05-14 14:49:04 +01:00
Jair Henrique
b83e9121f3
Remove compat urls for Django < 2.0 (#7335) 2020-05-14 14:48:14 +01:00
Jair Henrique
aed74961ba
Remove compat for ProhibitNullCharactersValidator (#7333) 2020-05-14 08:24:09 +01:00
johnthagen
fccfdd21c0
Remove object inheritance in docs (#7332) 2020-05-13 17:54:46 -07:00
Carlton Gibson
8bb9a37f4b
Removed duplicated class RemovedInDRF314Warning.
Added accidently in e888fc11c7

Co-authored-by: Jair Henrique <jair.henrique@gmail.com>
2020-05-13 20:41:53 +02:00
Kevin Brown
e888fc11c7
Merge NullBooleanField with BooleanField(allow_null=True) (#7122)
* Make `NullBooleanField` subclass `BooleanField`

This removes a lot of the redundancy that was in place becuase we
were not doing this. This maintains the `None` initial value that
was previously present, as well as disallowing `allow_null` to be
passed in.

* Remove special case for mapping `NullBooleanField`

In newer versions of Django, the `NullBooleanField` is handled the
same way as a `BooleanField(null=True)`. Given that we also support
that combination, and that our own `NullBooleanField` behaves in the
same manner, it makes sense to remove the special casing that exists
for it.

* Add test for BooleanField(null=True, choices)

* Remove special case for NullBooleanField

* Adjust mapping tests for NullBooleanField

* Fixed linting error

* Raise deprecation warning when NullBooleanField is used

* Fix linting issue in imports
2020-05-13 14:59:04 +01:00
Ryan P Kilby
089162e6e3
Fix ModelSerializer unique_together handling for field sources (#7143)
* Fix ModelSerializer unique_together field sources

Updates ModelSerializer to check for serializer fields that map to the
model field sources in the unique_together lists.

* Ensure field name ordering consistency
2020-05-13 11:11:26 +01:00
Derek
00e6079e94
Nginx basic auth tutorial moved (#7324) 2020-05-11 16:29:31 +01:00
Asif Saif Uddin
1260ed424a
jquery 3.5.1 (#7313)
* jquery 3.5.1
2020-05-11 13:08:40 +01:00
Kamil Sampolski
f07f48a5da
Updating documentation / switching from url to path (#7237)
* Update README.md

We should use path instead of url in urlpatterns,

* Update index.md

We should use path instead of url in urlpatterns

* Update README.md

We should use path instead of url in urlpatterns
2020-05-11 11:01:00 +01:00
Ryan P Kilby
8a38991d6a
Fix SearchFilter.must_call_distinict for annotation+m2m (#7146)
* Test SearchFilter annotation+m2m distinct

* Fix SearchFilter annotation+m2m distinct
2020-05-11 10:55:39 +01:00
Daniil Okhlopkov
4ac0fae75b
use @admin decorator (#7022) 2020-05-11 09:04:37 +01:00
Asif Saif Uddin
56ff382b17
updated required versions of dependencies (#7312) 2020-05-05 14:05:29 +01:00
Sardorbek Imomaliev
46be2ffd34
Fix schema endpoint example (#7178)
* Fix schema endpoint example

Endpoint `schema` collides with `schema` class variable `schema` which is use for specification generation

* Update metadata.md

Co-authored-by: Tom Christie <tom@tomchristie.com>
2020-05-05 14:04:35 +01:00
Xavier Ordoquy
5b388e8f83
Merge pull request #7307 from santos22/docs
Update index.md
2020-05-02 12:23:42 +02:00
Santos Solorzano
256f076df2
Update index.md
- Dropped Django 1.11, 2.0, 2.1 support
2020-05-01 14:16:18 -07:00
Mathieu Pillard
d7777ea10f
Pass custom code to PermissionDenied if permission class had one set (#7306) 2020-05-01 10:22:36 +01:00
ADimeo
4349ce1a54
Fix broken documentation link (#7305) 2020-04-30 13:14:27 +01:00
Ryan P Kilby
900773ad06
Minor test improvements (#7297)
* Pass data via response instead of renderer_context

Instead of relying on internal implementation details to get a reference
to the response or view, attach these directly to the returned response.

* Remove unused method
2020-04-29 11:21:42 +01:00
Rick van Hattem
5828d8f7ca
Changed hardcoded /tmp/ directory to autodetect from system (#7292) 2020-04-29 11:20:02 +01:00
Ryan P Kilby
e275b9036a
Allow context to be provided to get_serializer (#7298)
* Test generics serializer behavior

* Allow context to be provided to get_serializer
2020-04-29 11:19:44 +01:00
Robert Singer
05a59095ce
Adds drf-typed-views to 3rd party packages (#7293) 2020-04-27 12:12:13 -07:00
Xavier Ordoquy
bda84372d4 Fix viewsets action urls with namespaces (#7287)
Use the current request's namespace to resolve action urls.
2020-04-25 19:50:59 +02:00
Victor Mireyev
3eef5f47f3
Fix typo in links (#7289)
Reference-style link should be enclosed in square brackets. Otherwise it is treated as an inline-style link.
2020-04-24 22:38:01 -04:00
Victor Mireyev
26cd52a461
Fix markdown lists formatting. (#7288) 2020-04-24 15:17:35 +01:00
Dhaval Mehta
e1336387d1
Added example for pagination in schemas. (#7275) 2020-04-24 16:13:13 +02:00
Matthaus Woolard
812f254bbd
SearchFilter to support JSONField and HStoreField (#7121)
* SearchFilter to support Custom query Transforms

Since Some fields support `__` as a custom Transform for query lookups we needed to update the m2m checking code to handle search_fields that contain __ that are not relationships.

* Update documentation on SearchFilter to include references to JSON and HStore Fields.
2020-04-23 09:38:14 +01:00
spollard
13c08370e7
Remove a few submenu scroll bars on docs site (#7283)
Remove the scroll bars for the "Topics" and "Tutorial" submenus on the website. Previously, unnecessary scroll bars appeared in Firefox and Chrome. Applying this change allows "Community" and "API Guide" submenues to still have scroll bars as necessary.
2020-04-23 09:36:46 +01:00
Byron Peebles
676aa77223
Fix punctuation in system check (#7281) 2020-04-20 16:40:05 -07:00
Tasawar Hussain
8cba4f87ca
Updates Ruby on Rails reference link (#7269)
The cited sentences are from actually the action controller docs from ruby on rails
2020-04-13 03:58:51 +01:00
Carlton Gibson
b2497fc245 Convert openapi.AutoSchema methods to public API. 2020-04-09 20:05:16 +02:00
Carlton Gibson
d45e0005f3 Updated deprecation warnings for 3.12 2020-04-09 20:05:16 +02:00
Carlton Gibson
b1bfff4f1c Revert "Schemas: Improved decimal handling when mapping ChoiceField. (#7264)"
This reverts commit 1872bde462.
2020-04-09 19:35:46 +02:00
Dhaval Mehta
1872bde462
Schemas: Improved decimal handling when mapping ChoiceField. (#7264) 2020-04-09 19:18:00 +02:00
Clinton Blackburn
603aac7db1
Corrected OpenAPI schema type for DecimalField (#7254) 2020-04-09 19:16:17 +02:00
Dhaval Mehta
41f27c3b43
Schemas: Don't generate component for DELETE method. (#7229) 2020-04-09 19:10:50 +02:00
François Freitag
e6c1afbcf9
Tighten checks for invalid field name in ordering (#7259)
Django master removed the ORDER_PATTERN regex with commit
513948735b
2020-04-07 12:28:09 +02:00
tsurutan
0c8eb91737
Fixed docs' custom render example. (#7171) 2020-04-06 17:09:23 +02:00
Rotzbua
a7a362813b
Update optional dependencies list. (#7243)
Co-authored-by: Ryan P Kilby <kilbyr@gmail.com>
2020-04-06 15:54:30 +02:00
David Szotten
734c534dbb
update release note to include full message (#7251)
the truncation changes the meaning somewhat..
2020-03-31 14:53:33 +01:00
Ryan P Kilby
dd33ebb4e2
Add Request repr (#7239) 2020-03-29 12:01:14 +01:00
Rotzbua
57e7cc21e1
Remove unavailable script (#7244) 2020-03-24 11:52:17 -07:00
Artur Barseghyan
5cc6ace9c4
Update third-party-packages.md (#7175) 2020-03-20 11:28:51 -07:00
Mahmoud Adel
8b5d3437f9
Add django-rest-auth fork to docs (#7227) 2020-03-17 15:45:45 -07:00
0dysseas
be96939ec1
Fix serializer example in docs (#7233) 2020-03-17 09:49:19 -07:00
Ryan P Kilby
86aa549832
Drop Django 2.1 and below. (#7225) 2020-03-11 14:51:42 +01:00
Ryan P Kilby
908f91d8ef
Set action for HEAD requests (#7223)
* Test viewset action attr

* Add 'head' to viewset actions map
2020-03-09 09:43:02 +00:00
Tom Christie
4a98533746
Fix - run test_head_request_against_viewset method (#7219) 2020-03-05 13:18:48 +00:00
Tom Christie
73f7bf4941
Extra action detection is too permissive. Add failing test + fix (#7217)
* Add failing test

* Add failing test++

* Make get_extra_action less permissive
2020-03-05 10:18:22 +00:00
Tom Christie
ddfb9672ae
Release notes for 3.11.0 (#7214) 2020-03-04 13:31:43 +00:00
Martin Desrumaux
6a23fa0649
OpenAPI: Make operationId camelCase, matching spec examples. (#7208) 2020-03-03 17:51:51 +01:00
Martin Desrumaux
609f708a27
Fix schema generation for ObtainAuthToken view. (#7211) 2020-03-03 13:27:34 +01:00
Martin Desrumaux
8aa8be7653
Implement OpenAPI Components (#7124) 2020-03-02 19:35:27 +01:00
Martin Desrumaux
797518af6d
OpenAPI: Warn user about duplicate operationIds. (#7207) 2020-03-02 16:44:06 +01:00
Martin Desrumaux
5b16a17242
OpenAPI: Allow customizing operation name. (#7190) 2020-03-02 16:40:18 +01:00
Mateusz Legięcki
94a09149b6
OpenAPI: Use 201 status code for POST requests. (#7206) 2020-03-02 16:32:26 +01:00
Dhaval Mehta
2a5c2f3f70
Added OpenAPI tags to schemas. (#7184) 2020-02-28 12:06:03 +01:00
Samuel Dion-Girardeau
e32ffbb12b
Fix docs code example (#7201) 2020-02-24 16:33:00 -08:00
Prayash Mohapatra
764dabd29e
Update writeable nested serializer doc (#7198) 2020-02-20 10:55:13 +00:00
Ryan P Kilby
92a4a5d423
Fix docs 404 (#7197)
* Use 'site_url' instead of hardcoding DRF homepage

* Use 'url' template filter instead of 'base_url'

This fixes static file loading for the 404 page.

* Only insert funding <hr> if toc is present

* Link quickstart to valid API guide page

* Fix 404 search modal link

* Use 'base_url' instead of 'site_url' on 404 page
2020-02-20 10:23:06 +00:00
Yoo In Keun
4faa674196
Fixed docs typo. (#7188) 2020-02-19 20:16:42 +01:00
Dalei
39dd34f161
Update docs for OpenAPI (#6814) (#7191) 2020-02-19 11:56:12 +00:00
Kevin Kennell
d7b218f5eb
decode base64 credentials as utf8; adjust tests (#7193)
* decode base64 credentials as utf8; adjust tests

* basicauth: add dedicated test for utf8 credentials

* basicauth: add fallback to latin-1 encoding if utf-8 fails
2020-02-17 16:10:52 +00:00
Thorsten
f81ca78642
Add file option to generateschema (#7130) 2020-02-12 20:35:54 +01:00
Thorsten
4137ef41ef
Disable yaml aliases for schema generation. (#7131) 2020-02-03 14:41:47 +01:00
Kentalot
79d37bce4c
OpenAPI: Include type key in schema object properties dict. (#7169) 2020-01-30 12:14:17 +01:00
Dhaval Mehta
bc4d52558b
Schemas: Add mapping of type for ChoiceField. (#7161) 2020-01-29 19:15:56 +01:00
Stella
160f912a60
Schemas: Handle default=false for boolean fields (#7165) 2020-01-29 10:20:51 +01:00
William S. Vincent
d21b8eb084 update Django for APIs book to 3.0 edition (#7164) 2020-01-28 14:05:32 +00:00
Fábio Domingues
d22daf4e05 OpenAPI: Use _get_serializer() in _get_operation_id() (#7160) 2020-01-26 19:13:08 +01:00
Fábio Domingues
e4a26ad58a Corrected _get_serializer() argument order. (#7156) 2020-01-23 15:53:47 +01:00
Kevin Brown
f8f8b3a1f1 Adjust test for ListField(IntegerField)
The `maximum` is valid here within the schema but it was not
previously being included because we were not copying over the
entire schema for the generated `IntegerField` previously.
2020-01-21 20:45:07 +01:00
Kevin Brown
98c8af5291 ListField mapping should map all options for the child
Previously it was only mapping the `type` and `format`, even though
for some field types (like a `MultipleChoiceField`) we map more
than just these. And for some fields (like a `ChoiceField`) we do
not map the `type` at all.
2020-01-21 20:45:07 +01:00
Kevin Brown
b1048984a7 Add failing test for ListField schema generation
The `ListField` was generating a schema that contained `type=None`
when a `ChoiceField` was the child, since we are not currently able
to introspect the type of a `ChoiceField`.
2020-01-21 20:45:07 +01:00
Carlton Gibson
496947be3a Inline unnecessary method in OpenAPI schema generator. 2020-01-21 20:05:13 +01:00
Carlton Gibson
3b88312c33 Call get_schema(), rather than sub-method in schema tests. 2020-01-21 20:05:13 +01:00
Carlton Gibson
d0b9577605 Return valid OpenAPI schema even when empty. 2020-01-21 20:05:13 +01:00
David Runge
7bd730124c MANIFEST.in: Adding tests to sdist tarball. (#7145) 2020-01-15 20:18:25 +00:00
Jonathan Longe
62193e0378 Add permissions to quickstart tutorial (#7113) 2020-01-15 11:58:31 -08:00
Ryan P Kilby
5f3f2ef106 Add note that APISettings is an internal class (#7144) 2020-01-15 10:52:29 +00:00
Danny
442a206502 Fix full-text search docs (#7133) 2020-01-10 22:38:29 -08:00
Sebastian Pipping
373e521f36 Make CharField prohibit surrogate characters (#7026) (#7067)
* CharField: Detect and prohibit surrogate characters

* CharField: Cover handling of surrogate characters
2020-01-06 14:12:21 +00:00
Alex ⚡
165da5be0c Documentation: make codeblocks easier to read. (#6896) 2020-01-03 14:42:29 +00:00
phankiewicz
a9e55334e7 Add X-CSRFToken HTTP header in swagger-ui example (#6968) 2020-01-03 13:59:32 +00:00
Frederico Lima
25ac7ba450 Add third party lib drf-viewset-profiler (#6993) 2020-01-03 13:53:09 +00:00
Tom Christie
430a567258
Update openapi.py 2020-01-03 13:50:26 +00:00
Noam
ced37a56cb Avoid outputting callable defaults to schema. (#7105) 2020-01-03 13:49:46 +00:00
Bart
07376f128c Grammar fix (#6933) 2020-01-03 13:36:43 +00:00
Jihoon Park
f3ed69374d Add missing punctuation marks and URL name (#7108)
- trailing commas (as both Python and JavaScript allow them)
- trailing semicolons in JavaScript
- URL name `api-docs`
2020-01-03 13:28:35 +00:00
Ran Benita
62ae241894 Remove outdated comment in SerializerMethodField (#7110)
Since 91ea138406.
2020-01-02 14:52:05 +00:00
Ran Benita
d985c7cbb9 Remove a few no longer needed compat checks and references (#7092)
* serializers: removes no longer needed compat checks

UUIDField and DurationField are both supported in all supported Django
versions.

IPAddressField was removed in Django 1.9, which is no longer supported.

* serializers: move related code closer together

This way it's easier to see all of the mappings in one place.

* serializers,docs: remove some DRF 2.x references

The last release of DRF 2.x was 5 years ago, it seems fine to remove
these references now.
2019-12-16 18:59:25 +00:00
Tom Christie
de497a9bf1
Version 3.11 (#7083)
* Version 3.11

* Added notes on OpenAPI changes for 3.11.

* Minor docs tweaking

* Update package version and supported versions

* Use a lazy import for django.test.client.encode_mutlipart. Closes #7078
2019-12-12 14:31:40 +00:00
Jordan Ephron
3c1428ff79 Fix NotImplementedError for Field.to_internal_value and Field.to_representation (#6996) 2019-12-12 14:09:34 +00:00
Ryan P Kilby
b8c369c4cf Fix serializer multiple inheritance bug (#6980)
* Expand declared filtering tests

- Test declared filter ordering
- Test multiple inheritance

* Fix serializer multiple inheritance bug

* Improve field order test to check for field types
2019-12-12 14:03:55 +00:00
Adam Johnson
7c5459626d Declare Django versions in install_requires (#7063)
* Declare Django versions in install_requires

Pip's dependency resolver (used in pipenv, pip-compile, poetry, etc.) can use this to infer whether there's a verison collision in what it's being asked to install or not.

* No max
2019-12-12 13:03:34 +00:00
Ryan P Kilby
236667b717 Fix UniqueTogetherValidator with field sources (#7086)
* Add failing tests for unique_together+source

* Fix UniqueTogetherValidator source handling

* Fix read-only+default+source handling

* Update test to use functional serializer

* Test UniqueTogetherValidator error+source
2019-12-12 13:02:30 +00:00
Aarni Koskela
f744da74d2 Improve the docstring on @action (#6951) 2019-12-11 15:08:54 -08:00
Ryan P Kilby
de9f1d56c4 Followup to set_context removal (#7076)
* Raise framework-specific deprecation warnings

- Use `RemovedInDRF313Warning` instead of DeprecationWarning
- Update to follow deprecation policy

* Pass serializer instead of model to validator

The `UniqueTogetherValidator` may need to access attributes on the
serializer instead of just the model instance. For example, this is
useful for handling field sources.

* Fix framework deprecation warning in test

* Remove outdated validator attribute
2019-12-11 08:44:08 +00:00
Roy Segall
ebcd93163a Adding I'm a teapot error code (#7081) 2019-12-10 09:18:35 +00:00
Ryan P Kilby
90eaf51839
Update framework deprecation warnings (#7075)
- Bump version numbers for deprecation warnings
- Drop deprecated features
2019-12-04 16:18:38 -08:00
Ryan P Kilby
95d4843abe
Fix Django 3.0 deprecations (#7074) 2019-12-04 14:14:43 -08:00
Hasan Ramezani
4d9f9eb192 Changed default widget for TextField with choices to select (#6892) 2019-12-04 12:24:49 -08:00
Kye Russell
dff9759555 Removed Eric S. Raymond quote from the release notes (#7073) 2019-12-04 09:29:01 +00:00
Tom Christie
070cff5a03
Drop set_context() (#7062)
* Do not persist the context in validators

Fixes encode/django-rest-framework#5760

* Drop set_context() in favour of 'requires_context = True'
2019-12-03 11:16:27 +00:00
Asif Saif Uddin
9325c3f654 dj 3.0 (#7070) 2019-12-03 11:13:44 +00:00
Oskar Persson
8001087e9e Fix typo in unsupported version error message (#7060) 2019-11-21 14:59:50 +00:00
Tom Christie
7fbbfe2c60
Django 3 compat (#7058)
* First pass at Django 3.0 compat

* Drop Guardian for 1.11 tests, since we're installing an incompatible version

* Fix ROOT_URLCONF override in test case

* Fix typo

Co-Authored-By: Rémy HUBSCHER <hubscher.remy@gmail.com>

* Linting
2019-11-21 11:55:53 +00:00
Tom Christie
fe840a34ff
Escape hyperlink URLs on lookup (#7059)
* Escape hyperlink URLs on lookup

* Rename duplicate test
2019-11-21 11:38:40 +00:00
Xavier Ordoquy
39876e6607
Merge pull request #7061 from b0uh/doc-remove-old-ref
[Doc] Remove the old reference to `JSONResponse`
2019-11-20 14:29:04 +01:00
Thomas Loiret
adaf97a739 Remove the old reference to JSONResponse 2019-11-20 14:09:49 +01:00
Hendrik
a73d3c309f Elaborated on nested relationships (#7051) 2019-11-18 12:35:36 +00:00
CloudCode Hungary
6196e9c8cd add djangorestframework-features to third-party (#7052) 2019-11-18 12:31:32 +00:00
Chris Guo
cad1b08260 Fix override func style and regular usage (#7050)
* style: add space and rm redundant parentheses

* refactor: use super to replace inherit class

* Prefer explicit tuple syntax
2019-11-18 12:30:36 +00:00
James
323e1cddda Cleanup "Documenting your API" 3rd party recommendations (#7057) 2019-11-15 18:39:47 -08:00
Maxime Jacques
8988afa082 Update bootstrap to 3.4.1 (#6923) 2019-11-11 16:41:10 -05:00
brantmorton
0d6589cf45 Updated url() with re_path() in Versioning docs. (#7043) 2019-11-07 13:20:56 +01:00
Yann Savary
0d3d548aa5 OpenAPI: Fixed generation when title or version not provided. (#6912) 2019-11-06 21:54:12 +01:00
Yann Savary
7c3477dcda OpenAPI: Ported docstring operation description from CoreAPI inspector. (#6898) 2019-11-06 21:52:02 +01:00
Kentalot
becb962160 OpenAPI: Use int64 format for large integers. (#7018) 2019-11-06 21:46:19 +01:00
Dima Knivets
8b06ce72d7 OpenAPI: Map renderers/parsers for request/response media-types. (#6865) 2019-11-06 21:44:51 +01:00
Aaron Yong
14d740d088 Update DEFAULT_SCHEMA_CLASSES default value in Settings docs (#7014)
The default value was changed to point to the OpenAPI AutoSchema class.  The docs were leading users to believe that rest_framework.schemas.AutoSchema was the default.  As of this commit, the root AutoSchema is in fact imported from the coreapi module.
2019-11-06 21:37:13 +01:00
Erwan Rouchet
5e8fe6edf0 Fix link to Django docs (#7040) 2019-11-06 09:34:28 -08:00
Tom Christie
82f2569895
Update __init__.py 2019-11-05 16:43:32 +00:00
Chris Guo
5521eacb02 Update docs imports (#7030) 2019-11-01 10:56:59 -07:00
Daniel Hnyk
ab40b80fa6 Remove unmaintained django-rest-framework-bulk from docs (#7021) 2019-10-28 03:46:44 -07:00
Erwan Rouchet
39bd6cc5cb Set the proper JSON schema type for HStoreFields in OpenAPI schemas (#6914) 2019-10-27 21:13:01 -04:00
Chris Guo
5ee970c090 Fix docs typos (#7015) 2019-10-24 11:31:12 -07:00
Jeremy Lainé
c9f06bf73f Fix a spelling error in openapi AutoSchema method (#7004)
Replace "pagninator" by "paginator".
2019-10-24 10:51:16 +02:00
Aaron Yong
4d57cd31f6 Update method override example in Schemas docs (#6887) (#7013)
get_link() was a method in the old CoreAPI-based AutoSchema implementation.  The new OpenAPI one defines get_operation() instead: the example code block was overlooked.
2019-10-24 08:54:37 +02:00
Bastien Vallet
64f567a021 Bump CI to Python 3.8 (#7008) 2019-10-22 14:39:01 -07:00
Ryan P Kilby
a8c86be660
Update linter requirements (#7010) 2019-10-22 11:18:51 -07:00
nautikos1235
65ed7be754 Fix markdown code indent in schemas (#7009) 2019-10-22 11:10:15 -07:00
Sergey
43397a81ae Fixed decimal snan deserialization (#7002)
* Added test case causes exception in DecimalField deserialization

* Fixed NaN checking which throws exception with sNaN value
2019-10-22 10:06:37 +01:00
Chris Guo
a734e58d44 Fix docs typos (#7006) 2019-10-21 15:11:12 -07:00
zach valenta
f98b6f3577 proper Github repo issue already resolved (#6999)
per the ticket anyway https://github.com/encode/django-rest-framework/issues/2162
2019-10-17 13:58:12 +01:00
Braden MacDonald
3aa1089a6a Update serializer docs to use correct param name (#6995)
Avoids a pylint warning ".to_representation: Parameters differ from overridden 'to_representation' method" if people copy these examples.
2019-10-15 15:47:05 +01:00
Guilherme Munarolo
0fd72f17ee Fixed crash deleting required schema parameter key on PATCH requests. (#6944)
Closes #6941
2019-10-10 08:50:20 +02:00
David Sanders
9850441e6f Fix docs typo (#6974) 2019-10-08 16:37:58 -07:00
Law Karingithi
0e4811e9ce Fix minor grammatical errors in docs (#6979) 2019-10-08 09:38:14 -07:00
Tom Christie
f9cc190177 Crop width on premium sponsor images 2019-10-07 14:31:16 +01:00
Tom Christie
1f3505931c
Update README.md 2019-10-07 14:22:40 +01:00
Tom Christie
f36ff9b08b
Add Retool as a new premium sponsor (#6977) 2019-10-07 14:21:58 +01:00
Francisco Couzo
37dcd55370 Fix bug in escape_curly_brackets (#6909) 2019-10-04 13:50:19 -07:00
mehrab
b4db2dfacf Fixed no-cls-argument on staticmethod __new__ (#6960) 2019-10-04 12:40:09 -07:00
Konstantinos Tselepakis
30e56f62ba Fix nested write of non-relational fields (#6916) 2019-10-03 09:33:37 -07:00
Xavier Ordoquy
0dac98d215
Merge pull request #6953 from felixxm/import-FieldDoesNotExist
Fixed import of FieldDoesNotExist exception.
2019-09-29 08:53:20 +02:00
Mariusz Felisiak
75afe48b6c Fixed import of FieldDoesNotExist exception. 2019-09-28 20:52:22 +02:00
Ted Stoychev
60f9c12900 Fixed broken link in documentation (#6937) 2019-09-27 09:47:51 -07:00
Yezy Ilomo
5b990d4092 Add django-restql to 3rd party packages in docs (#6947) 2019-09-24 00:22:25 -07:00
Oxan van Leeuwen
2664e65019 Add djangorestframework-dataclasses to 3rd party package docs (#6939) 2019-09-18 11:21:32 -07:00
napsterv
7a3b7d2001 Fixed method signature in docs (#6931) 2019-09-16 10:47:29 -07:00
Tom Christie
89ac0a1c7e
Version 3.10.3 (#6908)
* Version 3.10.3

* Version 3.10.3 release notes
2019-09-04 14:28:25 +01:00
Tom Christie
4b30b32014
Default OpenAPI version to the empty string (#6907) 2019-09-04 12:53:50 +01:00
Pramod Pujara
c0cf37e35d Update tutorial links (#6890) 2019-09-03 11:21:53 -07:00
Yann Savary
e57c1505fc Replaced 'TODO' hardcoded version info by a parameter with default '0.1.0' (#6899) 2019-09-03 16:07:30 +02:00
Peter J. Farrell
b3f032fb8f Fixed #6875 -- Made OpenAPI Schema operationId casing consistent. (#6876) 2019-09-03 16:05:43 +02:00
Dima Knivets
1cc4be47b4 Fixed min/max attributes for serializers.ListField (#6866) 2019-09-03 15:43:54 +02:00
Reupen Shah
f8c16441fa Add support for pagination in OpenAPI response schemas (#6867)
Refs #6846

This provides a way for pagination classes to add pagination properties (`count`, `next`, `results` etc.) to OpenAPI response schemas.

A new method `get_paginated_response_schema()` has been added to `BasePagination`. This method is intended to mirror `get_paginated_response()` (which takes a `list` and wraps it in a `dict`). 

Hence, `get_paginated_response_schema()` takes an unpaginated response schema (of type `array`) and wraps that with a schema object of type `object` containing the relevant properties that the pagination class adds to responses.

The default implementation of `BasePagination.get_paginated_response_schema()` simply passes the schema through unmodified, for backwards compatibility.
2019-09-03 15:25:44 +02:00
Min ho Kim
ec1b14174f Fixed typos (#6872) 2019-08-14 14:39:45 -07:00
Christopher Grebs
5a8736ae45 Handle 'None' return value of wait() properly during throttling. (#6837) 2019-08-12 11:36:05 -07:00
Dima Knivets
a142467586 Fixed incorrect OpenAPI response schema generation for a DELETE method in generic views (#6860) 2019-08-09 15:02:41 +02:00
Chris Vigelius
f7dc6b5656 OpenAPI: Added required description to responses. (#6850) 2019-08-07 22:09:27 +02:00
Chris Vigelius
0ebfbfdf81 OpenAPI: only include non-empty required property. (#6851)
Closes #6834
2019-08-07 21:40:21 +02:00
Gregory N. Schmit
335054a5d3 replace force_text with force_str 2019-08-07 21:05:24 +02:00
Reupen Shah
b45ff07294 Use an array type for list view response schemas
This is the first part of #6846.

Previously, the response schema for list views was an object representing a single item. However, list views return a list of items, and hence it should be an array.

Further work will need to be done to support how pagination classes modify list responses.

There should be no change for views not determined to be list views.
2019-08-07 20:40:22 +02:00
Reupen Shah
a3f244d85e Move AutoSchema serializer instantiation to common method 2019-08-07 20:40:22 +02:00
zeroohub
7e1c4be7ce Avoided double call for remote url in FileField.to_representation. (#6841) 2019-08-06 12:31:46 +02:00
Greg Schmit
0cc09f0c0d Add drf-action-sreializer to third party packages (#6845) 2019-07-30 12:37:49 -07:00
Ryan P Kilby
bcf196d0ac
Remove outdated note about read_only+default (#6847) 2019-07-29 15:10:57 -07:00
Max Wittig
ed7f3c55f7
docs(tutorial): add missing permission import in viewsets 2019-07-29 14:20:11 +02:00
Min ho Kim
0e1c5d3132 Fix typos (#6835) 2019-07-25 10:04:01 -07:00
Chris Vigelius
ca727872c8 OpenAPI schemas: Ensure lazy field descriptions are converted to str(). (#6832) 2019-07-25 15:30:20 +02:00
Daniel Alvarez
659375ffe6 Fixed a typo on the ExampleValidatedAPIView
Cherry-picked from #6819
2019-07-24 11:13:30 +02:00
Carlton Gibson
1b66d1b819 Move serializer field introspection tests to correct test case.
From SchemaGenerator tests to Operation Introspection.
2019-07-24 11:13:30 +02:00
Carlton Gibson
de26af4295 Move determine_path_prefix() logic into CoreAPI module. 2019-07-24 11:13:30 +02:00
Carlton Gibson
e309a4f0b8 Fix OpenAPI path generation with common prefixes.
Closes #6675. Closes #6823.
2019-07-24 11:13:30 +02:00
Carlton Gibson
30a21a98dc Add test for OpenAPI SchemaGenerator url argument. 2019-07-24 11:13:30 +02:00
Carlton Gibson
178a2dc786 Correct OpenAPI test for common prefixes. 2019-07-24 11:13:30 +02:00
Daniel Alvarez
2138f558ce Added mapping of ListField.child type for OpenAPI Schemas. 2019-07-24 11:09:57 +02:00
Muammar ibn Faisal
f7c3220fdb Ability to specify urlconf in include_docs_urls added (#6824)
There is a problem in the current implementation that if one exports docs via `include_docs_urls` he will be using `ROOT_URLCONF` (https://github.com/encode/django-rest-framework/blob/master/rest_framework/schemas/generators.py#L73), which is a big problem, if one is working with subdomains and he has sets of disjoint URLs.
This simple fix allows to pass through forgotten `urlconf` parameter.
2019-07-23 12:06:03 +01:00
Bary Levi
ea2ebf61cb fix quote was outside of inline code (#6830) 2019-07-22 13:02:17 +01:00
linchiwei123
da1c6d4129 Fix indent (#6825) 2019-07-18 23:09:04 -07:00
Tom Christie
044252af1c
Version 3.10.1 (#6817)
* Ensure that requiring 'uritemplate' does not also require 'coreapi'

* Don't include autocomplete fields on TokenAuth admin

* Version 3.10.1
2019-07-17 14:17:45 +01:00
Carlton Gibson
9114034856
Update Django Filter dependency for OpenAPI schema support. (#6812) 2019-07-17 06:29:28 +02:00
Carlton Gibson
4991e4dbbe
Merge pull request #6813 from dalvtor/fix-schemas-docs
Fixes import in the schemas documentation
2019-07-16 23:03:13 +02:00
Daniel Alvarez
316526d877 Fixes import in the schemas documentation 2019-07-16 21:32:19 +01:00
Ryan P Kilby
0cb2523927
Update docs search plugin (#6810) 2019-07-16 13:00:45 -07:00
Tom Christie
a4c2d4f0d5 Fix side nav in project docs 2019-07-16 09:31:29 +01:00
Tom Christie
908516f2bd Fix pagination docs meta information 2019-07-15 20:14:59 +01:00
Ryan P Kilby
0cb6b63bde Use 'url' template filter in docs (#6805) 2019-07-15 20:11:49 +01:00
Tom Christie
6499378fc3 3.10 release notes tweaks 2019-07-15 12:38:28 +01:00
Tom Christie
9eaf49dab9
Version 3.10 (#6802)
* 3.10 release notes

* Version number -> 3.10

* Update translations

* Update 3.10 release docs

* Update release notes

* Delete symlink
2019-07-15 12:31:09 +01:00
Ryan P Kilby
b26db12813 Update default settings to use lists instead of tuples (#6799)
* Update default settings from tuples to lists

* Add missing trailing commas

* Use single quotes for consistency

* Update settings lists in docs
2019-07-15 11:54:46 +01:00
Luke Plant
f0dbf0a264 Update docs to use lists instead of tuples (#6797) 2019-07-12 18:15:36 -07:00
Aarni Koskela
5c922fb39d JSONEncoder: ensure empty listlikes remain lists, not dicts (#6794) 2019-07-09 11:41:05 +01:00
Carlton Gibson
7915485c0d Update docs for OpenAPI. (#6668)
* Update schema docs for OpenAPI

* Begin v3.10 Release Announcement.

* Update docs/topics/documenting-your-api.md

Co-Authored-By: Martin Pajuste <pajusmar@users.noreply.github.com>

* Update docs/topics/documenting-your-api.md

Co-Authored-By: Martin Pajuste <pajusmar@users.noreply.github.com>

* Update docs/topics/documenting-your-api.md

Co-Authored-By: Martin Pajuste <pajusmar@users.noreply.github.com>

* Update docs/topics/documenting-your-api.md

Co-Authored-By: Martin Pajuste <pajusmar@users.noreply.github.com>
2019-07-08 13:09:05 +01:00
Tom Quinonero
7762aaa90f Docs sidebar improvements (#5638) (#6589)
* add sans-serif fallback for Verdana in docs sidebar

Co-Authored-By: Joachim Jablon <ewjoachim@gmail.com>

* improve display for docs sidebar (#5638)

Co-Authored-By: Joachim Jablon <ewjoachim@gmail.com>
2019-07-08 13:05:13 +01:00
Tom Christie
1619d282f7
Update rollbar sponsor URL (#6791) 2019-07-08 12:27:21 +01:00
Tom Christie
cc88c8a6f3
Update serializers.md 2019-07-08 11:12:30 +01:00
Ryan P Kilby
bd6a1b3b6c Fix dotted-source field checking on serializer write (#6786)
* Add tests for raise_errors_on_nested_writes

* Fix dotted-source field checking on serializer write

The code was previously checking the validated data for the field's
attribute name, however, the data contain the first source attr.
2019-07-08 11:10:18 +01:00
linchiwei123
372f4fde20 Update pagination.md (#6787)
it seems like that
2019-07-05 22:30:01 -07:00
cyap
eebc579e9b Fix typo (#6785) 2019-07-05 15:46:51 +01:00
linchiwei123
373195996e Update fields.md (#6784)
Example ==> Example
2019-07-05 14:24:52 +01:00
linchiwei123
8fbf8c3fa3 Update serializers.md (#6783) 2019-07-05 09:11:20 +01:00
Ryan P Kilby
976739206c Don't render extra actions when unauthenticated (#6775) 2019-07-04 14:54:16 +01:00
Alex Ayon
a3eeeb20e7 Update 1-serialization.md (#6781)
Assigning a sorted list to STYLE_CHOICES by using a list comprehension.
2019-07-04 13:41:15 +01:00
johnthagen
989aeca205 Add link to django-filter on first reference (#6777) 2019-07-03 10:43:30 -07:00
Étienne Noss
f5470ab9e2 docs: update http method override middleware example (#6776) 2019-07-03 10:23:35 +01:00
Florian Bruhin
43d4736802 Fix rel=prev/next in docs (#6650) 2019-07-02 19:04:49 -07:00
Michael
1256d5363d Add project_urls to setup.py (#6625) 2019-07-02 18:56:26 -07:00
Ryan P Kilby
e4e75f1c7c
Strip null characters from search param (#6774) 2019-07-02 11:33:48 -07:00
Ryan P Kilby
280014fe37 Update docs for pagination settings (#6772) 2019-07-02 12:09:45 +01:00
Ryan P Kilby
41d5338ba6 Translate Throttled exception messages (#6771) 2019-07-02 11:21:40 +01:00
Ryan P Kilby
da06240257
Fix ModelField max_length argument (#6773) 2019-07-01 19:14:45 -07:00
Karambir Singh Nain
a7778897ad Fix ArrayField kwargs mapping for blank/allow_empty (#6758)
Postgres ArrayField blank=True should allow empty Lists in Serializer
2019-07-01 17:34:34 -07:00
Reupen Shah
3242adf058 Enforce allow_empty=False during partial validation of parent serializer (#6512)
Refs #6509

This enforces allow_empty=True when a ListSerializer is a child of another serializer and partial validation is being performed on the parent serializer.

This is because partial validation should allow fields to be omitted, but should not cause values that are invalid without partial validation to become valid.

This effectively reverts #4222. None of the tests added in that PR fail if the associated change is removed, so I‘m not sure what that PR was trying to fix.
2019-07-01 13:30:16 +01:00
Michael
79b2350b54 [fields] Format error message only if params exist (#6624)
This prevents exceptions when the error message contains `%`, but is
not intended for formatting.  Django itself does the same:
6866c91b63/django/core/exceptions.py (L168-L169)

Fixes encode/django-rest-framework#6622
2019-07-01 13:28:16 +01:00
Ryan P Kilby
7179ea9984 Raise exception when field source is a built-in (#6766) 2019-07-01 13:25:47 +01:00
Ryan P Kilby
91ea138406 Allow redundant SerializerMethodField method names (#6767) 2019-07-01 13:22:03 +01:00
Greg Curtis
42fd179d4e upgrade jQuery to latest version (#6728) 2019-07-01 13:16:21 +01:00
Ryan P Kilby
e36ba9c46e
Add twine check to publish process (#6770) 2019-07-01 00:19:12 -07:00
Ryan P Kilby
c04d6eac43
Update pytest (#6768)
* Update pytest to 5.x

* Ensure test de-monkeypatches auth on failure

* Fix pytest.raises compat issue
2019-06-30 19:08:52 -07:00
Ryan P Kilby
82c2b5c3e7
Update mkdocs (#6769) 2019-06-30 19:04:36 -07:00
Jon Besga
9a429a1c2e Fix custom authentication example (#6640) 2019-06-30 17:55:54 -07:00
Ryan P Kilby
df1d146ee7
Remove old documentation (#6765) 2019-06-28 16:03:00 -07:00
Florimond Manca
af2a2e6010 Update description and link to djangorestframework-api-key (#6764) 2019-06-28 15:40:31 -07:00
Jan Pieter Waagmeester
cfd3ea0996 TokenAdmin: add 'user' to autocomplete_fields (#6762)
TokenAdmin is unusable with a big number of user records (in this case ~150k). Django 2.0 added the [ModelAdmin.autocomplete_fields](https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields) option to use select2 to provide a better user experience.

If support for django 1.11 is dropped, this change would make the `TokenAdmin` usable again.
2019-06-28 13:44:15 +01:00
bonohubby
f76480a127 Fix typo in docs (#6757) 2019-06-25 10:08:46 +01:00
Tanner Rollefson
a1921b1adb Add djangorestframework-mvt to third party packages (#6756) 2019-06-24 15:44:22 -07:00
Robert Singer
80e89c75c7 Add DRF Access Policy to 3rd party packages (#6723) 2019-06-23 13:18:08 -07:00
Kryštof Řeháček
6a95451d72 Fixes #6751 - ModelSerializer fields does not get updated correctly when signals are connected to some fields (#6752)
* fixes #6751

* reverted condition

* save instance before setting m2m fields

* added comment why m2m fields are saved after instance

* removed blank line

* added test for the issue 6751
2019-06-22 09:14:15 +01:00
Min ho Kim
72de94a05d Fix typos in docs (#6747) 2019-06-18 12:58:01 -07:00
Xavier Ordoquy
809a6acd36 Add --urlconf to the generateschema command (#6696) 2019-06-09 15:23:52 +02:00
Alan Crosswell
4d228257ac Retain declared path ordering in OpenAPI YAML output. (#6680)
* Add pyyaml.dump(..., sort_keys=False) to not sort openapi keys alphabetically
* Retain ordering of paths as provided in urlconf in OpenAPI schemas.
2019-06-09 14:58:02 +02:00
Alan Crosswell
819c46ea80 Add --generator_class CLI option to generateschema (#6735)
* add --generator_class CLI option to generateschema
* Add test for generateschema —generator_class flag.
2019-06-09 14:43:54 +02:00
Alan Crosswell
2d65f82dd7 Generate OpenAPI schema field types from validators. (#6674) 2019-06-09 14:42:56 +02:00
Alan Crosswell
a63860fc8b Corrected openapi.SchemaGenerator path prefixes. (#6724) 2019-06-09 14:29:55 +02:00
Hasan Ramezani
60bcc93202 Remove duplicate test in tests/test_utils.py (#6736) 2019-06-07 14:45:34 +01:00
Ryan P Kilby
9ac9c1b2ea
Update status code docs (#6732) 2019-06-05 17:51:50 -07:00
Tom Christie
6a8575b042
Sponsor update (#6727)
* Sponsor updates

* Sponsor Update
2019-06-04 12:03:31 +01:00
Tom Christie
3135ae86c9
Create FUNDING.yml 2019-06-04 09:00:11 +01:00
Ryan P Kilby
3e210ae48d
Update markdown preprocessor registration (#6722) 2019-05-31 14:11:58 -07:00
Adam
6aac9d2be1 Remove references to django-crispy-forms (#6600) 2019-05-30 19:47:30 -07:00
Jon Dufresne
b37aa284eb Remove unnecessary bytes() calls (#6626) 2019-05-30 15:05:27 -07:00
Florian Wendelborn
6bd25c09a6 Add Multiple HTTP Statuses (#6706) 2019-05-30 14:32:46 -07:00
Timothy Allen
8430f3e5b6 Fix typo in github.com URL. (#6720) 2019-05-30 12:23:37 -07:00
Ran Benita
c2293e9f25 Improve performance of lazy validation message formatting (#6709) 2019-05-29 11:32:03 -07:00
Rodolfo Carvalho
62ed1f8270 Use yaml.safe_load instead of load (#6719)
Use of PyYAML's yaml.load function without specifying the Loader
parameter has been deprecated, see https://msg.pyyaml.org/load.

Earlier versions of PyYAML already had the alternative safe_load
function, which limits the loader to a subset of YAML constructs, that
is enough for what we need here.

Fixes #6677
2019-05-29 09:51:24 -07:00
Monte Hellawell
063f0de949 Move security information to the GitHub security tab (#6716)
* Create SECURITY.md

* Update security policy links in README.md
2019-05-29 09:57:07 +01:00
Dani Hodovic
10a0b42b74 Add more DRF job sites (#6691) 2019-05-24 12:50:15 +01:00
Raffaele Salmaso
514033815d Allow JSONField encoder customization. (#6713) 2019-05-24 12:47:35 +01:00
Mathieu Pillard
afb678433b Always call all throttling classes on the view when checking throttles (#6711) 2019-05-23 14:42:29 +01:00
Ryan P Kilby
19ca86d8d6
Fix lazy translation of ListField errors (#6708)
* Test init for fields w/ lazy translations
* Fix lazy translations for ListField
2019-05-22 19:41:53 -07:00
Florian Wendelborn
0d0e7c3ae0 Add HTTP 308 Permanent Redirect (#6693) 2019-05-22 11:25:12 -07:00
Ryan P Kilby
db37512a6e
Remove 3.10 deprecations (#6687)
* Remove DjangoObjectPermissionsFilter
* Remove detail_route/list_route
* Bump deprecation warning versions
2019-05-21 10:36:55 -07:00
Ran Benita
ccd9b71c0a Don't cache _readable_fields and _writable_fields (#6689)
It might be useful for a serializer with many many fields which uses
read_only and write_only on a large percentage of the fields. But the
memory usage and statefulness it adds are not worth it for the common
case.
2019-05-21 15:45:31 +01:00
Ryan P Kilby
1b8141a4aa
Fix nullable source='*' fields (#6659) 2019-05-20 14:58:02 -07:00
Rick van Hattem
2c92548963 Made the loading of the fund sidebar async (#6686) 2019-05-20 16:09:23 +01:00
Ran Benita
7232586c7c Simplify Serializer.fields with @cached_property (#6662) 2019-05-20 14:49:47 +01:00
Joachim Jablon
43a9cc1b7a Fix CursorPagination when objects get deleted between calls (#6504) (#6593)
* Added regression tests (#6504)

Co-Authored-By: Tom Quinonero <tq@3yourmind.com>

* Fix CursorPagination when objects get deleted between calls (#6504)

Co-Authored-By: Tom Quinonero <tq@3yourmind.com>
2019-05-20 14:41:31 +01:00
Asif Saif Uddin
ac0f0a1774 Updated optional requirements (#6673) 2019-05-14 10:14:11 -07:00
Ryan P Kilby
c3a13916d2
Update release notes (#6671)
* Add 3.9.4 release notes to master
* Add top-level symlink to release notes
2019-05-14 10:13:14 -07:00
Carlton Gibson
37f210a455
Added OpenAPI Schema Generation. (#6532)
Co-authored-by: Lucidiot <lucidiot@protonmail.com>
Co-authored-by: dongfangtianyu <dongfangtianyu@qq.com>
2019-05-13 16:07:03 +02:00
Asif Saif Uddin
a91e6a0e69 Updated test packges version (#6665) 2019-05-13 09:21:27 +01:00
Ran Benita
9811a29a5a Pass through memo in __deepcopy__ as required by the docs (#6660)
This is needed to avoid problems with recursive loops. See
https://docs.python.org/3.7/library/copy.html
toward the end.
2019-05-09 09:20:32 +01:00
gaetano-guerriero
a7c577cb31 Dict field allow empty (#6583)
* dict field: support allow_empty option

* document ListField allow_empty option

* document HStoreField allow_empty parameter
2019-05-09 09:18:20 +01:00
Tim Gates
564faddb0f Make Markdown 2.6 the minimum compatible version (#6576) 2019-05-08 19:34:38 -07:00
Xavier Ordoquy
2e7ab9d6c6
Merge pull request #6654 from jorrit-wehelp/patch-1
Fix test with STRICT_JSON setting
2019-05-08 18:14:27 +02:00
Jorrit
3a21b390ff
Fix test with STRICT_JSON setting
Test is not overriding the intended setting, should be nested inside settings.REST_FRAMEWORK
2019-05-08 16:48:45 +02:00
Andreu Vallbona Plazas
be5a9f78f3 Added note on serializing extra fields from Through Model (#6652)
* adding small clarification on ManyToManyFields with a Through Model

As pointed here: https://github.com/encode/django-rest-framework/pull/6585#issuecomment-490145334 I suggest to add the small clarification to work with **ManyToManyFields with a Through Model**.

* Remove blank line.
2019-05-07 20:01:24 +02:00
Serkan Hosca
680ed8aa8b Add django-rest-witchcraft to third party packages (#6587) 2019-05-06 16:19:51 -07:00
Asif Saif Uddin
50a24d6d7f Drop Python 3.4 support (#6620) 2019-05-06 11:35:58 -07:00
Aart Goossens
0f819d844d Remove recommendation for DRF Docs (#6580)
Since DRF Docs is not compatible with the latest version of DRF (or Django?; related issue: https://github.com/manosim/django-rest-framework-docs/issues/180) and the latest release is almost 3 years ago I suggest to remove the recommendation for this package.
2019-05-03 15:26:06 -07:00
Jimmy Merrild Krag
14fad0d690 Fix capitalization, markdown syntax link in docs (#6621)
The `Pygments` and `Markdown` python packages have first letter capital.
Fixed link to markdown syntax to go directly to the syntax page.
2019-05-02 18:17:33 -07:00
Jon Dufresne
1e519486e1 Fixup isort command/config (#6639) 2019-05-01 17:42:10 -07:00
Afnarel
67d2eabd6c Fix username in template for custom user models (#6612) 2019-05-01 17:23:23 -07:00
Jon Dufresne
f669395dd8 Fix BytesWarning in test_schemas.py (#6638) 2019-05-01 16:47:01 -07:00
Jon Dufresne
e16273a658 Simplify import_from_string() with Django's import_string() (#6617) 2019-05-01 15:32:28 -07:00
vu3jej
1c976f2ac8 Fix typo in docs (#6628) 2019-05-01 15:24:38 -07:00
Jon Dufresne
059947028b Update docs on django-oauth-toolkit (#6618)
Since django-oauth-toolkit 1.2.0 (2018-06-03), the package requires
Python 3.4+.

https://github.com/jazzband/django-oauth-toolkit/blob/master/CHANGELOG.md#120-2018-06-03
2019-05-01 07:52:26 +02:00
Jon Dufresne
5e1619bc9e Remove unnecessary assignments immediately before a return statement (#6619)
Cleans up the pattern:

    ...
    myvar = <expression>
    return myvar

To:

    ...
    return <expression>
2019-05-01 07:51:54 +02:00
Jon Dufresne
565794bedc Replace virtualenv references with venv in the docs (#6636)
On Python 3, creating virtual environments is available through the
stdlib module venv.

https://docs.python.org/3/library/venv.html
2019-05-01 07:51:02 +02:00
Jon Dufresne
8687f6135f Remove references to Python 2 from the docs (#6635) 2019-05-01 07:50:28 +02:00
Jon Dufresne
3f19e66d9f Replace all usage ugettext functions with the non-u versions (#6634)
On Python 3, the ugettext functions are a simple aliases of their non-u
counterparts (the 'u' represents Python 2 unicode type). Starting with
Django 3.0, the u versions will be deprecated.

https://docs.djangoproject.com/en/dev/releases/3.0/#id2

> django.utils.translation.ugettext(), ugettext_lazy(), ugettext_noop(),
> ungettext(), and ungettext_lazy() are deprecated in favor of the
> functions that they’re aliases for:
> django.utils.translation.gettext(), gettext_lazy(), gettext_noop(),
> ngettext(), and ngettext_lazy().
2019-05-01 07:49:54 +02:00
Jon Dufresne
513a49d63b Drop default 'utf-8' to .encode()/.decode() (#6633)
A Python 3 cleanup that allows for less noise in the code.

https://docs.python.org/3/library/stdtypes.html#bytes.decode
https://docs.python.org/3/library/stdtypes.html#str.encode
2019-05-01 07:49:16 +02:00
Jon Dufresne
734ca7ca8c Remove unneeded repo() test (#6632) 2019-05-01 07:46:30 +02:00
Jon Dufresne
b4e80ac721 Remove unnecessary coerce to str() in test_decorators.py (#6637)
Was added only for Python 2 compatibility.
2019-05-01 07:45:16 +02:00
Jon Dufresne
ff86f09f74 Remove unnecessary compatibility shims from rest_framework/compat.py (#6631)
For Python 3, collections.abc.Mapping and collections.abc.MutableMapping
are always available from the stdlib.
2019-05-01 07:44:33 +02:00
Carlton Gibson
0407a0df8a
Dropped Python 2 compatibility. (#6615)
Thanks to Jon Dufresne (@jdufresne) for review.

Co-authored-by: Asif Saif Uddin <auvipy@gmail.com>
Co-authored-by: Rizwan Mansuri <Rizwan@webbyfox.com>
2019-04-30 17:53:44 +02:00
Xavier Ordoquy
5c992baf32
Merge pull request #6627 from vu3jej/docs
Correct misspelled class name in validators docs
2019-04-30 14:55:27 +02:00
Jithesh Eriyakkadan Janardhanan
908236a576 Correct misspelled class name 2019-04-30 18:01:17 +05:30
Jon Dufresne
1a0a8dde00 Correct misspelled module 'typing' (#6616)
https://docs.python.org/3/library/typing.html
2019-04-30 09:44:01 +01:00
Carlton Gibson
7f16ed7727 Correct version number in release notes. 2019-04-29 16:35:17 +02:00
Carlton Gibson
83d09c7bc5
Update version and release notes for v3.9.3. 2019-04-29 16:30:44 +02:00
Carlton Gibson
bf9859de51
Adjust django-guardian check for PY2 compatible version. (#6613) 2019-04-29 16:08:39 +02:00
Xavier Ordoquy
59a5a5a868
Merge pull request #6611 from dsanders11/patch-1
Fix typo in docs
2019-04-27 22:04:07 +02:00
David Sanders
95e28b2252
Fix typo in docs 2019-04-27 12:07:49 -07:00
Dmitry Alimov
1ac0f63aa9 Fix private attributes ignore in documentation (#6601) 2019-04-21 17:27:13 +01:00
Xavier Ordoquy
db65282163
Merge pull request #6588 from rawteech/master
Add some words about `extra_kwargs` and explicitly defined fields.
2019-04-15 02:31:07 +02:00
Billy Rotich
f8c4e5079e Minor documentation fixes (#6581) 2019-04-13 15:02:19 +02:00
Asif Saif Uddin
29cbe574a3 Fix DeprecationWarning in tests (#6551) 2019-04-05 14:27:07 -07:00
jozo
cceb416098 Link DRF Condition (cache headers) third party package. (#6557) 2019-04-04 11:31:08 +02:00
Carlton Gibson
b1122a441a
Update tox to use Django 2.2 final. (#6556) 2019-04-01 16:30:26 +02:00
Matt Hegarty
f34a0a4e6a Minor documentation fixes (#6543) 2019-03-28 23:32:25 -07:00
Asif Saif Uddin
13b9b0fb98 Upgraded to Django 2.2rc1 on Tox (#6544) 2019-03-28 21:19:06 +01:00
Jabi
ac19c69539 Corrected typo in permissions docs. (#6540) 2019-03-28 11:45:13 +01:00
Turfa Auliarachman
d784e42207 Fix basename deprecation warnings in tests (#6529) 2019-03-25 10:42:27 -07:00
Patrickcai
b25d245b89 Merge multiple isinstance() calls to one (#6513)
* Merge multiple isinstance() calls to one

See https://docs.python.org/3/library/functions.html#isinstance

* Fix `)` mismatch

Fix `)` mismatch
2019-03-22 12:29:45 +00:00
Ryan Siemens
d2d1888217 Document DateTimeField default_timezone argument (#6469) 2019-03-12 21:15:12 -07:00
Matt Hegarty
6f24c21cfb Fixed typo: /Janurary/January/ (#6506) 2019-03-12 12:46:02 +01:00
Tom Christie
9bfb58746e
Update README.md 2019-03-07 11:02:43 +00:00
Tom Christie
bcdfcf7e49
Sponsor updates (#6495) 2019-03-07 11:00:50 +00:00
Kevin Brown
86c72bb226 Fix schema generation of ManyRelatedField to detect the child type (#6489)
* Introspect ManyRelatedField data type recursively

For all `ManyRelatedField` objects, we were assuming that the inner type was always a `String`. While this may be true for the default output, a `ManyRelatedField` is a wrapper for a lot of other classes which includes more than just strings. This should allow us to document lists of things other than strings.

* Added test for schemas for many-to-many fields

This adds a test that makes sure we generate the schema for a many-to-many field such that it actually has the right type. For some reason we did not previously have any tests for schema generation that included them, so hopefully this will prevent any future issues from popping up.

This should serve as a regression test for the `items` field on to-many relationships, which was previously forced to a `String` even though in most cases it is a different inner type within the array.
2019-03-07 11:26:03 +01:00
Ryan P Kilby
fd32dd7ca4 Explicitly raise exc in 'raise_uncaught_exception' (#6435) 2019-03-07 09:44:20 +00:00
Asif Saif Uddin
9e1e32f678 upgraded pytest dependencies (#6492) 2019-03-07 09:22:00 +00:00
Jon Dufresne
9d06e43d05 Replace type('') with six.text_type (#6482)
As all source files import unicode_literals, type('') is always
equivalent to six.text_type (str on Python 3 and unicode on Python 2).
Removes the need to call type(), is more explicit, and will be easier to
catch places to change for when it is time to eventually drop Python 2.
2019-03-05 12:11:46 +01:00
Luoxzhg
dfc277cce6 Corrected tutorial 1 example renderer output to bytes. (#6486) 2019-03-05 11:50:13 +01:00
SrdjanCosicPrica
ac7b20cca2 Fix get_search_fields example (#6487) 2019-03-04 14:46:14 +01:00
Carlton Gibson
0ab527a3df Updated release notes for v3.9.2 2019-03-03 20:16:16 +01:00
Carlton Gibson
ac4c78967a Update version for v3.9.2 release. 2019-03-03 20:16:16 +01:00
Jon Dufresne
7eac86688a Remove executable bit from static assets (#6484)
These files are simply static assets and do not require an executable
bit. They are never intended to be executed as standalone scripts.
2019-03-03 18:39:08 +00:00
Carlton Gibson
94593b3a50
Introduce RemovedInDRF…Warning classes to simplify deprecations. (#6480)
Closes #6290.
2019-03-03 09:20:45 +01:00
Jon Dufresne
a216d02ce0 Merge multiple isinstance() calls to one (#6481)
https://docs.python.org/3/library/functions.html#isinstance

> If classinfo is a tuple of type objects (or recursively, other such
> tuples), return true if object is an instance of any of the types.
2019-03-02 20:48:03 +00:00
Carlton Gibson
31bf597081 Updated note on BooleanField required kwarg generation.
Closes #6474.
2019-03-01 12:48:12 +01:00
Ramon de Jezus
1dc81acb4d Fixed a typo in pagination docs. (#6475) 2019-02-28 15:18:58 +01:00
Andrzej Górski
317174b163 Avoided calling distinct on annotated fields in SearchFilter. (#6240)
Fixes #6094
2019-02-25 16:59:25 +01:00
Adrien Brunet
2daf6f1341 Add negation ~ operator to permissions composition (#6361) 2019-02-25 15:33:40 +01:00
Xtreak
739b0a272a Fix DeprecationWarning in tests when accessing collections.abc classes via collections (#6473) 2019-02-25 15:22:45 +01:00
Frédéric Massart
94fbfcb6fd Added lazy evaluation to composed permissions. (#6463)
Refs #6402.
2019-02-25 13:47:02 +01:00
Carlton Gibson
8a29c53226 Allowed Q objects in limit_choices_to introspection. (#6472)
Closes #6470.
2019-02-25 10:49:29 +00:00
Charlie Hornsby
07c5c968ce Fix DeprecationWarning when accessing collections.abc classes via collections (#6268)
* Use compat version of collections.abc.Mapping

Since the Mapping class will no longer be available to import directly
from the collections module in Python 3.8, we should use the
compatibility helper introduced in #6154 in the fields module.

* Alias and use compat version of collections.abc.MutableMapping

Since the MutableMapping class will no longer be available to import
directly from the collections module in Python 3.8, we should create an
alias for it in the compat module and use that instead.
2019-02-25 09:17:04 +01:00
Ryan P Kilby
286cf57a8d
Update filtering docs (#6467) 2019-02-22 10:58:01 -08:00
Carlton Gibson
d932baa646
Corrected link to ajax-form library.
Closes #6465.
2019-02-22 11:11:52 +01:00
Allan Reyes
d110454d4c Added SearchFilter.get_search_fields() hook. (#6279) 2019-02-19 17:18:14 +01:00
Si Feng
1ece516d2d Adjusted field validators to accept iterables. (#6282)
Closes 6280.
2019-02-19 16:38:20 +01:00
Carlton Gibson
6de33effd6
Doc’d requirement to implement has_object_permission() (#6462)
…when using provided permission classes.

Closes #6402.
2019-02-19 16:18:55 +01:00
jeffrey k eliasen
eb3180173e Made templates compatible with session-based CSRF. (#6207) 2019-02-19 12:15:03 +01:00
Xavier Ordoquy
1660469ed8
Merge pull request #6460 from michael-k/docs-py3-compat
Fix Python 3 compat in documentation
2019-02-17 22:16:35 +01:00
Michael Käufl
f9401f5ff0
Fix Python 3 compat in documentation 2019-02-16 15:47:13 +01:00
Rohit Gupta
de3929fb33 Add Python 3.7 to classifiers. (#6458) 2019-02-15 10:57:02 +01:00
kuter
e8b4bb1471 Added tests for generateschema management command. (#6442) 2019-02-14 17:51:10 +01:00
Carlton Gibson
65f5c11a5b Document support for Django 2.2. 2019-02-14 15:57:20 +01:00
Carlton Gibson
1c5466eae7 Remove Django 2.2 from allowed failure. 2019-02-14 15:57:20 +01:00
Carlton Gibson
59fcbc6dd5 Add migration for generic relations Tag model. 2019-02-14 15:57:20 +01:00
Carlton Gibson
481ae69df3 Add migration for CustomToken test model.
Move authentication tests to sub-app to enable this.
2019-02-14 15:57:20 +01:00
Carlton Gibson
cb4cbb61f2 Fix search filter tests against Django 2.2.
Django 2.2 enables foreign key constraint checking on SQLite.
2019-02-14 15:57:20 +01:00
Carlton Gibson
606dd49227 Update tox to use Django 2.2b2. 2019-02-14 15:57:20 +01:00
Carlton Gibson
3b996c6dc2
Correct 3rd-party-packages link in issue template.
Closes #6457
2019-02-14 12:01:36 +01:00
Xavier Ordoquy
d23ea30d26
Merge pull request #6454 from johnthagen/patch-1
Fix typo in caching docs
2019-02-14 06:47:31 +01:00
johnthagen
9f66fc9a7c
Fix typo in caching docs 2019-02-13 19:00:16 -05:00
briwa
dc6b3bf42e Fix tutorial instruction to also add pyyaml (#6443) 2019-02-07 09:10:11 +01:00
Tanner Prestegard
abf07e672e Fix throttling documentation for specifying alternate caches (#6446) 2019-02-06 21:26:09 +01:00
carlfarrington
3c5c61f33b fix for a couple of missing words (#6444) 2019-02-06 09:35:04 +00:00
jhtimmins
7c6e34c14f Fix typo: 'what' to 'that' (#6437) 2019-02-02 14:49:58 +01:00
Daniel Roseman
7310411533 Updated example models to use __str__ in relations docs. (#6433) 2019-02-01 19:50:27 +01:00
Carlton Gibson
63e352586b
Drop testing Python 3.5 against Django master. (#6431)
Not supported in Django 3.0.
2019-01-31 17:16:43 +01:00
Asif Saif Uddin
2b62941bb4 Added testing against Django 2.2a1. (#6422)
* Added testing against Django 2.2a1.
* Allow failures for Django 2.2
2019-01-31 16:50:36 +01:00
Carlton Gibson
190f6201cb
Update Django Guardian dependency. (#6430)
* Update Django Guardian dependency.
* Skip testing Guardian on PY2. See https://github.com/django-guardian/django-guardian/issues/602
2019-01-31 15:59:19 +01:00
Carlton Gibson
bd9a799e16
Fixed SchemaView to reset renderer on exception. (#6429)
Fixes #6258.
2019-01-31 15:28:01 +01:00
Carlton Gibson
f54a220d8f
Corrected coreapi CLI code example generation. (#6428)
Remove “> “ when rendering template.
Closes #6333.
2019-01-31 11:36:40 +01:00
Andy Babic
87ade870c3 Added 'request_forms' block to base.html (#6340) 2019-01-24 16:30:46 +01:00
Carlton Gibson
9ff0092061 Added release note stub for v3.9.2. 2019-01-24 16:25:47 +01:00
Marcin Popławski
4c2af75957 Updated links to djangorestframework-api-key project. (#6414) 2019-01-24 16:10:11 +01:00
Carlton Gibson
8d20e10218
Deferred schema renderer creation to avoid requiring pyyaml. (#6416)
Closes #6366.
2019-01-24 16:01:06 +01:00
Carlton Gibson
f539c0dbd1
Removed incorrect DictField docstring. (#6417)
Closes #6363.
2019-01-24 15:18:22 +01:00
Carlton Gibson
0ac20a3d8e
Updated filtering docs to use filterset_fields. (#6415)
Closes #6411.
2019-01-21 21:00:54 +01:00
Steven Loria
271c4c5920 Remove sudo from .travis.yml (#6408)
Travis CI has migrated their infrastructure
https://blog.travis-ci.com/2018-11-19-required-linux-infrastructure-migration
2019-01-17 13:58:24 +00:00
Sébastien Diemer
822b85ac36 routers: invalidate _urls cache on register (#6407)
see https://github.com/encode/django-rest-framework/issues/5660

Trying to register new routes on a router after having accessed the
router `urls` attribute leads to surprising results.
The route is added without error to the router's `registry` but the urls
are not updated, because they are cached in `_urls`.
This commit invalidates the cache after each new registration.
2019-01-17 13:07:57 +00:00
Tom Christie
c049777dc7 Add missing item in 3.9.1 release notes 2019-01-16 13:39:36 +00:00
Tom Christie
453196e9c3
Version 3.9.1 (#6405)
* Version 3.9.1

* Upgrade bootstrap

* Release notes for 3.9.1
2019-01-16 13:27:35 +00:00
Yury V. Zaytsev
4bb9a3c484 Fix XSS caused by disabled autoescaping in the default DRF Browsable API view templates (#6330)
* Add test that verifies that HTML is correctly escaped in Browsable API views

* Fix `urlize_quoted_links` tag to avoid double escaping in autoescape mode

* Fix XSS in default DRF Browsable API template by re-enabling autoescape
2019-01-16 12:36:25 +00:00
Adrien Brunet
e3bd4b9048 Fix #1811: take limit_choices_to into account with FK (#6371)
* Fix issue1811: take limit_choices_to into account with FK

* Issue 1811: Add tests to illustrate issue

* Filter queryset only if limit_choices_to exists

* Move test_relations_with_limited_querysets file within test_relations_pk

* move limit_choices_to logic from relations.py to utils/field_mapping.py

* move limit_choices_to above other check to avoid conflicts
2019-01-08 13:49:47 +00:00
johnthagen
9c408b296b Remove reference to deprecated drf-openapi package (#6398) 2019-01-08 12:47:09 +00:00
Matt Wiens
e0ae975e5c Fix a badly formatted title in docs (#6089)
While having code blocks in a title is valid Markdown, MkDocs does not
render it as expected. This removes a code block placed in a title.
2019-01-08 12:07:00 +00:00
Stephen Finucane
c052a86c7b compat: (py2) urlparse = urllib.parse (py3) (#6262)
* compat: (py2) urlparse = urllib.parse (py3)

We were mistakenly importing the 'urlparse' function from the Python 2
'urlparse' module, as opposed to the module itself. Correct this.

Signed-off-by: Stephen Finucane <stephen@that.guru>
Closes: #6261

* compat: Remove 'compat.urlparse'

We can just use Django's vendored six library, like we do everywhere
else.

Signed-off-by: Stephen Finucane <stephen@that.guru>
2019-01-08 12:03:02 +00:00
johnthagen
a49d744d5e Fix OpenAPI links (#6382) 2019-01-08 11:56:42 +00:00
johnthagen
0860ef9eee Update quickstart to Django 2.0 routing syntax (#6385)
* Update quickstart to Django 2.0 routing syntax

* Remove uneccessary raw string identifiers

* Correctly import path function

* Fix import path to use django.urls

This is what is prescribed in the Django 2.1 tutorial
2019-01-08 11:53:51 +00:00
Carlton Gibson
587058e3c2 Allow run_validators() to handle non-dict types. (#6365)
Fixes #6053.

Original test case thanks to Vincent Delaitre in #6242.
2019-01-08 11:39:30 +00:00
Yaser Khahani
0cf18c4163 Use Default Version in URLPathVersioning if 'version' Didn't Specified by Client (#6380)
* Use Default Version in URLPathVersioning if 'version' Didn't Passed

* Clean Code
2019-01-08 11:34:54 +00:00
Adrien Brunet
4863a24451 Fix links 404/302/303 in docs/community (#6387)
* Fix links 404/302/303

* Fix machinalis links in docs

* Fix kickstarter links in documentation

* Fix kickstarter links in documentation

* Fix kickstarter links in documentation - dropping links when broken
2019-01-08 11:15:53 +00:00
johnthagen
7749e4e3be Make code snippet Python 3 compatible (#6377) 2019-01-04 18:00:38 -08:00
Adrien Brunet
1e2fd25f54 Fix #3387: Documentation - Remove leading '.' before format option (#6388) 2019-01-04 14:45:08 +00:00
Xavier Ordoquy
030119c117
Merge pull request #6386 from philratcliffe/fix_missing_import_in_example_code
Fix missing import in example code
2018-12-28 17:54:41 +01:00
Phil Ratcliffe
1a9548db4f Fix missing import in example code 2018-12-28 16:10:08 +00:00
Anuvrat Parashar
97a47958c0 correct grammar, remove common noun after proper noun. (#6383)
`MultipartParser` is enough to denote that it is a parser.
2018-12-24 15:54:27 +00:00
Xavier Ordoquy
5fd12d1b16
Merge pull request #6376 from johnthagen/patch-1
Fix example to be Python 3.x and 2.7 compatible
2018-12-23 07:46:35 +01:00
johnthagen
f0712aa78a
Fix example to be Python 3.x and 2.7 compatible 2018-12-22 15:29:02 -05:00
Carlton Gibson
86aa7768a7 Update quote in relations.md (#6373)
Fixes #6372.
2018-12-21 11:39:01 +00:00
Carlton Gibson
63e6bbfd36 Note that only latest patches of Python & Django are supported. (#6370)
Fixes #6367.
2018-12-20 13:41:54 +00:00
Dario Cangialosi, Coder
fa57fb8aeb Use HTTPS URL example for git clone commands. (#6134) 2018-12-19 19:28:03 +01:00
Alf
963ce306f3 Added "allow_unicode" to generated kwargs for ModelSerializer SlugField (#6315) 2018-12-19 15:37:52 +01:00
Cyrus Ghazanfar
7ad5bdb669 Adjusted login template override example (#6265) 2018-12-19 15:25:34 +01:00
Jonathan Berger
1348bdc48a Fixed quickstart.md typos (#6348) 2018-12-19 14:50:14 +01:00
Xavier Ordoquy
a52087b1b8
Merge pull request #6362 from adrienbrunet/typo
docs: typo in permissions (double space)
2018-12-19 14:34:18 +01:00
Adrien Brunet
c4a021185f docs: typo in permissions (double space) 2018-12-18 13:03:03 +01:00
Tom Christie
2aecef3460 Update kloudless logo 2018-12-18 11:23:08 +00:00
Tom Christie
3453d65655 Update Kloudless logo 2018-12-18 11:18:40 +00:00
Michael D. Hoyle
a64980232a Add example of gender-neutral language in contributing guide. (#6358) 2018-12-17 21:10:39 +01:00
Dan Wilson
ef61288d77 Remove mention of djangorestframework-jwt (#6353)
Follow-up to https://github.com/encode/django-rest-framework/pull/6138
2018-12-13 21:01:10 +00:00
JerzySpendel
627eeb8202 Add missing comma in documentation of permission composition (#6336) 2018-12-07 16:44:57 -05:00
Josh Smith
facb433c89 Remove unmaintained digest authentication package (#6347)
https://github.com/juanriaza/django-rest-framework-digestauth has not been updated in 5 years and is currently incompatible with the latest DRF ecosystem.
2018-12-06 16:26:40 +00:00
HoangYell
b61806e3b3 add "js-tooltip" class to "POST" button (#6344)
the tool tip of "POST" button is different from other buttons, since it loses the "js-tooltip" class.
2018-12-03 12:10:05 +00:00
Benjamin Pereto
5a54f897ec FIX: openapi schema title should be a string not a tuple (#6259) 2018-11-28 12:45:26 +00:00
Xavier Ordoquy
11edf572c5
Merge pull request #6299 from encode/xordoquy/fix_composable_permissions
Fix composable permissions
2018-11-27 15:47:30 +01:00
Xavier Ordoquy
74574217a4 Fix composable permissions
In some cases we end with an operation between two `OperandHolder`.
This didn't work as it didn't knew how to deal with | or &
This fixes by adding those operations.
2018-11-27 15:29:44 +01:00
takaaki shimbo
0f5dfe8b3c Fix typo in schemas (#6332)
* Fix typo in generators.py

* Fix typo in inspectors.py

* message line too long

* Change backslash to multiline strings

* Removed trailing whitespace from assertion message
2018-11-26 10:14:59 -08:00
Ryan P Kilby
9b7db8dd69
Travis has released Xenial support (#6322) 2018-11-20 23:45:04 -08:00
Tom Christie
2084555fbe Update Lights On logo 2018-11-16 15:41:38 +00:00
Mice Pápai
d0369b27cd update docs/api-guide/serializers.md: consistency (#6320) 2018-11-15 14:44:54 +00:00
Tom Christie
2c0b2bd44e
Add 'Lights On Software' (#6319)
* Add 'Lights On Software'

* Fix link
2018-11-15 13:52:24 +00:00
Tom Christie
588c6976d4
Delete lightson.png 2018-11-15 12:06:47 +00:00
Tom Christie
bc36cf5e2b
Lights On 2018-11-15 12:06:18 +00:00
Tom Christie
f73b4896b8
Lights On Software 2018-11-15 12:04:06 +00:00
Stan Fateev
f7d2839562 Typo fix in the release announcement (#6318) 2018-11-14 07:50:28 +01:00
Xavier Ordoquy
bf9533ae37
Merge pull request #6286 from markddavidoff/patch-1
permissions must return a boolean to allow &/| operator comparison
2018-11-05 16:04:08 +00:00
Stephen Finucane
fae7e91728 docs: Remove references to drf-openapi (#6272)
This has been EOL'd in favour of drf-yasg [1].

[1] https://github.com/limdauto/drf_openapi/commit/1673c6e0

Signed-off-by: Stephen Finucane <stephen@that.guru>
2018-11-03 15:57:47 +01:00
Tom Snee
d59a130168 Fixes an import statement in chapter 5 of the tutorial. (#6267) 2018-11-02 08:48:39 -07:00
ilmucio
40da2a21ef Update authentication.md (#6291) 2018-10-29 15:43:06 -07:00
Mark Davidoff
1f13b6f6b2 use actual user instead of fake user in permission composition test 2018-10-29 10:45:40 -07:00
Zach Wernberg
67e99a29b8 Fix typo in release-notes.md (#6285) 2018-10-29 10:03:34 -07:00
Mark Davidoff
fc08e0189f
update tests to reflect that django now returns a callable for is_authenticated 2018-10-29 08:26:20 -07:00
Mark Davidoff
6f2c0dbf4d
permissions must return a boolean
`x and y` actually returns object y when both are true. the means P & IsAuthenticated will fail with TypeError: unsupported operand type(s) for &: 'instance' and 'bool' as IsAuthenticated now returns a CallableBool which does not overload __ror__
2018-10-28 14:12:39 -07:00
Tano Abeleyra
9d001cd84c Fix typo in testing.md (#6257) 2018-10-18 15:42:52 -07:00
Tom Christie
2c9c0f1b7f
Version 3.9 (#6247)
* Release notes to 5174a26ec9

* Update version for v3.9.0

* Removed exclude_from_schema per deprecation policy.

* Updated list_route() and detail_route() deprecations.

* Weakened to PendingDeprecationWarning for `base_name`

cc @rpkilby.

* Add (beginning of) 3.9 release announcement.

@tomchristie: Input on OpenAPI and What’s Next very welcome! :)

* Add announcement section for Extra Actions in Browsable API

* Update release notes and add deprecation note for Django Guardian backend.

* Add release note for #6073

* Add release notes to dd19a44583

* Adding release notes

* Update 3.9 announcement

* Add Oct 18 release date
2018-10-18 10:38:46 +01:00
Tom Christie
28040b3bda
Upgrade Auklet to premium (#6244) 2018-10-15 17:31:36 +01:00
Tom Christie
1c3f796219
Add kloudless as a new premium sponsor (#6241) 2018-10-11 14:48:05 +01:00
Tom Christie
ebc5393776 Add spacing around kloudless logo 2018-10-11 14:06:33 +01:00
Tom Christie
317d2489e4 Add Kloudless logo 2018-10-11 14:03:02 +01:00
Dennis Kliban
dd19a44583 Problem: autoescape not getting passed to urlize_quoted_links filter (#6191)
Solution: set needs_autoescape=True when registering the filter

Without this patch, the disabling autoescape in the template does not work.
2018-10-10 10:36:04 +02:00
Daniel Bate
5feb835929 Feature/action docs sections (#6060)
* added ability to add sections to custom action documentation

* added tests to cover docs sections in custom actions

* added method specific docs test for action mapping

* added docs for custom action documentation
2018-10-10 10:29:29 +02:00
Tom Christie
6522d4ae20
Add OpenAPIRenderer by default, and add schema docs. (#6233)
* Add OpenAPIRenderer as a default for get_schema_view, and start adding schema docs

* Add optional pyyaml

* Updating schema docs
2018-10-04 14:05:55 +01:00
Jufe Brown-Tsai
18ad3290ef Documentation fix for django-admin commands (#6232)
* fix django-admin commands on quickstart doc

* fix django-admin commands on tutorial/1-serialization doc

* fix django-admin command on readme

* fix django-admin command on docs/community/project-management.md
2018-10-03 16:16:52 +01:00
Xavier Ordoquy
b41a6cfa38 permissions: Allow permissions to be composed (#5753)
* permissions: Allow permissions to be composed

Implement a system to compose permissions with and / or.
This is performed by returning an `OperationHolder` instance that keeps the
permission classes and type of composition (and / or).
When called it will return a AND/OR instance that will then delegate the
permission check to the operands.

* permissions: Add documentation about composed permissions

* Fix documentation typo in permissions
2018-10-03 15:36:24 +01:00
Tom Christie
8908934928
Add OpenAPIRenderer and generate_schema management command. (#6229)
* Add OpenAPIRenderer and generate_schema command

* Add both OpenAPIRenderer and JSONOpenAPIRenderer

* Add flags to generate_schema command

* Fix syntax error

* Pull coreschema references into method, so they are only used if 'OpenAPIRenderer' is in use.

* generate_schema -> generateschema, and fix to OpenAPIRenderer

* Ensure that renderers generate bytes and generateschema outputs text

* Drop unused import
2018-10-03 15:28:04 +01:00
Tom Christie
c9d2bbcead
Update codecov.yml 2018-10-02 16:57:49 +01:00
Jerome Leclanche
0eb2dc1137 Prohibit null characters in CharField by default (#6073)
* Implement an allow_null_bytes argument to CharField (default True)
* Switch to using native ProhibitNullCharactersValidator instead
2018-10-02 16:54:15 +02:00
Ryan P Kilby
66183389f6 Deprecate DjangoObjectPermissionsFilter (#6075) 2018-10-02 16:34:25 +02:00
Ryan P Kilby
903204cd79 Fix action support for ViewSet suffixes (#6081)
* Add suffix support for actions

Removes the newly introduced `action.name` in favor of leveraging the
View's `.get_view_name()` method, which supports both name and suffix.

* Fix view description func docstrings

* Test action decorator name & suffix kwargs

* Adjust 'extra action' docs
2018-10-02 16:22:21 +02:00
Tom Christie
20a7734dce Bring docs license text up to date 2018-10-02 11:12:31 +01:00
Lewis M. Kabui
d0995fac70 Remove dot character from "pagination_class" (#6137) 2018-10-02 08:49:31 +02:00
Matheus Cansian
9ecce21044 Update JWT docs. (#6138)
* Remove mentions to djangorestframework-jwt in docs
* Remove links for blimp and djangorestframework-jwt
2018-10-02 08:43:45 +02:00
Jon Dufresne
878f9d2783 Prefer https:// for URLs when available throughout project (#6208) 2018-10-02 08:28:58 +02:00
Tom Christie
d1514d1f9c Update codecov.yml (#6224) 2018-10-01 18:12:03 +02:00
Anish Shrestha
2e8ccfd883 Fix typo in docs (#6212) 2018-09-25 12:11:13 -07:00
Anish Shrestha
d976ac56b0 Fix spelling error (#6198) 2018-09-21 08:55:32 +02:00
Melissa Lewis
b090ae9d30 Fix docs typos (#6195) 2018-09-18 15:32:32 -07:00
Ryan P Kilby
5174a26ec9 Simplify job matrix on Travis (#6174)
* Move to explicit Travis matrix

* Cleanup Python 3.6 matrix
2018-09-17 10:41:55 +02:00
Jon Dufresne
ed6340ee76 Remove unnecessary use of compat shim six.binary_type (#6189)
The type bytes is available on all supported Pythons. On Python 2.7, it
is an alias for str, same as six.binary_type. Makes the code more
forward compatible with Python 3.
2018-09-17 10:39:59 +02:00
Ryan P Kilby
fc6cbb5b26 Allow nullable BooleanField in Django 2.1 (#6183)
* Add tests for BooleanField when nullable

* Allow nullable BooleanField in Django 2.1

* Drop 'BooleanField.allow_null' check

* Remove conflicting false/null values
2018-09-13 17:25:03 +01:00
Tom Christie
5f1f2b1003 Higher res. load impact logo 2018-09-11 12:55:53 +01:00
Tom Christie
4e093b0e25 Add Load Impact to README 2018-09-11 11:53:45 +01:00
Tom Christie
9140629c45 Fix Load Impact URL 2018-09-11 11:41:49 +01:00
Tom Christie
4033f0c6b3
Add Load Impact to premium sponsors (#6176) 2018-09-11 11:40:47 +01:00
Ryan P Kilby
7f77340b33
Add Python 3.7 support (#6141) 2018-09-10 21:44:23 -07:00
Jerome Leclanche
612a7b989f Fix Python 3.8 compatibility (#6154) 2018-09-10 21:12:32 -07:00
Jon Dufresne
4d57d46bf8 Prefer io.BytesIO over six; available on all supported Pythons (#6168)
On all supported Pythons, the io.BytesIO is always a stream
implementation using an in-memory bytes buffer.

Makes code slightly more forward compatible by reducing use of the six
module and promotes more forward compatible practices in the docs.
2018-09-09 11:53:41 +01:00
Xavier Ordoquy
1d5771d980
Merge pull request #6165 from dsanders11/patch-1
Fix validate_my_field signature
2018-09-07 05:44:24 +00:00
David Sanders
69f605f30e
Fix validate_my_field signature 2018-09-06 18:16:06 -07:00
Timothy Allen
bc573d8096 Add drf-renderer-xlsx package. (#6147)
* Add drf-renderer-xlsx package.

* Gah, tabs creeped in; never leave your default editor environment. :)
2018-09-06 11:01:57 +01:00
oliver
bcc565f387 Clean up unnecessary if statement (#6163) 2018-09-06 07:25:20 +01:00
Michael
2c992f09da Mention Django 2.1 compat where missing (#6158) 2018-09-04 11:33:42 -07:00
Jon Dufresne
468cdd16ed Remove unnecessary models.py file (#6142)
Since Django 1.7, an empty models.py file is not required.

See
https://docs.djangoproject.com/en/dev/releases/1.7/#app-loading-refactor

> It is possible to omit models.py entirely if an application doesn’t
> have any models.
2018-08-28 09:51:28 +02:00
Ryan P Kilby
c4b068cfd3
Fix dist build (#6139)
* Use tox-venv to reduce warnings in output

* Remove .egg-info/ to allow wheel installation

tox now invokes pip as a python module instead of through its entry
point. "python -m" adds the current directory to the PYTHONPATH, picking
up the .egg-info/ metadata directory, tricking pip into thinking that
the package is already installed (and thus not installing the wheel).
Deleting the metadata directory fixes this.
2018-08-24 15:57:45 -07:00
Craig Johnson
90ed2c1ef7 Small grammar correction in quickstart. (#6121)
Just felt the sentence could use some improving.
2018-08-13 10:32:17 +01:00
Craig de Stigter
81fa4b4f75 Fix CSRF cookie check failure when using session auth with django 1.11.6+ (#6113)
Test included. Fixes #6088
2018-08-07 08:18:56 +01:00
Oleg
2fab7838ef Improve ModelSerializer.create() error message. (#6112) 2018-08-06 20:11:55 +02:00
Oleg
8b5e830bce Handle models without .objects manager in ModelSerializer. (#6111)
* Handle models without .objects manager in ModelSerializer.

* Improvements according to review comments.
2018-08-06 14:30:43 +02:00
Jon Dufresne
5ad24b0811 Test using Django 2.1 final release (#6109) 2018-08-06 10:06:17 +02:00
Shabda Raaj
8f9b875456 Add building with drf book (#6102)
* Added building APIs with Django and DRF book

* Added book cover
2018-08-01 16:43:09 +01:00
Michael
8493990a66 Add Django 2.1 to classifiers (#6099) 2018-07-29 11:54:10 +01:00
Daniel Hahler
f404fda29c codecov: enable status for patch/changes, comment: diff (#6080)
Ref: https://github.com/encode/django-rest-framework/pull/6077#issuecomment-403838095

This is https://github.com/encode/django-rest-framework/pull/6050
without the project status, and fixes/improves the comment added in
https://github.com/encode/django-rest-framework/pull/6077.
2018-07-10 16:32:47 +02:00
dengshilong
0484d01aae Fix typo error, Link to Field (#6078) 2018-07-10 11:03:39 +02:00
Ryan P Kilby
987d73a03d Add minimal codecov comment (#6077) 2018-07-10 10:59:08 +02:00
Ryan P Kilby
33f8910b26
Fix deprecation warnings in tests (#6076)
* Fix deprecated arguments in schema tests

* Update optional reqs, fixing markdown deprecation
2018-07-09 23:56:52 -04:00
Eze Sunday
a0277919f0 Fix grammar mistake in html-and-forms.md (#6070) 2018-07-08 16:11:05 -04:00
Ryan P Kilby
38b3d0109b Only catch TypeError/ValueError for object lookups (#6028)
* Only catch TypeError/ValueError for object lookups

* Test wrapped TypeError/ValueError handling

* Raise NotImplementedError in tests instead of pass
2018-07-06 12:18:17 +02:00
Ryan P Kilby
a628a2dbce Drop Django 1.10 support (#5657)
* Remove Django 1.10 from CI

* Remove Django 1.10 compat code
2018-07-06 12:14:31 +02:00
Ryan P Kilby
9b8af04e7f Move guardian imports out of compat (#6054) 2018-07-06 11:32:02 +02:00
Ryan P Kilby
99ca078ebb Add "Community" section to docs, minor cleanup (#5993)
* Add 'Community' tab to navigation, move articles

* Drop DRF 2.x announcements and the docs note

* Drop embedded tutorial/guide/topics links

* Conver mixture of tabs/spaces => spaces

* Fix topics/community links
2018-07-06 11:28:18 +02:00
Ryan P Kilby
7095021db7 Rename base_name => basename for consistency's sake (#5990)
* Rename base_name => basename for consistency

* Update tests to use basename
2018-07-06 11:03:12 +02:00
Ryan P Kilby
f89cc066bc Admin renderer urls (#5988)
* Make admin detail link have small width

* Disable admin detail link when no URL

* Add 'AdminRenderer.get_result_url'

Attempts to reverse the result's detail view URL.
2018-07-06 10:58:26 +02:00
Daniel Hahler
3578bd6883 get_error_detail: use error_dict/error_list (#5785) 2018-07-06 10:44:58 +02:00
Ryan P Kilby
6511b52cca Fix schemas for extra actions (#5992)
* Add failing test for extra action schemas

* Add ViewInspector setter to store instances

* Fix schema disabling for extra actions

* Add docs note about disabling schemas for actions
2018-07-06 10:35:36 +02:00
Daniel Hahler
b23cdaff4c tox/pytest: move posargs, use -ra (#6039)
- tox: move {posargs} to the end, so that it can override previous
  entries, e.g. `-ra` when `-rw` was used.
- pytest: add `-ra` to addopts: it is good to see a summary of skipped
  and failed tests at the end.
2018-07-06 10:34:11 +02:00
Ryan P Kilby
0148a9f8da Improvements to ViewSet extra actions (#5605)
* View suffix already set by initializer

* Add 'name' and 'description' attributes to ViewSet

ViewSets may now provide their `name` and `description` attributes
directly, instead of relying on view introspection to derive them.
These attributes may also be provided with the view's initkwargs.

The ViewSet `name` and `suffix` initkwargs are mutually exclusive.

The `action` decorator now provides the `name` and `description` to
the view's initkwargs. By default, these values are derived from the
method name and its docstring. The `name` may be overridden by providing
it as an argument to the decorator.

The `get_view_name` and `get_view_description` hooks now provide the
view instance to the handler, instead of the view class. The default
implementations of these handlers now respect the `name`/`description`.

* Add 'extra actions' to ViewSet & browsable APIs

* Update simple router tests

Removed old test logic around link/action decorators from `v2.3`. Also
simplified the test by making the results explicit instead of computed.

* Add method mapping to ViewSet actions

* Document extra action method mapping
2018-07-06 10:33:10 +02:00
Daniel Hahler
56967dbd90 Fix upload parser test (#6044) 2018-07-05 23:52:32 -04:00
Ryan P Kilby
0e10d32fb1
Add NotImplementedError to coverage exclusion (#6057) 2018-06-24 17:56:31 -04:00
Ryan P Kilby
c5ab65923f
tests/test_permissions.py: do not add view perm for dj21 (#6055) 2018-06-23 07:31:06 -04:00
Daniel Hahler
499533d219 Use [tool:pytest] header in setup.cfg (#6045) 2018-06-22 18:14:26 -04:00
Chris Shyi
d9f541836b Update to Django 2.0 Routing Syntax (#6049) 2018-06-22 10:28:59 +02:00
Ryan P Kilby
1a170438d2 Add "optionals not required" build (#6047) 2018-06-22 10:16:57 +02:00
Daniel Hahler
7e0ad9262e tests: update pytest/pytest-django (#6042) 2018-06-21 16:23:52 -04:00
Daniel Hahler
a44cb67988 tests: fix usage of transaction.non_atomic_requests (#6043) 2018-06-21 14:44:58 -04:00
Daniel Hahler
06526cafe5 runtests.py: clean up PYTEST_ARGS (#6040)
1. `tests` and `--tb=short` is not necessary, since it is in
`pytest.addopts` already.
2. removes `-s` (shortcut for --capture=no): it is typically a good idea
   to not display output from successful tests.
2018-06-21 14:28:25 +01:00
Çağıl
8f55cd8db5 Fix url for group_names action example (#6036) 2018-06-21 04:29:05 -04:00
Asif Saifuddin Auvi
d778c5e51e Update tox to use Django v2.1b1 (#6037) 2018-06-21 09:07:33 +02:00
William S. Vincent
feffa109a8 Add REST APIs with Django book (#6033)
Just published book dedicated to DRF.
2018-06-20 00:24:26 +01:00
Xavier Ordoquy
3fcc076d91
Merge pull request #6024 from tveastman/master
Documentation: Correct the signature for HyperlinkedRelatedField.get_object()
2018-06-13 07:43:35 +02:00
Tom Eastman
be2bcf7e3f Documentation: Correct the signature for HyperlinkedRelatedField.get_object() 2018-06-13 16:39:28 +12:00
Emeka Icha
a21484d90e (fix) link to disqus article on cursor pagination (#6020) 2018-06-12 10:34:28 +01:00
Xavier Ordoquy
8688c99602
Merge pull request #6019 from jdufresne/pypi-register
Update incorrect PyPI URL to register an account
2018-06-10 09:49:16 +02:00
Jon Dufresne
89fb0b0f99 Update incorrect PyPI URL to register an account
To register an account on PyPI, the URL is
https://pypi.org/account/register/, which changed after the move to
pypi.org.
2018-06-09 19:09:31 -07:00
Tom Christie
26b0f650d6
Update LICENSE.md 2018-06-04 09:16:18 +01:00
Tom Christie
206423009b
Update LICENSE.md 2018-06-04 09:15:05 +01:00
Steven Loria
cf925caa48 Render markdown readme on PyPI (#6004)
* Render markdown readme on PyPI

PyPI now supports GitHub-flavored Markdown descriptions
(https://blog.thea.codes/github-flavored-markdown-on-pypi/),
so there's no need to convert the README to rst with pypandoc
any more.

* Remove readme checking

Checking markdown descriptions is not necessary.
See https://github.com/pypa/readme_renderer#markdown

* Upgrade twine
2018-06-03 19:21:04 +01:00
Matt Layman
f67d23c441 Add docs link to Caching API Guide. (#6012) 2018-05-31 09:58:02 +02:00
Teppei Fukuda
fe54575e6a Fix exceptions.md (#6003) 2018-05-25 10:42:22 +01:00
Xavier Ordoquy
a7cd1dbc43
Merge pull request #6001 from auvipy/master
updated tox and travis for django 2.1 alpha1
2018-05-23 21:10:27 +02:00
Asif Saifuddin Auvi
2634294667 updated tox and travis for django 2.1 alpha1 2018-05-23 16:33:15 +06:00
int3l
1ee3829a2f Update the http signature auth library ref link (#5997)
* Update the http signature auth library ref link

It seems that the djangorestframework-httpsignature package is outdated
and there is updated fork named drf-httpsig.

* Fixing the link ref format in the http signature section
2018-05-22 12:22:09 +01:00
Tamirlan Omarov
edfcbe076d Added pagination section to the quickstart page (#5987) 2018-05-21 13:32:07 +01:00
John Franey
f20e282d15 Update documenting-your-api.md (#5991)
Fix link to "Schemas as Documentation: Examples"
2018-05-17 00:36:41 -04:00
Eduardo GP
ff4429fad4 fix e.indexOf is not a function error (#5982) 2018-05-11 21:49:29 +01:00
Craig de Stigter
9629886915 Fixed AttributeError from items filter when value is None (#5981) 2018-05-11 08:50:08 +02:00
Daniel Hahler
c17b4ad0d0 Include coverage for tests (#5970)
It is useful to see if tests itself are covered after all - missing
coverage there typically indicates dead/missed code paths.

This also uses `source=.` and includes (with run and report), to help
Codecov with reporting.
Ref: https://github.com/encode/django-rest-framework/pull/5956
2018-05-08 14:02:45 +01:00
Daniel Hahler
275c157341 tests: remove some dead code, use assert 0 for never called methods (#5973)
* tests: remove some dead code, use `assert 0` for never called methods

* fixup! tests: remove some dead code, use `assert 0` for never called methods
2018-05-08 13:28:46 +01:00
Daniel Hahler
4527a753cd Move pytest config to setup.cfg (#5979)
Also adds `testspath` to improve test collection performance.
2018-05-08 13:28:16 +01:00
Daniel Hahler
fca39f9dbb tests: fix test_write_only_fields not being executed (#5971)
This adds the required `test_` prefix.
2018-05-08 09:27:35 +01:00
Daniel Hahler
4c29752b6a requirements-testing: update pytest and pytest-django (#5972) 2018-05-08 09:27:25 +01:00
Tom Christie
da4ecfddc2
Update .gitignore 2018-05-08 09:21:32 +01:00
Tom Christie
6957aaae85
Delete config 2018-05-08 09:20:01 +01:00
Tom Christie
0218f20ac4
Delete .editorconfig 2018-05-08 09:19:31 +01:00
Ari Rouvinen
45acfe05b4 Add missing comma (#5978) 2018-05-08 09:15:59 +01:00
Daniel Hahler
40d5985f57 requirements-optionals: use psycopg2-binary (#5969)
Ref: https://github.com/encode/django-rest-framework/pull/5967#issuecomment-386431446
2018-05-08 09:15:32 +01:00
Andreas Lutro
a6b6b6ce55 remove references to DOAC in docs (#5977)
Project has been archived on github and recommends alternative.
2018-05-08 09:10:43 +01:00
Chris Shyi
fc2143207b Update tutorial to Django 2.0 routing syntax (#5963) (#5964)
Update tutorial to Django 2.0 routing syntax
2018-05-08 09:06:14 +01:00
Xavier Ordoquy
4340ff42de
Merge pull request #5976 from victormpa/fix_filter_docs
Added import statement on filtering docs
2018-05-07 05:40:59 +00:00
Victor Martins
21c0fcf63b Added import statement on filtering docs 2018-05-06 00:02:09 -03:00
Daniel Hahler
fd4282c7fa pytest: use --strict (#5966)
This causes errors with invalid markers:

> AttributeError: 'skipUnless' not a registered marker

Fixed in https://github.com/encode/django-rest-framework/pull/5965.
2018-05-03 21:43:57 +01:00
Daniel Hahler
d4dc24ea3e requirements-optionals.txt: bump psycopg2 to 2.7.4 (#5967)
With 2.7.3 I am seeing an ImportError on Arch Linux:

> ImportError: …/.venv/lib/python3.6/site-packages/psycopg2/.libs/libresolv-2-c4c53def.5.so:
> symbol __res_maybe_init version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference
2018-05-03 13:32:39 +01:00
Daniel Hahler
e79610af3a tests: fix skipping with TestPosgresFieldsMapping (#5965)
`pytest.mark.skipUnless` does not exist, it was confused with
`unittest.skipUnless` probably.
2018-05-03 13:31:46 +01:00
Çağıl
8c03c49400 update testing.md - fixes related to RequestsClient (#5959)
* Include import for RequestsClient in the docs.
* Use fully qualified URLs for `RequestsClient` in the docs.
2018-04-26 12:47:38 +01:00
Ryan O’Hara
a11938ce96 Fixed instance being overwritten in pk-only optimization try/except block (#5747) 2018-04-24 16:15:38 +02:00
Noam
7268643b25 min_value/max_value support in DurationField (#5643)
* Added min_value/max_value field arguments to DurationField.
* Made field mapping use mix/max kwargs for DurationField validators.
2018-04-24 09:24:05 +02:00
Sascha P
7d64b7016d Removed input value from deault_error_message (#5881) 2018-04-20 16:00:27 +02:00
Jimmy Merrild Krag
4260531b6c Render descriptions (from help_text) using safe (#5869)
To allow embedded HTML, and make consistent with other usages.

Fixes #5715.
2018-04-20 15:51:27 +02:00
Jimmy Merrild Krag
5ee0e5df83 Correct schema parsing for JSONField (#5878)
Fixes #5873.
* Use Object type. 
* Add test for field_to_schema
2018-04-20 15:47:20 +02:00
Mikkel Munch Mortensen
9dbb49ef22 Docs: Match original argument names (#5889)
Change argument names in overridden field methods to match those of the base classes.
2018-04-20 15:35:09 +02:00
Jochen Wersdörfer
c4676510fd Adjusted client JWT example (#5944) 2018-04-20 15:33:59 +02:00
Craig Anderson
2ebd479759 Allow hashing of ErrorDetail to fix #5919 (#5932) 2018-04-20 15:32:37 +02:00
Christian Kreuzberger
f148e4e259 Ensure that html forms (multipart form data) respect optional fields (#5927) 2018-04-20 15:11:52 +02:00
Tom Christie
7e705246ca
Ensure docs sidebar can scroll to bottom. (#5949)
Closes #5948
2018-04-20 12:11:48 +01:00
Michael
e4b63f70d6 [docs] Remove leftover from former python 3.2/3.3 support (#5947) 2018-04-20 09:22:36 +02:00
Jon Dufresne
8c47a875ec Update all pypi.python.org URLs to pypi.org (#5942)
For details on the new PyPI, see the blog post:

https://pythoninsider.blogspot.ca/2018/04/new-pypi-launched-legacy-pypi-shutting.html
2018-04-19 08:36:18 +02:00
Tom Christie
f3d41625f5
Add Cadre as a premium sponsor (#5941) 2018-04-18 10:33:02 +01:00
Arne Schauf
d5fe1f66ac Fix a typo in the 3.8 announcement (#5940) 2018-04-18 06:36:03 +01:00
Ryan P Kilby
7078afa42c Change ISO 8601 date format to exclude year/month (#5936) 2018-04-14 05:23:31 +01:00
David Jean Louis
1c53fd3212 Added djangorestframework-datatables to third-party packages (#5931) 2018-04-10 13:25:20 +01:00
Xavier Ordoquy
4b47721c6d
Merge pull request #5930 from minitux/patch-1
[DOCS] python print syntax docs/api-guide/settings.md
2018-04-10 08:39:44 +00:00
minitux
3dd90d2b46
[DOCS] python print syntax
python3 style
2018-04-09 23:31:58 +02:00
Steven Loria
8a639c6c06 Update link to django-rest-marshmallow docs (#5925) 2018-04-09 16:48:18 +02:00
Anna Ossowski
0178d3063d
Added 3.8 release + updated monthly report link 2018-04-08 21:47:50 +02:00
Carlton Gibson
fb802c0910
Update version and notes for 3.8.2 release. (#5923) 2018-04-06 15:41:11 +02:00
Carlton Gibson
42eb5a4342
Fix read_only + default unique_together validation. (#5922)
* Add test for read_only + default unique_together validation.
* Fix read_only + default validation
2018-04-06 15:20:54 +02:00
gsvr
32caca4dd3 Import coreapi from rest_framework.compat, not directly. (#5921) 2018-04-05 15:07:49 +02:00
Michael
ffac61c6fe Docs: Add missing argument 'detail' to Route (#5920)
The namedtuple Route requires `detail` to be specified, otherwise it
fails with:
`TypeError: __new__() missing 1 required positional argument: 'detail'`

See https://github.com/encode/django-rest-framework/pull/5705/files#diff-88b0cad65f9e1caad64e0c9bb44615f9R34
2018-04-05 14:24:31 +02:00
Carlton Gibson
bc353452f4
Bump version and release notes for 3.8.1 (#5916) 2018-04-04 21:10:34 +02:00
Ryan P Kilby
cba426b34c Use old url_name behavior in route decorators (#5915)
* Wrap action decorator for old url_name behavior
2018-04-04 20:50:42 +02:00
Xavier Ordoquy
3365ec23ec
Merge pull request #5914 from encode/xordoquy/fix_release_notes
release_notes: fix call to super().data
2018-04-04 13:29:48 +00:00
Xavier Ordoquy
3a29eff5f8 release_notes: fix call to super().data
`super().data()` leads to a `TypeError` saying that 'ReturnDict' object
is not callable.
2018-04-04 15:21:36 +02:00
Carlton Gibson
2621e03aa3 Added 3.8 announcement to docs
Correct release notes MD formatting
2018-04-03 16:06:06 +02:00
436 changed files with 32012 additions and 14475 deletions

View File

@ -1,7 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

2
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: encode
custom: https://fund.django-rest-framework.org/topics/funding/

13
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,13 @@
# Keep GitHub Actions up to date with GitHub's Dependabot...
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
version: 2
updates:
- package-ecosystem: github-actions
directory: /
groups:
github-actions:
patterns:
- "*" # Group all Action updates into a single larger pull request
schedule:
interval: weekly

22
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,22 @@
# Documentation: https://github.com/probot/stale
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 1
# Label to use when marking as stale
staleLabel: stale

73
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,73 @@
name: CI
on:
push:
branches:
- master
pull_request:
jobs:
tests:
name: Python ${{ matrix.python-version }}
runs-on: ubuntu-24.04
strategy:
matrix:
python-version:
- '3.9'
- '3.10'
- '3.11'
- '3.12'
- '3.13'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements/*.txt'
- name: Upgrade packaging tools
run: python -m pip install --upgrade pip setuptools virtualenv wheel
- name: Install dependencies
run: python -m pip install --upgrade tox
- name: Run tox targets for ${{ matrix.python-version }}
run: tox run -f py$(echo ${{ matrix.python-version }} | tr -d . | cut -f 1 -d '-')
- name: Run extra tox targets
if: ${{ matrix.python-version == '3.9' }}
run: |
tox -e base,dist,docs
- name: Upload coverage
uses: codecov/codecov-action@v5
with:
env_vars: TOXENV,DJANGO
test-docs:
name: Test documentation links
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.9'
- name: Install dependencies
run: pip install -r requirements/requirements-documentation.txt
# Start mkdocs server and wait for it to be ready
- run: mkdocs serve &
- run: WAIT_TIME=0 && until nc -vzw 2 localhost 8000 || [ $WAIT_TIME -eq 5 ]; do sleep $(( WAIT_TIME++ )); done
- run: if [ $WAIT_TIME == 5 ]; then echo cannot start mkdocs server on http://localhost:8000; exit 1; fi
- name: Check links
continue-on-error: true
run: pylinkvalidate.py -P http://localhost:8000/
- run: echo "Done"

22
.github/workflows/pre-commit.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: pre-commit
on:
push:
branches:
- master
pull_request:
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: "3.10"
- uses: pre-commit/action@v3.0.1

7
.gitignore vendored
View File

@ -2,6 +2,8 @@
*.db *.db
*~ *~
.* .*
*.py.bak
/site/ /site/
/htmlcov/ /htmlcov/
@ -13,7 +15,6 @@
MANIFEST MANIFEST
coverage.* coverage.*
!.editorconfig !.github
!.gitignore !.gitignore
!.travis.yml !.pre-commit-config.yaml
!.isort.cfg

39
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,39 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-json
- id: check-merge-conflict
- id: check-symlinks
- id: check-toml
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/PyCQA/flake8
rev: 7.0.0
hooks:
- id: flake8
additional_dependencies:
- flake8-tidy-imports
- repo: https://github.com/adamchainz/blacken-docs
rev: 1.16.0
hooks:
- id: blacken-docs
exclude: ^(?!docs).*$
additional_dependencies:
- black==23.1.0
- repo: https://github.com/codespell-project/codespell
# Configuration for codespell is in .codespellrc
rev: v2.2.6
hooks:
- id: codespell
exclude: locale|kickstarter-announcement.md|coreapi-0.1.1.js
- repo: https://github.com/asottile/pyupgrade
rev: v3.19.1
hooks:
- id: pyupgrade
args: ["--py39-plus", "--keep-percent-format"]

View File

@ -1,57 +0,0 @@
language: python
cache: pip
python:
- "2.7"
- "3.4"
- "3.5"
sudo: false
env:
- DJANGO=1.10
- DJANGO=1.11
- DJANGO=2.0
- DJANGO=master
matrix:
fast_finish: true
include:
- { python: "3.6", env: DJANGO=master }
- { python: "3.6", env: DJANGO=1.11 }
- { python: "3.6", env: DJANGO=2.0 }
- { python: "2.7", env: TOXENV=lint }
- { python: "2.7", env: TOXENV=docs }
- python: "3.6"
env: TOXENV=dist
script:
- python setup.py bdist_wheel
- tox --installpkg ./dist/djangorestframework-*.whl
- tox # test sdist
- python: "3.6"
env: TOXENV=readme
addons:
apt_packages: pandoc
exclude:
- { python: "2.7", env: DJANGO=master }
- { python: "2.7", env: DJANGO=2.0 }
- { python: "3.4", env: DJANGO=master }
allow_failures:
- env: DJANGO=master
install:
- pip install tox tox-travis
script:
- tox
after_success:
- pip install codecov
- codecov -e TOXENV,DJANGO
notifications:
email: false

View File

@ -1,207 +1,5 @@
# Contributing to REST framework # Contributing to REST framework
> The world can only really be changed one piece at a time. The art is picking that piece. At this point in its lifespan we consider Django REST framework to be essentially feature-complete. We may accept pull requests that track the continued development of Django versions, but would prefer not to accept new features or code formatting changes.
>
> &mdash; [Tim Berners-Lee][cite]
There are many ways you can contribute to Django REST framework. We'd like it to be a community-led project, so please get involved and help shape the future of the project. The [Contributing guide in the documentation](https://www.django-rest-framework.org/community/contributing/) gives some more information on our process and code of conduct.
## Community
The most important thing you can do to help push the REST framework project forward is to be actively involved wherever possible. Code contributions are often overvalued as being the primary way to get involved in a project, we don't believe that needs to be the case.
If you use REST framework, we'd love you to be vocal about your experiences with it - you might consider writing a blog post about using REST framework, or publishing a tutorial about building a project with a particular JavaScript framework. Experiences from beginners can be particularly helpful because you'll be in the best position to assess which bits of REST framework are more difficult to understand and work with.
Other really great ways you can help move the community forward include helping to answer questions on the [discussion group][google-group], or setting up an [email alert on StackOverflow][so-filter] so that you get notified of any new questions with the `django-rest-framework` tag.
When answering questions make sure to help future contributors find their way around by hyperlinking wherever possible to related threads and tickets, and include backlinks from those items if relevant.
## Code of conduct
Please keep the tone polite & professional. For some users a discussion on the REST framework mailing list or ticket tracker may be their first engagement with the open source community. First impressions count, so let's try to make everyone feel welcome.
Be mindful in the language you choose. As an example, in an environment that is heavily male-dominated, posts that start 'Hey guys,' can come across as unintentionally exclusive. It's just as easy, and more inclusive to use gender neutral language in those situations.
The [Django code of conduct][code-of-conduct] gives a fuller set of guidelines for participating in community forums.
# Issues
It's really helpful if you can make sure to address issues on the correct channel. Usage questions should be directed to the [discussion group][google-group]. Feature requests, bug reports and other issues should be raised on the GitHub [issue tracker][issues].
Some tips on good issue reporting:
* When describing issues try to phrase your ticket in terms of the *behavior* you think needs changing rather than the *code* you think need changing.
* Search the issue list first for related items, and make sure you're running the latest version of REST framework before reporting an issue.
* If reporting a bug, then try to include a pull request with a failing test case. This will help us quickly identify if there is a valid issue, and make sure that it gets fixed more quickly if there is one.
* Feature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintenance overhead of REST framework, so that the focus can be on continued stability, bug fixes, and great documentation.
* Closing an issue doesn't necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we'll consider if it needs to be reopened.
## Triaging issues
Getting involved in triaging incoming issues is a good way to start contributing. Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be. Anyone can help out with this, you just need to be willing to:
* Read through the ticket - does it make sense, is it missing any context that would help explain it better?
* Is the ticket reported in the correct place, would it be better suited as a discussion on the discussion group?
* If the ticket is a bug report, can you reproduce it? Are you able to write a failing test case that demonstrates the issue and that can be submitted as a pull request?
* If the ticket is a feature request, do you agree with it, and could the feature request instead be implemented as a third party package?
* If a ticket hasn't had much activity and it addresses something you need, then comment on the ticket and try to find out what's needed to get it moving again.
# Development
To start developing on Django REST framework, clone the repo:
git clone git@github.com:encode/django-rest-framework.git
Changes should broadly follow the [PEP 8][pep-8] style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles.
## Testing
To run the tests, clone the repository, and then:
# Setup the virtual environment
virtualenv env
source env/bin/activate
pip install django
pip install -r requirements.txt
# Run the tests
./runtests.py
### Test options
Run using a more concise output style.
./runtests.py -q
Run the tests using a more concise output style, no coverage, no flake8.
./runtests.py --fast
Don't run the flake8 code linting.
./runtests.py --nolint
Only run the flake8 code linting, don't run the tests.
./runtests.py --lintonly
Run the tests for a given test case.
./runtests.py MyTestCase
Run the tests for a given test method.
./runtests.py MyTestCase.test_this_method
Shorter form to run the tests for a given test method.
./runtests.py test_this_method
Note: The test case and test method matching is fuzzy and will sometimes run other tests that contain a partial string match to the given command line input.
### Running against multiple environments
You can also use the excellent [tox][tox] testing tool to run the tests against all supported versions of Python and Django. Install `tox` globally, and then simply run:
tox
## Pull requests
It's a good idea to make pull requests early on. A pull request represents the start of a discussion, and doesn't necessarily need to be the final, finished submission.
It's also always best to make a new branch before starting work on a pull request. This means that you'll be able to later switch back to working on another separate issue without interfering with an ongoing pull requests.
It's also useful to remember that if you have an outstanding pull request then pushing new commits to your GitHub repo will also automatically update the pull requests.
GitHub's documentation for working on pull requests is [available here][pull-requests].
Always run the tests before submitting pull requests, and ideally run `tox` in order to check that your modifications are compatible with both Python 2 and Python 3, and that they run properly on all supported versions of Django.
Once you've made a pull request take a look at the Travis build status in the GitHub interface and make sure the tests are running as you'd expect.
## Managing compatibility issues
Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into the `compat.py` module, and should provide a single common interface that the rest of the codebase can use.
# Documentation
The documentation for REST framework is built from the [Markdown][markdown] source files in [the docs directory][docs].
There are many great Markdown editors that make working with the documentation really easy. The [Mou editor for Mac][mou] is one such editor that comes highly recommended.
## Building the documentation
To build the documentation, install MkDocs with `pip install mkdocs` and then run the following command.
mkdocs build
This will build the documentation into the `site` directory.
You can build the documentation and open a preview in a browser window by using the `serve` command.
mkdocs serve
## Language style
Documentation should be in American English. The tone of the documentation is very important - try to stick to a simple, plain, objective and well-balanced style where possible.
Some other tips:
* Keep paragraphs reasonably short.
* Don't use abbreviations such as 'e.g.' but instead use the long form, such as 'For example'.
## Markdown style
There are a couple of conventions you should follow when working on the documentation.
##### 1. Headers
Headers should use the hash style. For example:
### Some important topic
The underline style should not be used. **Don't do this:**
Some important topic
====================
##### 2. Links
Links should always use the reference style, with the referenced hyperlinks kept at the end of the document.
Here is a link to [some other thing][other-thing].
More text...
[other-thing]: http://example.com/other/thing
This style helps keep the documentation source consistent and readable.
If you are hyperlinking to another REST framework document, you should use a relative link, and link to the `.md` suffix. For example:
[authentication]: ../api-guide/authentication.md
Linking in this style means you'll be able to click the hyperlink in your Markdown editor to open the referenced document. When the documentation is built, these links will be converted into regular links to HTML pages.
##### 3. Notes
If you want to draw attention to a note or warning, use a pair of enclosing lines, like so:
---
**Note:** A useful documentation note.
---
[cite]: https://www.w3.org/People/Berners-Lee/FAQ.html
[code-of-conduct]: https://www.djangoproject.com/conduct/
[google-group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework
[so-filter]: https://stackexchange.com/filters/66475/rest-framework
[issues]: https://github.com/encode/django-rest-framework/issues?state=open
[pep-8]: https://www.python.org/dev/peps/pep-0008/
[pull-requests]: https://help.github.com/articles/using-pull-requests
[tox]: https://tox.readthedocs.io/en/latest/
[markdown]: https://daringfireball.net/projects/markdown/basics
[docs]: https://github.com/encode/django-rest-framework/tree/master/docs
[mou]: http://mouapp.com/

View File

@ -1,14 +0,0 @@
## Checklist
- [ ] I have verified that that issue exists against the `master` branch of Django REST framework.
- [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
- [ ] This is not a usage question. (Those should be directed to the [discussion group](https://groups.google.com/forum/#!forum/django-rest-framework) instead.)
- [ ] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](http://www.django-rest-framework.org/topics/third-party-resources/#about-third-party-packages) where possible.)
- [ ] I have reduced the issue to the simplest possible case.
- [ ] I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)
## Steps to reproduce
## Expected behavior
## Actual behavior

View File

@ -1,16 +1,21 @@
# License # License
Copyright (c) 2011-2017, Tom Christie Copyright © 2011-present, [Encode OSS Ltd](https://www.encode.io/).
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or * Redistributions in binary form must reproduce the above copyright notice,
other materials provided with the distribution. this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

View File

@ -1,6 +1,7 @@
include README.md include README.md
include LICENSE.md include LICENSE.md
recursive-include rest_framework/static *.js *.css *.png *.ico *.eot *.svg *.ttf *.woff *.woff2 recursive-include tests/ *
recursive-include rest_framework/static *.js *.css *.map *.png *.ico *.eot *.svg *.ttf *.woff *.woff2
recursive-include rest_framework/templates *.html schema.js recursive-include rest_framework/templates *.html schema.js
recursive-include rest_framework/locale *.mo recursive-include rest_framework/locale *.mo
global-exclude __pycache__ global-exclude __pycache__

View File

@ -1,4 +1,4 @@
*Note*: Before submitting this pull request, please review our [contributing guidelines](https://github.com/encode/django-rest-framework/blob/master/CONTRIBUTING.md#pull-requests). *Note*: Before submitting a code change, please review our [contributing guidelines](https://www.django-rest-framework.org/community/contributing/#pull-requests).
## Description ## Description

143
README.md
View File

@ -1,12 +1,12 @@
# [Django REST framework][docs] # [Django REST framework][docs]
[![build-status-image]][travis] [![build-status-image]][build-status]
[![coverage-status-image]][codecov] [![coverage-status-image]][codecov]
[![pypi-version]][pypi] [![pypi-version]][pypi]
**Awesome web-browsable Web APIs.** **Awesome web-browsable Web APIs.**
Full documentation for the project is available at [http://www.django-rest-framework.org][docs]. Full documentation for the project is available at [https://www.django-rest-framework.org/][docs].
--- ---
@ -19,13 +19,18 @@ continued development by [signing up for a paid plan][funding].
The initial aim is to provide a single full-time position on REST framework. The initial aim is to provide a single full-time position on REST framework.
*Every single sign-up makes a significant impact towards making that possible.* *Every single sign-up makes a significant impact towards making that possible.*
[![][rover-img]][rover-url]
[![][sentry-img]][sentry-url] [![][sentry-img]][sentry-url]
[![][stream-img]][stream-url] [![][stream-img]][stream-url]
[![][machinalis-img]][machinalis-url] [![][spacinov-img]][spacinov-url]
[![][rollbar-img]][rollbar-url] [![][retool-img]][retool-url]
[![][bitio-img]][bitio-url]
[![][posthog-img]][posthog-url]
[![][cryptapi-img]][cryptapi-url]
[![][fezto-img]][fezto-url]
[![][svix-img]][svix-url]
[![][zuplo-img]][zuplo-url]
Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Rover][rover-url], [Sentry][sentry-url], [Stream][stream-url], [Machinalis][machinalis-url], and [Rollbar][rollbar-url]. Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Spacinov][spacinov-url], [Retool][retool-url], [bit.io][bitio-url], [PostHog][posthog-url], [CryptAPI][cryptapi-url], [FEZTO][fezto-url], [Svix][svix-url], and [Zuplo][zuplo-url].
--- ---
@ -35,14 +40,12 @@ Django REST framework is a powerful and flexible toolkit for building Web APIs.
Some reasons you might want to use REST framework: Some reasons you might want to use REST framework:
* The [Web browsable API][sandbox] is a huge usability win for your developers. * The Web browsable API is a huge usability win for your developers.
* [Authentication policies][authentication] including optional packages for [OAuth1a][oauth1-section] and [OAuth2][oauth2-section]. * [Authentication policies][authentication] including optional packages for [OAuth1a][oauth1-section] and [OAuth2][oauth2-section].
* [Serialization][serializers] that supports both [ORM][modelserializer-section] and [non-ORM][serializer-section] data sources. * [Serialization][serializers] that supports both [ORM][modelserializer-section] and [non-ORM][serializer-section] data sources.
* Customizable all the way down - just use [regular function-based views][functionview-section] if you don't need the [more][generic-views] [powerful][viewsets] [features][routers]. * Customizable all the way down - just use [regular function-based views][functionview-section] if you don't need the [more][generic-views] [powerful][viewsets] [features][routers].
* [Extensive documentation][docs], and [great community support][group]. * [Extensive documentation][docs], and [great community support][group].
There is a live example API for testing purposes, [available here][sandbox].
**Below**: *Screenshot from the browsable API* **Below**: *Screenshot from the browsable API*
![Screenshot][image] ![Screenshot][image]
@ -51,8 +54,11 @@ There is a live example API for testing purposes, [available here][sandbox].
# Requirements # Requirements
* Python (2.7, 3.4, 3.5, 3.6) * Python 3.9+
* Django (1.10, 1.11, 2.0) * Django 4.2, 5.0, 5.1, 5.2
We **highly recommend** and only officially support the latest patch release of
each Python and Django series.
# Installation # Installation
@ -61,11 +67,12 @@ Install using `pip`...
pip install djangorestframework pip install djangorestframework
Add `'rest_framework'` to your `INSTALLED_APPS` setting. Add `'rest_framework'` to your `INSTALLED_APPS` setting.
```python
INSTALLED_APPS = ( INSTALLED_APPS = [
... ...
'rest_framework', 'rest_framework',
) ]
```
# Example # Example
@ -75,7 +82,7 @@ Startup up a new project like so...
pip install django pip install django
pip install djangorestframework pip install djangorestframework
django-admin.py startproject example . django-admin startproject example .
./manage.py migrate ./manage.py migrate
./manage.py createsuperuser ./manage.py createsuperuser
@ -83,15 +90,16 @@ Startup up a new project like so...
Now edit the `example/urls.py` module in your project: Now edit the `example/urls.py` module in your project:
```python ```python
from django.conf.urls import url, include
from django.contrib.auth.models import User from django.contrib.auth.models import User
from rest_framework import serializers, viewsets, routers from django.urls import include, path
from rest_framework import routers, serializers, viewsets
# Serializers define the API representation. # Serializers define the API representation.
class UserSerializer(serializers.HyperlinkedModelSerializer): class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ('url', 'username', 'email', 'is_staff') fields = ['url', 'username', 'email', 'is_staff']
# ViewSets define the view behavior. # ViewSets define the view behavior.
@ -104,12 +112,11 @@ class UserViewSet(viewsets.ModelViewSet):
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register(r'users', UserViewSet) router.register(r'users', UserViewSet)
# Wire up our API using automatic URL routing. # Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API. # Additionally, we include login URLs for the browsable API.
urlpatterns = [ urlpatterns = [
url(r'^', include(router.urls)), path('', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
] ]
``` ```
@ -118,16 +125,16 @@ We'd also like to configure a couple of settings for our API.
Add the following to your `settings.py` module: Add the following to your `settings.py` module:
```python ```python
INSTALLED_APPS = ( INSTALLED_APPS = [
... # Make sure to include the default installed apps here. ... # Make sure to include the default installed apps here.
'rest_framework', 'rest_framework',
) ]
REST_FRAMEWORK = { REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions, # Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users. # or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [ 'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
] ]
} }
``` ```
@ -141,14 +148,14 @@ You can now open the API in your browser at `http://127.0.0.1:8000/`, and view y
You can also interact with the API using command line tools such as [`curl`](https://curl.haxx.se/). For example, to list the users endpoint: You can also interact with the API using command line tools such as [`curl`](https://curl.haxx.se/). For example, to list the users endpoint:
$ curl -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/ $ curl -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/
[ [
{ {
"url": "http://127.0.0.1:8000/users/1/", "url": "http://127.0.0.1:8000/users/1/",
"username": "admin", "username": "admin",
"email": "admin@example.com", "email": "admin@example.com",
"is_staff": true, "is_staff": true,
} }
] ]
Or to create a new user: Or to create a new user:
@ -162,54 +169,58 @@ Or to create a new user:
# Documentation & Support # Documentation & Support
Full documentation for the project is available at [http://www.django-rest-framework.org][docs]. Full documentation for the project is available at [https://www.django-rest-framework.org/][docs].
For questions and support, use the [REST framework discussion group][group], or `#restframework` on freenode IRC. For questions and support, use the [REST framework discussion group][group], or `#restframework` on libera.chat IRC.
You may also want to [follow the author on Twitter][twitter].
# Security # Security
If you believe you've found something in Django REST framework which has security implications, please **do not raise the issue in a public forum**. Please see the [security policy][security-policy].
Send a description of the issue via email to [rest-framework-security@googlegroups.com][security-mail]. The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure. [build-status-image]: https://github.com/encode/django-rest-framework/actions/workflows/main.yml/badge.svg
[build-status]: https://github.com/encode/django-rest-framework/actions/workflows/main.yml
[build-status-image]: https://secure.travis-ci.org/encode/django-rest-framework.svg?branch=master
[travis]: https://travis-ci.org/encode/django-rest-framework?branch=master
[coverage-status-image]: https://img.shields.io/codecov/c/github/encode/django-rest-framework/master.svg [coverage-status-image]: https://img.shields.io/codecov/c/github/encode/django-rest-framework/master.svg
[codecov]: https://codecov.io/github/encode/django-rest-framework?branch=master [codecov]: https://codecov.io/github/encode/django-rest-framework?branch=master
[pypi-version]: https://img.shields.io/pypi/v/djangorestframework.svg [pypi-version]: https://img.shields.io/pypi/v/djangorestframework.svg
[pypi]: https://pypi.python.org/pypi/djangorestframework [pypi]: https://pypi.org/project/djangorestframework/
[twitter]: https://twitter.com/_tomchristie
[group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework [group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework
[sandbox]: https://restframework.herokuapp.com/
[funding]: https://fund.django-rest-framework.org/topics/funding/ [funding]: https://fund.django-rest-framework.org/topics/funding/
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors [sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors
[rover-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/rover-readme.png
[sentry-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/sentry-readme.png [sentry-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/sentry-readme.png
[stream-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/stream-readme.png [stream-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/stream-readme.png
[machinalis-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/machinalis-readme.png [spacinov-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/spacinov-readme.png
[rollbar-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/rollbar-readme.png [retool-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/retool-readme.png
[bitio-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/bitio-readme.png
[posthog-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/posthog-readme.png
[cryptapi-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cryptapi-readme.png
[fezto-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/fezto-readme.png
[svix-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/svix-premium.png
[zuplo-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/zuplo-readme.png
[rover-url]: http://jobs.rover.com/
[sentry-url]: https://getsentry.com/welcome/ [sentry-url]: https://getsentry.com/welcome/
[stream-url]: https://getstream.io/try-the-api/?utm_source=drf&utm_medium=banner&utm_campaign=drf [stream-url]: https://getstream.io/?utm_source=DjangoRESTFramework&utm_medium=Webpage_Logo_Ad&utm_content=Developer&utm_campaign=DjangoRESTFramework_Jan2022_HomePage
[machinalis-url]: https://hello.machinalis.co.uk/ [spacinov-url]: https://www.spacinov.com/
[rollbar-url]: https://rollbar.com/ [retool-url]: https://retool.com/?utm_source=djangorest&utm_medium=sponsorship
[bitio-url]: https://bit.io/jobs?utm_source=DRF&utm_medium=sponsor&utm_campaign=DRF_sponsorship
[posthog-url]: https://posthog.com?utm_source=drf&utm_medium=sponsorship&utm_campaign=open-source-sponsorship
[cryptapi-url]: https://cryptapi.io
[fezto-url]: https://www.fezto.xyz/?utm_source=DjangoRESTFramework
[svix-url]: https://www.svix.com/?utm_source=django-REST&utm_medium=sponsorship
[zuplo-url]: https://zuplo.link/django-gh
[oauth1-section]: http://www.django-rest-framework.org/api-guide/authentication/#django-rest-framework-oauth [oauth1-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-rest-framework-oauth
[oauth2-section]: http://www.django-rest-framework.org/api-guide/authentication/#django-oauth-toolkit [oauth2-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-oauth-toolkit
[serializer-section]: http://www.django-rest-framework.org/api-guide/serializers/#serializers [serializer-section]: https://www.django-rest-framework.org/api-guide/serializers/#serializers
[modelserializer-section]: http://www.django-rest-framework.org/api-guide/serializers/#modelserializer [modelserializer-section]: https://www.django-rest-framework.org/api-guide/serializers/#modelserializer
[functionview-section]: http://www.django-rest-framework.org/api-guide/views/#function-based-views [functionview-section]: https://www.django-rest-framework.org/api-guide/views/#function-based-views
[generic-views]: http://www.django-rest-framework.org/api-guide/generic-views/ [generic-views]: https://www.django-rest-framework.org/api-guide/generic-views/
[viewsets]: http://www.django-rest-framework.org/api-guide/viewsets/ [viewsets]: https://www.django-rest-framework.org/api-guide/viewsets/
[routers]: http://www.django-rest-framework.org/api-guide/routers/ [routers]: https://www.django-rest-framework.org/api-guide/routers/
[serializers]: http://www.django-rest-framework.org/api-guide/serializers/ [serializers]: https://www.django-rest-framework.org/api-guide/serializers/
[authentication]: http://www.django-rest-framework.org/api-guide/authentication/ [authentication]: https://www.django-rest-framework.org/api-guide/authentication/
[image]: http://www.django-rest-framework.org/img/quickstart.png [image]: https://www.django-rest-framework.org/img/quickstart.png
[docs]: http://www.django-rest-framework.org/ [docs]: https://www.django-rest-framework.org/
[security-mail]: mailto:rest-framework-security@googlegroups.com [security-policy]: https://github.com/encode/django-rest-framework/security/policy

7
SECURITY.md Normal file
View File

@ -0,0 +1,7 @@
# Security Policy
## Reporting a Vulnerability
**Please report security issues by emailing security@encode.io**.
The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure.

View File

@ -1,7 +1,11 @@
coverage: coverage:
precision: 2
round: down
range: "80...100"
status: status:
project: false project: yes
patch: false patch: no
changes: false changes: no
comment: off comment: off

View File

@ -1,4 +1,7 @@
source: authentication.py ---
source:
- authentication.py
---
# Authentication # Authentication
@ -8,9 +11,9 @@ source: authentication.py
Authentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The [permission] and [throttling] policies can then use those credentials to determine if the request should be permitted. Authentication is the mechanism of associating an incoming request with a set of identifying credentials, such as the user the request came from, or the token that it was signed with. The [permission] and [throttling] policies can then use those credentials to determine if the request should be permitted.
REST framework provides a number of authentication schemes out of the box, and also allows you to implement custom schemes. REST framework provides several authentication schemes out of the box, and also allows you to implement custom schemes.
Authentication is always run at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed. Authentication always runs at the very start of the view, before the permission and throttling checks occur, and before any other code is allowed to proceed.
The `request.user` property will typically be set to an instance of the `contrib.auth` package's `User` class. The `request.user` property will typically be set to an instance of the `contrib.auth` package's `User` class.
@ -20,7 +23,7 @@ The `request.auth` property is used for any additional authentication informatio
**Note:** Don't forget that **authentication by itself won't allow or disallow an incoming request**, it simply identifies the credentials that the request was made with. **Note:** Don't forget that **authentication by itself won't allow or disallow an incoming request**, it simply identifies the credentials that the request was made with.
For information on how to setup the permission polices for your API please see the [permissions documentation][permission]. For information on how to set up the permission policies for your API please see the [permissions documentation][permission].
--- ---
@ -37,10 +40,10 @@ The value of `request.user` and `request.auth` for unauthenticated requests can
The default authentication schemes may be set globally, using the `DEFAULT_AUTHENTICATION_CLASSES` setting. For example. The default authentication schemes may be set globally, using the `DEFAULT_AUTHENTICATION_CLASSES` setting. For example.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ( 'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
) ]
} }
You can also set the authentication scheme on a per-view or per-viewset basis, You can also set the authentication scheme on a per-view or per-viewset basis,
@ -52,25 +55,25 @@ using the `APIView` class-based views.
from rest_framework.views import APIView from rest_framework.views import APIView
class ExampleView(APIView): class ExampleView(APIView):
authentication_classes = (SessionAuthentication, BasicAuthentication) authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = (IsAuthenticated,) permission_classes = [IsAuthenticated]
def get(self, request, format=None): def get(self, request, format=None):
content = { content = {
'user': unicode(request.user), # `django.contrib.auth.User` instance. 'user': str(request.user), # `django.contrib.auth.User` instance.
'auth': unicode(request.auth), # None 'auth': str(request.auth), # None
} }
return Response(content) return Response(content)
Or, if you're using the `@api_view` decorator with function based views. Or, if you're using the `@api_view` decorator with function based views.
@api_view(['GET']) @api_view(['GET'])
@authentication_classes((SessionAuthentication, BasicAuthentication)) @authentication_classes([SessionAuthentication, BasicAuthentication])
@permission_classes((IsAuthenticated,)) @permission_classes([IsAuthenticated])
def example_view(request, format=None): def example_view(request, format=None):
content = { content = {
'user': unicode(request.user), # `django.contrib.auth.User` instance. 'user': str(request.user), # `django.contrib.auth.User` instance.
'auth': unicode(request.auth), # None 'auth': str(request.auth), # None
} }
return Response(content) return Response(content)
@ -87,6 +90,12 @@ The kind of response that will be used depends on the authentication scheme. Al
Note that when a request may successfully authenticate, but still be denied permission to perform the request, in which case a `403 Permission Denied` response will always be used, regardless of the authentication scheme. Note that when a request may successfully authenticate, but still be denied permission to perform the request, in which case a `403 Permission Denied` response will always be used, regardless of the authentication scheme.
## Django 5.1+ `LoginRequiredMiddleware`
If you're running Django 5.1+ and use the [`LoginRequiredMiddleware`][login-required-middleware], please note that all views from DRF are opted-out of this middleware. This is because the authentication in DRF is based authentication and permissions classes, which may be determined after the middleware has been applied. Additionally, when the request is not authenticated, the middleware redirects the user to the login page, which is not suitable for API requests, where it's preferable to return a 401 status code.
REST framework offers an equivalent mechanism for DRF views via the global settings, `DEFAULT_AUTHENTICATION_CLASSES` and `DEFAULT_PERMISSION_CLASSES`. They should be changed accordingly if you need to enforce that API requests are logged in.
## Apache mod_wsgi specific configuration ## Apache mod_wsgi specific configuration
Note that if deploying to [Apache using mod_wsgi][mod_wsgi_official], the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level. Note that if deploying to [Apache using mod_wsgi][mod_wsgi_official], the authorization header is not passed through to a WSGI application by default, as it is assumed that authentication will be handled by Apache, rather than at an application level.
@ -117,33 +126,39 @@ Unauthenticated responses that are denied permission will result in an `HTTP 401
## TokenAuthentication ## TokenAuthentication
---
**Note:** The token authentication provided by Django REST framework is a fairly simple implementation.
For an implementation which allows more than one token per user, has some tighter security implementation details, and supports token expiry, please see the [Django REST Knox][django-rest-knox] third party package.
---
This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients. This authentication scheme uses a simple token-based HTTP Authentication scheme. Token authentication is appropriate for client-server setups, such as native desktop and mobile clients.
To use the `TokenAuthentication` scheme you'll need to [configure the authentication classes](#setting-the-authentication-scheme) to include `TokenAuthentication`, and additionally include `rest_framework.authtoken` in your `INSTALLED_APPS` setting: To use the `TokenAuthentication` scheme you'll need to [configure the authentication classes](#setting-the-authentication-scheme) to include `TokenAuthentication`, and additionally include `rest_framework.authtoken` in your `INSTALLED_APPS` setting:
INSTALLED_APPS = ( INSTALLED_APPS = [
... ...
'rest_framework.authtoken' 'rest_framework.authtoken'
) ]
--- Make sure to run `manage.py migrate` after changing your settings.
**Note:** Make sure to run `manage.py migrate` after changing your settings. The `rest_framework.authtoken` app provides Django database migrations. The `rest_framework.authtoken` app provides Django database migrations.
---
You'll also need to create tokens for your users. You'll also need to create tokens for your users.
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
token = Token.objects.create(user=...) token = Token.objects.create(user=...)
print token.key print(token.key)
For clients to authenticate, the token key should be included in the `Authorization` HTTP header. The key should be prefixed by the string literal "Token", with whitespace separating the two strings. For example: For clients to authenticate, the token key should be included in the `Authorization` HTTP header. The key should be prefixed by the string literal "Token", with whitespace separating the two strings. For example:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
**Note:** If you want to use a different keyword in the header, such as `Bearer`, simply subclass `TokenAuthentication` and set the `keyword` class variable. *If you want to use a different keyword in the header, such as `Bearer`, simply subclass `TokenAuthentication` and set the `keyword` class variable.*
If successfully authenticated, `TokenAuthentication` provides the following credentials. If successfully authenticated, `TokenAuthentication` provides the following credentials.
@ -164,9 +179,9 @@ The `curl` command line tool may be useful for testing token authenticated APIs.
--- ---
#### Generating Tokens ### Generating Tokens
##### By using signals #### By using signals
If you want every user to have an automatically generated Token, you can simply catch the User's `post_save` signal. If you want every user to have an automatically generated Token, you can simply catch the User's `post_save` signal.
@ -190,13 +205,13 @@ If you've already created some users, you can generate tokens for all existing u
for user in User.objects.all(): for user in User.objects.all():
Token.objects.get_or_create(user=user) Token.objects.get_or_create(user=user)
##### By exposing an api endpoint #### By exposing an api endpoint
When using `TokenAuthentication`, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the `obtain_auth_token` view to your URLconf: When using `TokenAuthentication`, you may want to provide a mechanism for clients to obtain a token given the username and password. REST framework provides a built-in view to provide this behavior. To use it, add the `obtain_auth_token` view to your URLconf:
from rest_framework.authtoken import views from rest_framework.authtoken import views
urlpatterns += [ urlpatterns += [
url(r'^api-token-auth/', views.obtain_auth_token) path('api-token-auth/', views.obtain_auth_token)
] ]
Note that the URL part of the pattern can be whatever you want to use. Note that the URL part of the pattern can be whatever you want to use.
@ -207,7 +222,7 @@ The `obtain_auth_token` view will return a JSON response when valid `username` a
Note that the default `obtain_auth_token` view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. Note that the default `obtain_auth_token` view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings.
By default there are no permissions or throttling applied to the `obtain_auth_token` view. If you do wish to apply throttling you'll need to override the view class, By default, there are no permissions or throttling applied to the `obtain_auth_token` view. If you do wish to apply throttling you'll need to override the view class,
and include them using the `throttle_classes` attribute. and include them using the `throttle_classes` attribute.
If you need a customized version of the `obtain_auth_token` view, you can do so by subclassing the `ObtainAuthToken` view class, and using that in your url conf instead. If you need a customized version of the `obtain_auth_token` view, you can do so by subclassing the `ObtainAuthToken` view class, and using that in your url conf instead.
@ -235,19 +250,19 @@ For example, you may return additional user information beyond the `token` value
And in your `urls.py`: And in your `urls.py`:
urlpatterns += [ urlpatterns += [
url(r'^api-token-auth/', CustomAuthToken.as_view()) path('api-token-auth/', CustomAuthToken.as_view())
] ]
##### With Django admin #### With Django admin
It is also possible to create Tokens manually through admin interface. In case you are using a large user base, we recommend that you monkey patch the `TokenAdmin` class to customize it to your needs, more specifically by declaring the `user` field as `raw_field`. It is also possible to create Tokens manually through the admin interface. In case you are using a large user base, we recommend that you monkey patch the `TokenAdmin` class to customize it to your needs, more specifically by declaring the `user` field as `raw_field`.
`your_app/admin.py`: `your_app/admin.py`:
from rest_framework.authtoken.admin import TokenAdmin from rest_framework.authtoken.admin import TokenAdmin
TokenAdmin.raw_id_fields = ('user',) TokenAdmin.raw_id_fields = ['user']
#### Using Django manage.py command #### Using Django manage.py command
@ -276,11 +291,11 @@ If successfully authenticated, `SessionAuthentication` provides the following cr
Unauthenticated responses that are denied permission will result in an `HTTP 403 Forbidden` response. Unauthenticated responses that are denied permission will result in an `HTTP 403 Forbidden` response.
If you're using an AJAX style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as `PUT`, `PATCH`, `POST` or `DELETE` requests. See the [Django CSRF documentation][csrf-ajax] for more details. If you're using an AJAX-style API with SessionAuthentication, you'll need to make sure you include a valid CSRF token for any "unsafe" HTTP method calls, such as `PUT`, `PATCH`, `POST` or `DELETE` requests. See the [Django CSRF documentation][csrf-ajax] for more details.
**Warning**: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected. **Warning**: Always use Django's standard login view when creating login pages. This will ensure your login views are properly protected.
CSRF validation in REST framework works slightly differently to standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behaviour is not suitable for login views, which should always have CSRF validation applied. CSRF validation in REST framework works slightly differently from standard Django due to the need to support both session and non-session based authentication to the same views. This means that only authenticated requests require CSRF tokens, and anonymous requests may be sent without CSRF tokens. This behavior is not suitable for login views, which should always have CSRF validation applied.
## RemoteUserAuthentication ## RemoteUserAuthentication
@ -290,7 +305,7 @@ environment variable.
To use it, you must have `django.contrib.auth.backends.RemoteUserBackend` (or a subclass) in your To use it, you must have `django.contrib.auth.backends.RemoteUserBackend` (or a subclass) in your
`AUTHENTICATION_BACKENDS` setting. By default, `RemoteUserBackend` creates `User` objects for usernames that don't `AUTHENTICATION_BACKENDS` setting. By default, `RemoteUserBackend` creates `User` objects for usernames that don't
already exist. To change this and other behaviour, consult the already exist. To change this and other behavior, consult the
[Django documentation](https://docs.djangoproject.com/en/stable/howto/auth-remote-user/). [Django documentation](https://docs.djangoproject.com/en/stable/howto/auth-remote-user/).
If successfully authenticated, `RemoteUserAuthentication` provides the following credentials: If successfully authenticated, `RemoteUserAuthentication` provides the following credentials:
@ -298,10 +313,10 @@ If successfully authenticated, `RemoteUserAuthentication` provides the following
* `request.user` will be a Django `User` instance. * `request.user` will be a Django `User` instance.
* `request.auth` will be `None`. * `request.auth` will be `None`.
Consult your web server's documentation for information about configuring an authentication method, e.g.: Consult your web server's documentation for information about configuring an authentication method, for example:
* [Apache Authentication How-To](https://httpd.apache.org/docs/2.4/howto/auth.html) * [Apache Authentication How-To](https://httpd.apache.org/docs/2.4/howto/auth.html)
* [NGINX (Restricting Access)](https://www.nginx.com/resources/admin-guide/#restricting_access) * [NGINX (Restricting Access)](https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/)
# Custom authentication # Custom authentication
@ -313,7 +328,7 @@ In some circumstances instead of returning `None`, you may want to raise an `Aut
Typically the approach you should take is: Typically the approach you should take is:
* If authentication is not attempted, return `None`. Any other authentication schemes also in use will still be checked. * If authentication is not attempted, return `None`. Any other authentication schemes also in use will still be checked.
* If authentication is attempted but fails, raise a `AuthenticationFailed` exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes. * If authentication is attempted but fails, raise an `AuthenticationFailed` exception. An error response will be returned immediately, regardless of any permissions checks, and without checking any other authentication schemes.
You *may* also override the `.authenticate_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthorized` response. You *may* also override the `.authenticate_header(self, request)` method. If implemented, it should return a string that will be used as the value of the `WWW-Authenticate` header in a `HTTP 401 Unauthorized` response.
@ -321,21 +336,21 @@ If the `.authenticate_header()` method is not overridden, the authentication sch
--- ---
**Note:** When your custom authenticator is invoked by the request object's `.user` or `.auth` properties, you may see an `AttributeError` re-raised as a `WrappedAttributeError`. This is necessary to prevent the original exception from being suppressed by the outer property access. Python will not recognize that the `AttributeError` orginates from your custom authenticator and will instead assume that the request object does not have a `.user` or `.auth` property. These errors should be fixed or otherwise handled by your authenticator. **Note:** When your custom authenticator is invoked by the request object's `.user` or `.auth` properties, you may see an `AttributeError` re-raised as a `WrappedAttributeError`. This is necessary to prevent the original exception from being suppressed by the outer property access. Python will not recognize that the `AttributeError` originates from your custom authenticator and will instead assume that the request object does not have a `.user` or `.auth` property. These errors should be fixed or otherwise handled by your authenticator.
--- ---
## Example ## Example
The following example will authenticate any incoming request as the user given by the username in a custom request header named 'X_USERNAME'. The following example will authenticate any incoming request as the user given by the username in a custom request header named 'X-USERNAME'.
from django.contrib.auth.models import User from django.contrib.auth.models import User
from rest_framework import authentication from rest_framework import authentication
from rest_framework import exceptions from rest_framework import exceptions
class ExampleAuthentication(authentication.BaseAuthentication): class ExampleAuthentication(authentication.BaseAuthentication):
def authenticate(self, request): def authenticate(self, request):
username = request.META.get('X_USERNAME') username = request.META.get('HTTP_X_USERNAME')
if not username: if not username:
return None return None
@ -350,13 +365,17 @@ The following example will authenticate any incoming request as the user given b
# Third party packages # Third party packages
The following third party packages are also available. The following third-party packages are also available.
## django-rest-knox
[Django-rest-knox][django-rest-knox] library provides models and views to handle token-based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into).
## Django OAuth Toolkit ## Django OAuth Toolkit
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 excellent [OAuthLib][oauthlib]. The package is well documented, and well supported and is currently our **recommended package for OAuth 2.0 support**. The [Django OAuth Toolkit][django-oauth-toolkit] package provides OAuth 2.0 support and works with Python 3.4+. The package is maintained by [jazzband][jazzband] and uses the excellent [OAuthLib][oauthlib]. The package is well documented, and well supported and is currently our **recommended package for OAuth 2.0 support**.
#### Installation & configuration ### Installation & configuration
Install using `pip`. Install using `pip`.
@ -364,15 +383,15 @@ Install using `pip`.
Add the package to your `INSTALLED_APPS` and modify your REST framework settings. Add the package to your `INSTALLED_APPS` and modify your REST framework settings.
INSTALLED_APPS = ( INSTALLED_APPS = [
... ...
'oauth2_provider', 'oauth2_provider',
) ]
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ( 'DEFAULT_AUTHENTICATION_CLASSES': [
'oauth2_provider.contrib.rest_framework.OAuth2Authentication', 'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
) ]
} }
For more details see the [Django REST framework - Getting started][django-oauth-toolkit-getting-started] documentation. For more details see the [Django REST framework - Getting started][django-oauth-toolkit-getting-started] documentation.
@ -381,9 +400,9 @@ For more details see the [Django REST framework - Getting started][django-oauth-
The [Django REST framework OAuth][django-rest-framework-oauth] package provides both OAuth1 and OAuth2 support for REST framework. The [Django REST framework OAuth][django-rest-framework-oauth] package provides both OAuth1 and OAuth2 support for REST framework.
This package was previously included directly in REST framework but is now supported and maintained as a third party package. This package was previously included directly in the REST framework but is now supported and maintained as a third-party package.
#### Installation & configuration ### Installation & configuration
Install the package using `pip`. Install the package using `pip`.
@ -391,17 +410,9 @@ Install the package using `pip`.
For details on configuration and usage see the Django REST framework OAuth documentation for [authentication][django-rest-framework-oauth-authentication] and [permissions][django-rest-framework-oauth-permissions]. For details on configuration and usage see the Django REST framework OAuth documentation for [authentication][django-rest-framework-oauth-authentication] and [permissions][django-rest-framework-oauth-permissions].
## Digest Authentication
HTTP digest authentication is a widely implemented scheme that was intended to replace HTTP basic authentication, and which provides a simple encrypted authentication mechanism. [Juan Riaza][juanriaza] maintains the [djangorestframework-digestauth][djangorestframework-digestauth] package which provides HTTP digest authentication support for REST framework.
## 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.
## JSON Web Token Authentication ## JSON Web Token Authentication
JSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token. [Blimp][blimp] maintains the [djangorestframework-jwt][djangorestframework-jwt] package which provides a JWT Authentication class as well as a mechanism for clients to obtain a JWT given the username and password. An alternative package for JWT authentication is [djangorestframework-simplejwt][djangorestframework-simplejwt] which provides different features as well as a pluggable token blacklist app. JSON Web Token is a fairly new standard which can be used for token-based authentication. Unlike the built-in TokenAuthentication scheme, JWT Authentication doesn't need to use a database to validate a token. A package for JWT authentication is [djangorestframework-simplejwt][djangorestframework-simplejwt] which provides some features as well as a pluggable token blacklist app.
## Hawk HTTP Authentication ## Hawk HTTP Authentication
@ -409,27 +420,45 @@ The [HawkREST][hawkrest] library builds on the [Mohawk][mohawk] library to let y
## HTTP Signature Authentication ## HTTP Signature Authentication
HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to [Amazon's HTTP Signature scheme][amazon-http-signature], used by many of its services, it permits stateless, per-request authentication. [Elvio Toccalino][etoccalino] maintains the [djangorestframework-httpsignature][djangorestframework-httpsignature] package which provides an easy to use HTTP Signature Authentication mechanism. HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a way to achieve origin authentication and message integrity for HTTP messages. Similar to [Amazon's HTTP Signature scheme][amazon-http-signature], used by many of its services, it permits stateless, per-request authentication. [Elvio Toccalino][etoccalino] maintains the [djangorestframework-httpsignature][djangorestframework-httpsignature] (outdated) package which provides an easy-to-use HTTP Signature Authentication mechanism. You can use the updated fork version of [djangorestframework-httpsignature][djangorestframework-httpsignature], which is [drf-httpsig][drf-httpsig].
## Djoser ## Djoser
[Djoser][djoser] library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and it uses token based authentication. This is a ready to use REST implementation of Django authentication system. [Djoser][djoser] library provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. The package works with a custom user model and uses token-based authentication. This is a ready to use REST implementation of the Django authentication system.
## django-rest-auth ## django-rest-auth / dj-rest-auth
[Django-rest-auth][django-rest-auth] library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management. This library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management.
## django-rest-framework-social-oauth2
[Django-rest-framework-social-oauth2][django-rest-framework-social-oauth2] library provides an easy way to integrate social plugins (facebook, twitter, google, etc.) to your authentication system and an easy oauth2 setup. With this library, you will be able to authenticate users based on external tokens (e.g. facebook access token), convert these tokens to "in-house" oauth2 tokens and use and generate oauth2 tokens to authenticate your users. There are currently two forks of this project.
## django-rest-knox * [Django-rest-auth][django-rest-auth] is the original project, [but is not currently receiving updates](https://github.com/Tivix/django-rest-auth/issues/568).
* [Dj-rest-auth][dj-rest-auth] is a newer fork of the project.
[Django-rest-knox][django-rest-knox] library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into). ## drf-social-oauth2
[Drf-social-oauth2][drf-social-oauth2] is a framework that helps you authenticate with major social oauth2 vendors, such as Facebook, Google, Twitter, Orcid, etc. It generates tokens in a JWTed way with an easy setup.
## drfpasswordless ## drfpasswordless
[drfpasswordless][drfpasswordless] adds (Medium, Square Cash inspired) passwordless support to Django REST Framework's own TokenAuthentication scheme. Users log in and sign up with a token sent to a contact point like an email address or a mobile number. [drfpasswordless][drfpasswordless] adds (Medium, Square Cash inspired) passwordless support to Django REST Framework's TokenAuthentication scheme. Users log in and sign up with a token sent to a contact point like an email address or a mobile number.
## django-rest-authemail
[django-rest-authemail][django-rest-authemail] provides a RESTful API interface for user signup and authentication. Email addresses are used for authentication, rather than usernames. API endpoints are available for signup, signup email verification, login, logout, password reset, password reset verification, email change, email change verification, password change, and user detail. A fully functional example project and detailed instructions are included.
## Django-Rest-Durin
[Django-Rest-Durin][django-rest-durin] is built with the idea to have one library that does token auth for multiple Web/CLI/Mobile API clients via one interface but allows different token configuration for each API Client that consumes the API. It provides support for multiple tokens per user via custom models, views, permissions that work with Django-Rest-Framework. The token expiration time can be different per API client and is customizable via the Django Admin Interface.
More information can be found in the [Documentation](https://django-rest-durin.readthedocs.io/en/latest/index.html).
## django-pyoidc
[dango-pyoidc][django_pyoidc] adds support for OpenID Connect (OIDC) authentication. This allows you to delegate user management to an Identity Provider, which can be used to implement Single-Sign-On (SSO). It provides support for most uses-cases, such as customizing how token info are mapped to user models, using OIDC audiences for access control, etc.
More information can be found in the [Documentation](https://django-pyoidc.readthedocs.io/latest/index.html).
[cite]: https://jacobian.org/writing/rest-worst-practices/ [cite]: https://jacobian.org/writing/rest-worst-practices/
[http401]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 [http401]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
@ -437,7 +466,7 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a
[basicauth]: https://tools.ietf.org/html/rfc2617 [basicauth]: https://tools.ietf.org/html/rfc2617
[permission]: permissions.md [permission]: permissions.md
[throttling]: throttling.md [throttling]: throttling.md
[csrf-ajax]: https://docs.djangoproject.com/en/stable/ref/csrf/#ajax [csrf-ajax]: https://docs.djangoproject.com/en/stable/howto/csrf/#using-csrf-protection-with-ajax
[mod_wsgi_official]: https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIPassAuthorization.html [mod_wsgi_official]: https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIPassAuthorization.html
[django-oauth-toolkit-getting-started]: https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html [django-oauth-toolkit-getting-started]: https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html
[django-rest-framework-oauth]: https://jpadilla.github.io/django-rest-framework-oauth/ [django-rest-framework-oauth]: https://jpadilla.github.io/django-rest-framework-oauth/
@ -447,16 +476,12 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a
[djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth
[oauth-1.0a]: https://oauth.net/core/1.0a/ [oauth-1.0a]: https://oauth.net/core/1.0a/
[django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit [django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit
[evonove]: https://github.com/evonove/ [jazzband]: https://github.com/jazzband/
[oauthlib]: https://github.com/idan/oauthlib [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/integrations.md#
[blimp]: https://github.com/GetBlimp
[djangorestframework-jwt]: https://github.com/GetBlimp/django-rest-framework-jwt
[djangorestframework-simplejwt]: https://github.com/davesque/django-rest-framework-simplejwt [djangorestframework-simplejwt]: https://github.com/davesque/django-rest-framework-simplejwt
[etoccalino]: https://github.com/etoccalino/ [etoccalino]: https://github.com/etoccalino/
[djangorestframework-httpsignature]: https://github.com/etoccalino/django-rest-framework-httpsignature [djangorestframework-httpsignature]: https://github.com/etoccalino/django-rest-framework-httpsignature
[drf-httpsig]: https://github.com/ahknight/drf-httpsig
[amazon-http-signature]: https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html [amazon-http-signature]: https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
[http-signature-ietf-draft]: https://datatracker.ietf.org/doc/draft-cavage-http-signatures/ [http-signature-ietf-draft]: https://datatracker.ietf.org/doc/draft-cavage-http-signatures/
[hawkrest]: https://hawkrest.readthedocs.io/en/latest/ [hawkrest]: https://hawkrest.readthedocs.io/en/latest/
@ -465,6 +490,11 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a
[mac]: https://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05 [mac]: https://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05
[djoser]: https://github.com/sunscrapers/djoser [djoser]: https://github.com/sunscrapers/djoser
[django-rest-auth]: https://github.com/Tivix/django-rest-auth [django-rest-auth]: https://github.com/Tivix/django-rest-auth
[django-rest-framework-social-oauth2]: https://github.com/PhilipGarnero/django-rest-framework-social-oauth2 [dj-rest-auth]: https://github.com/jazzband/dj-rest-auth
[drf-social-oauth2]: https://github.com/wagnerdelima/drf-social-oauth2
[django-rest-knox]: https://github.com/James1345/django-rest-knox [django-rest-knox]: https://github.com/James1345/django-rest-knox
[drfpasswordless]: https://github.com/aaronn/django-rest-framework-passwordless [drfpasswordless]: https://github.com/aaronn/django-rest-framework-passwordless
[django-rest-authemail]: https://github.com/celiao/django-rest-authemail
[django-rest-durin]: https://github.com/eshaan7/django-rest-durin
[login-required-middleware]: https://docs.djangoproject.com/en/stable/ref/middleware/#django.contrib.auth.middleware.LoginRequiredMiddleware
[django-pyoidc] : https://github.com/makinacorpus/django_pyoidc

View File

@ -1,6 +1,6 @@
# Caching # Caching
> A certain woman had a very sharp conciousness but almost no > A certain woman had a very sharp consciousness but almost no
> memory ... She remembered enough to work, and she worked hard. > memory ... She remembered enough to work, and she worked hard.
> - Lydia Davis > - Lydia Davis
@ -13,40 +13,79 @@ provided in Django.
Django provides a [`method_decorator`][decorator] to use Django provides a [`method_decorator`][decorator] to use
decorators with class based views. This can be used with decorators with class based views. This can be used with
with other cache decorators such as [`cache_page`][page] and other cache decorators such as [`cache_page`][page],
[`vary_on_cookie`][cookie]. [`vary_on_cookie`][cookie] and [`vary_on_headers`][headers].
```python ```python
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie, vary_on_headers
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework import viewsets from rest_framework import viewsets
class UserViewSet(viewsets.Viewset):
# Cache requested url for each user for 2 hours class UserViewSet(viewsets.ViewSet):
@method_decorator(cache_page(60*60*2)) # With cookie: cache requested url for each user for 2 hours
@method_decorator(cache_page(60 * 60 * 2))
@method_decorator(vary_on_cookie) @method_decorator(vary_on_cookie)
def list(self, request, format=None): def list(self, request, format=None):
content = { content = {
'user_feed': request.user.get_user_feed() "user_feed": request.user.get_user_feed(),
} }
return Response(content) return Response(content)
class PostView(APIView):
# Cache page for the requested url class ProfileView(APIView):
@method_decorator(cache_page(60*60*2)) # With auth: cache requested url for each user for 2 hours
@method_decorator(cache_page(60 * 60 * 2))
@method_decorator(vary_on_headers("Authorization"))
def get(self, request, format=None): def get(self, request, format=None):
content = { content = {
'title': 'Post title', "user_feed": request.user.get_user_feed(),
'body': 'Post content' }
return Response(content)
class PostView(APIView):
# Cache page for the requested url
@method_decorator(cache_page(60 * 60 * 2))
def get(self, request, format=None):
content = {
"title": "Post title",
"body": "Post content",
} }
return Response(content) return Response(content)
``` ```
## Using cache with @api_view decorator
When using @api_view decorator, the Django-provided method-based cache decorators such as [`cache_page`][page],
[`vary_on_cookie`][cookie] and [`vary_on_headers`][headers] can be called directly.
```python
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie
from rest_framework.decorators import api_view
from rest_framework.response import Response
@cache_page(60 * 15)
@vary_on_cookie
@api_view(["GET"])
def get_user_list(request):
content = {"user_feed": request.user.get_user_feed()}
return Response(content)
```
**NOTE:** The [`cache_page`][page] decorator only caches the **NOTE:** The [`cache_page`][page] decorator only caches the
`GET` and `HEAD` responses with status 200. `GET` and `HEAD` responses with status 200.
[page]: https://docs.djangoproject.com/en/dev/topics/cache/#the-per-view-cache [page]: https://docs.djangoproject.com/en/stable/topics/cache/#the-per-view-cache
[cookie]: https://docs.djangoproject.com/en/dev/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie [cookie]: https://docs.djangoproject.com/en/stable/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie
[decorator]: https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/#decorating-the-class [headers]: https://docs.djangoproject.com/en/stable/topics/http/decorators/#django.views.decorators.vary.vary_on_headers
[decorator]: https://docs.djangoproject.com/en/stable/topics/class-based-views/intro/#decorating-the-class

View File

@ -1,4 +1,7 @@
source: negotiation.py ---
source:
- negotiation.py
---
# Content negotiation # Content negotiation
@ -79,7 +82,7 @@ The default content negotiation class may be set globally, using the `DEFAULT_CO
You can also set the content negotiation used for an individual view, or viewset, using the `APIView` class-based views. You can also set the content negotiation used for an individual view, or viewset, using the `APIView` class-based views.
from myapp.negotiation import IgnoreClientContentNegotiation from myapp.negotiation import IgnoreClientContentNegotiation
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView

View File

@ -1,4 +1,7 @@
source: exceptions.py ---
source:
- exceptions.py
---
# Exceptions # Exceptions
@ -35,7 +38,7 @@ Might receive an error response indicating that the `DELETE` method is not allow
Validation errors are handled slightly differently, and will include the field names as the keys in the response. If the validation error was not specific to a particular field then it will use the "non_field_errors" key, or whatever string value has been set for the `NON_FIELD_ERRORS_KEY` setting. Validation errors are handled slightly differently, and will include the field names as the keys in the response. If the validation error was not specific to a particular field then it will use the "non_field_errors" key, or whatever string value has been set for the `NON_FIELD_ERRORS_KEY` setting.
Any example validation error might look like this: An example validation error might look like this:
HTTP/1.1 400 Bad Request HTTP/1.1 400 Bad Request
Content-Type: application/json Content-Type: application/json
@ -98,7 +101,7 @@ Note that the exception handler will only be called for responses generated by r
The **base class** for all exceptions raised inside an `APIView` class or `@api_view`. The **base class** for all exceptions raised inside an `APIView` class or `@api_view`.
To provide a custom exception, subclass `APIException` and set the `.status_code`, `.default_detail`, and `default_code` attributes on the class. To provide a custom exception, subclass `APIException` and set the `.status_code`, `.default_detail`, and `.default_code` attributes on the class.
For example, if your API relies on a third party service that may sometimes be unreachable, you might want to implement an exception for the "503 Service Unavailable" HTTP response code. You could do this like so: For example, if your API relies on a third party service that may sometimes be unreachable, you might want to implement an exception for the "503 Service Unavailable" HTTP response code. You could do this like so:
@ -176,7 +179,7 @@ By default this exception results in a response with the HTTP status code "403 F
**Signature:** `NotFound(detail=None, code=None)` **Signature:** `NotFound(detail=None, code=None)`
Raised when a resource does not exists at the given URL. This exception is equivalent to the standard `Http404` Django exception. Raised when a resource does not exist at the given URL. This exception is equivalent to the standard `Http404` Django exception.
By default this exception results in a response with the HTTP status code "404 Not Found". By default this exception results in a response with the HTTP status code "404 Not Found".
@ -214,12 +217,11 @@ By default this exception results in a response with the HTTP status code "429 T
## ValidationError ## ValidationError
**Signature:** `ValidationError(detail, code=None)` **Signature:** `ValidationError(detail=None, code=None)`
The `ValidationError` exception is slightly different from the other `APIException` classes: 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 using a dictionary, you can specify field-level errors while performing object-level validation in the `validate()` method of a serializer. For example. `raise serializers.ValidationError({'name': 'Please enter a valid name.'})`
* 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.')` * 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: 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:
@ -249,7 +251,7 @@ Set as `handler500`:
handler500 = 'rest_framework.exceptions.server_error' handler500 = 'rest_framework.exceptions.server_error'
## `rest_framework.exceptions.server_error` ## `rest_framework.exceptions.bad_request`
Returns a response with status code `400` and `application/json` content type. Returns a response with status code `400` and `application/json` content type.
@ -257,6 +259,15 @@ Set as `handler400`:
handler400 = 'rest_framework.exceptions.bad_request' handler400 = 'rest_framework.exceptions.bad_request'
# Third party packages
The following third-party packages are also available.
## DRF Standardized Errors
The [drf-standardized-errors][drf-standardized-errors] package provides an exception handler that generates the same format for all 4xx and 5xx responses. It is a drop-in replacement for the default exception handler and allows customizing the error response format without rewriting the whole exception handler. The standardized error response format is easier to document and easier to handle by API consumers.
[cite]: https://doughellmann.com/blog/2009/06/19/python-exception-handling-techniques/ [cite]: https://doughellmann.com/blog/2009/06/19/python-exception-handling-techniques/
[authentication]: authentication.md [authentication]: authentication.md
[django-custom-error-views]: https://docs.djangoproject.com/en/dev/topics/http/views/#customizing-error-views [django-custom-error-views]: https://docs.djangoproject.com/en/stable/topics/http/views/#customizing-error-views
[drf-standardized-errors]: https://github.com/ghazi-git/drf-standardized-errors

View File

@ -1,4 +1,7 @@
source: fields.py ---
source:
- fields.py
---
# Serializer fields # Serializer fields
@ -39,17 +42,29 @@ Set to false if this field is not required to be present during deserialization.
Setting this to `False` also allows the object attribute or dictionary key to be omitted from output when serializing the instance. If the key is not present it will simply not be included in the output representation. Setting this to `False` also allows the object attribute or dictionary key to be omitted from output when serializing the instance. If the key is not present it will simply not be included in the output representation.
Defaults to `True`. Defaults to `True`. If you're using [Model Serializer](https://www.django-rest-framework.org/api-guide/serializers/#modelserializer), the default value will be `False` when you have specified a `default`, or when the corresponding `Model` field has `blank=True` or `null=True` and is not part of a unique constraint at the same time. (Note that without a `default` value, [unique constraints will cause the field to be required](https://www.django-rest-framework.org/api-guide/validators/#optional-fields).)
### `default` ### `default`
If set, this gives the default value that will be used for the field if no input value is supplied. If not set the default behaviour is to not populate the attribute at all. If set, this gives the default value that will be used for the field if no input value is supplied. If not set the default behavior is to not populate the attribute at all.
The `default` is not applied during partial update operations. In the partial update case only fields that are provided in the incoming data will have a validated value returned. The `default` is not applied during partial update operations. In the partial update case only fields that are provided in the incoming data will have a validated value returned.
May be set to a function or other callable, in which case the value will be evaluated each time it is used. When called, it will receive no arguments. If the callable has a `set_context` method, that will be called each time before getting the value with the field instance as only argument. This works the same way as for [validators](validators.md#using-set_context). May be set to a function or other callable, in which case the value will be evaluated each time it is used. When called, it will receive no arguments. If the callable has a `requires_context = True` attribute, then the serializer field will be passed as an argument.
When serializing the instance, default will be used if the the object attribute or dictionary key is not present in the instance. For example:
class CurrentUserDefault:
"""
May be applied as a `default=...` value on a serializer field.
Returns the current user.
"""
requires_context = True
def __call__(self, serializer_field):
return serializer_field.context['request'].user
When serializing the instance, default will be used if the object attribute or dictionary key is not present in the instance.
Note that setting a `default` value implies that the field is not required. Including both the `default` and `required` keyword arguments is invalid and will raise an error. Note that setting a `default` value implies that the field is not required. Including both the `default` and `required` keyword arguments is invalid and will raise an error.
@ -63,7 +78,14 @@ Defaults to `False`
### `source` ### `source`
The name of the attribute that will be used to populate the field. May be a method that only takes a `self` argument, such as `URLField(source='get_absolute_url')`, or may use dotted notation to traverse attributes, such as `EmailField(source='user.email')`. When serializing fields with dotted notation, it may be necessary to provide a `default` value if any object is not present or is empty during attribute traversal. The name of the attribute that will be used to populate the field. May be a method that only takes a `self` argument, such as `URLField(source='get_absolute_url')`, or may use dotted notation to traverse attributes, such as `EmailField(source='user.email')`.
When serializing fields with dotted notation, it may be necessary to provide a `default` value if any object is not present or is empty during attribute traversal. Beware of possible n+1 problems when using source attribute if you are accessing a relational orm model. For example:
class CommentSerializer(serializers.Serializer):
email = serializers.EmailField(source="user.email")
This case would require user object to be fetched from database when it is not prefetched. If that is not wanted, be sure to be using `prefetch_related` and `select_related` methods appropriately. For more information about the methods refer to [django documentation][django-docs-select-related].
The value `source='*'` has a special meaning, and is used to indicate that the entire object should be passed through to the field. This can be useful for creating nested representations, or for fields which require access to the complete object in order to determine the output representation. The value `source='*'` has a special meaning, and is used to indicate that the entire object should be passed through to the field. This can be useful for creating nested representations, or for fields which require access to the complete object in order to determine the output representation.
@ -124,20 +146,19 @@ A boolean representation.
When using HTML encoded form input be aware that omitting a value will always be treated as setting a field to `False`, even if it has a `default=True` option specified. This is because HTML checkbox inputs represent the unchecked state by omitting the value, so REST framework treats omission as if it is an empty checkbox input. When using HTML encoded form input be aware that omitting a value will always be treated as setting a field to `False`, even if it has a `default=True` option specified. This is because HTML checkbox inputs represent the unchecked state by omitting the value, so REST framework treats omission as if it is an empty checkbox input.
Note that default `BooleanField` instances will be generated with a `required=False` option (since Django `models.BooleanField` is always `blank=True`). If you want to change this behaviour explicitly declare the `BooleanField` on the serializer class. Note that Django 2.1 removed the `blank` kwarg from `models.BooleanField`.
Prior to Django 2.1 `models.BooleanField` fields were always `blank=True`. Thus
since Django 2.1 default `serializers.BooleanField` instances will be generated
without the `required` kwarg (i.e. equivalent to `required=True`) whereas with
previous versions of Django, default `BooleanField` instances will be generated
with a `required=False` option. If you want to control this behavior manually,
explicitly declare the `BooleanField` on the serializer class, or use the
`extra_kwargs` option to set the `required` flag.
Corresponds to `django.db.models.fields.BooleanField`. Corresponds to `django.db.models.fields.BooleanField`.
**Signature:** `BooleanField()` **Signature:** `BooleanField()`
## NullBooleanField
A boolean representation that also accepts `None` as a valid value.
Corresponds to `django.db.models.fields.NullBooleanField`.
**Signature:** `NullBooleanField()`
--- ---
# String fields # String fields
@ -150,10 +171,10 @@ Corresponds to `django.db.models.fields.CharField` or `django.db.models.fields.T
**Signature:** `CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)` **Signature:** `CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)`
- `max_length` - Validates that the input contains no more than this number of characters. * `max_length` - Validates that the input contains no more than this number of characters.
- `min_length` - Validates that the input contains no fewer than this number of characters. * `min_length` - Validates that the input contains no fewer than this number of characters.
- `allow_blank` - If set to `True` then the empty string should be considered a valid value. If set to `False` then the empty string is considered invalid and will raise a validation error. Defaults to `False`. * `allow_blank` - If set to `True` then the empty string should be considered a valid value. If set to `False` then the empty string is considered invalid and will raise a validation error. Defaults to `False`.
- `trim_whitespace` - If set to `True` then leading and trailing whitespace is trimmed. Defaults to `True`. * `trim_whitespace` - If set to `True` then leading and trailing whitespace is trimmed. Defaults to `True`.
The `allow_null` option is also available for string fields, although its usage is discouraged in favor of `allow_blank`. It is valid to set both `allow_blank=True` and `allow_null=True`, but doing so means that there will be two differing types of empty value permissible for string representations, which can lead to data inconsistencies and subtle application bugs. The `allow_null` option is also available for string fields, although its usage is discouraged in favor of `allow_blank`. It is valid to set both `allow_blank=True` and `allow_null=True`, but doing so means that there will be two differing types of empty value permissible for string representations, which can lead to data inconsistencies and subtle application bugs.
@ -201,11 +222,11 @@ A field that ensures the input is a valid UUID string. The `to_internal_value` m
**Signature:** `UUIDField(format='hex_verbose')` **Signature:** `UUIDField(format='hex_verbose')`
- `format`: Determines the representation format of the uuid value * `format`: Determines the representation format of the uuid value
- `'hex_verbose'` - The cannoncical hex representation, including hyphens: `"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"` * `'hex_verbose'` - The canonical hex representation, including hyphens: `"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"`
- `'hex'` - The compact hex representation of the UUID, not including hyphens: `"5ce0e9a55ffa654bcee01238041fb31a"` * `'hex'` - The compact hex representation of the UUID, not including hyphens: `"5ce0e9a55ffa654bcee01238041fb31a"`
- `'int'` - A 128 bit integer representation of the UUID: `"123456789012312313134124512351145145114"` * `'int'` - A 128 bit integer representation of the UUID: `"123456789012312313134124512351145145114"`
- `'urn'` - RFC 4122 URN representation of the UUID: `"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"` * `'urn'` - RFC 4122 URN representation of the UUID: `"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"`
Changing the `format` parameters only affects representation values. All formats are accepted by `to_internal_value` Changing the `format` parameters only affects representation values. All formats are accepted by `to_internal_value`
## FilePathField ## FilePathField
@ -216,11 +237,11 @@ Corresponds to `django.forms.fields.FilePathField`.
**Signature:** `FilePathField(path, match=None, recursive=False, allow_files=True, allow_folders=False, required=None, **kwargs)` **Signature:** `FilePathField(path, match=None, recursive=False, allow_files=True, allow_folders=False, required=None, **kwargs)`
- `path` - The absolute filesystem path to a directory from which this FilePathField should get its choice. * `path` - The absolute filesystem path to a directory from which this FilePathField should get its choice.
- `match` - A regular expression, as a string, that FilePathField will use to filter filenames. * `match` - A regular expression, as a string, that FilePathField will use to filter filenames.
- `recursive` - Specifies whether all subdirectories of path should be included. Default is `False`. * `recursive` - Specifies whether all subdirectories of path should be included. Default is `False`.
- `allow_files` - Specifies whether files in the specified location should be included. Default is `True`. Either this or `allow_folders` must be `True`. * `allow_files` - Specifies whether files in the specified location should be included. Default is `True`. Either this or `allow_folders` must be `True`.
- `allow_folders` - Specifies whether folders in the specified location should be included. Default is `False`. Either this or `allow_files` must be `True`. * `allow_folders` - Specifies whether folders in the specified location should be included. Default is `False`. Either this or `allow_files` must be `True`.
## IPAddressField ## IPAddressField
@ -230,8 +251,8 @@ Corresponds to `django.forms.fields.IPAddressField` and `django.forms.fields.Gen
**Signature**: `IPAddressField(protocol='both', unpack_ipv4=False, **options)` **Signature**: `IPAddressField(protocol='both', unpack_ipv4=False, **options)`
- `protocol` Limits valid inputs to the specified protocol. Accepted values are 'both' (default), 'IPv4' or 'IPv6'. Matching is case insensitive. * `protocol` Limits valid inputs to the specified protocol. Accepted values are 'both' (default), 'IPv4' or 'IPv6'. Matching is case-insensitive.
- `unpack_ipv4` Unpacks IPv4 mapped addresses like ::ffff:192.0.2.1. If this option is enabled that address would be unpacked to 192.0.2.1. Default is disabled. Can only be used when protocol is set to 'both'. * `unpack_ipv4` Unpacks IPv4 mapped addresses like ::ffff:192.0.2.1. If this option is enabled that address would be unpacked to 192.0.2.1. Default is disabled. Can only be used when protocol is set to 'both'.
--- ---
@ -245,8 +266,8 @@ Corresponds to `django.db.models.fields.IntegerField`, `django.db.models.fields.
**Signature**: `IntegerField(max_value=None, min_value=None)` **Signature**: `IntegerField(max_value=None, min_value=None)`
- `max_value` Validate that the number provided is no greater than this value. * `max_value` Validate that the number provided is no greater than this value.
- `min_value` Validate that the number provided is no less than this value. * `min_value` Validate that the number provided is no less than this value.
## FloatField ## FloatField
@ -256,8 +277,8 @@ Corresponds to `django.db.models.fields.FloatField`.
**Signature**: `FloatField(max_value=None, min_value=None)` **Signature**: `FloatField(max_value=None, min_value=None)`
- `max_value` Validate that the number provided is no greater than this value. * `max_value` Validate that the number provided is no greater than this value.
- `min_value` Validate that the number provided is no less than this value. * `min_value` Validate that the number provided is no less than this value.
## DecimalField ## DecimalField
@ -267,13 +288,14 @@ Corresponds to `django.db.models.fields.DecimalField`.
**Signature**: `DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)` **Signature**: `DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)`
- `max_digits` The maximum number of digits allowed in the number. It must be either `None` or an integer greater than or equal to `decimal_places`. * `max_digits` The maximum number of digits allowed in the number. It must be either `None` or an integer greater than or equal to `decimal_places`.
- `decimal_places` The number of decimal places to store with the number. * `decimal_places` The number of decimal places to store with the number.
- `coerce_to_string` Set to `True` if string values should be returned for the representation, or `False` if `Decimal` objects should be returned. Defaults to the same value as the `COERCE_DECIMAL_TO_STRING` settings key, which will be `True` unless overridden. If `Decimal` objects are returned by the serializer, then the final output format will be determined by the renderer. Note that setting `localize` will force the value to `True`. * `coerce_to_string` Set to `True` if string values should be returned for the representation, or `False` if `Decimal` objects should be returned. Defaults to the same value as the `COERCE_DECIMAL_TO_STRING` settings key, which will be `True` unless overridden. If `Decimal` objects are returned by the serializer, then the final output format will be determined by the renderer. Note that setting `localize` will force the value to `True`.
- `max_value` Validate that the number provided is no greater than this value. * `max_value` Validate that the number provided is no greater than this value. Should be an integer or `Decimal` object.
- `min_value` Validate that the number provided is no less than this value. * `min_value` Validate that the number provided is no less than this value. Should be an integer or `Decimal` object.
- `localize` Set to `True` to enable localization of input and output based on the current locale. This will also force `coerce_to_string` to `True`. Defaults to `False`. Note that data formatting is enabled if you have set `USE_L10N=True` in your settings file. * `localize` Set to `True` to enable localization of input and output based on the current locale. This will also force `coerce_to_string` to `True`. Defaults to `False`. Note that data formatting is enabled if you have set `USE_L10N=True` in your settings file.
- `rounding` Sets the rounding mode used when quantising to the configured precision. Valid values are [`decimal` module rounding modes][python-decimal-rounding-modes]. Defaults to `None`. * `rounding` Sets the rounding mode used when quantizing to the configured precision. Valid values are [`decimal` module rounding modes][python-decimal-rounding-modes]. Defaults to `None`.
* `normalize_output` Will normalize the decimal value when serialized. This will strip all trailing zeroes and change the value's precision to the minimum required precision to be able to represent the value without losing data. Defaults to `False`.
#### Example usage #### Example usage
@ -285,10 +307,6 @@ And to validate numbers up to anything less than one billion with a resolution o
serializers.DecimalField(max_digits=19, decimal_places=10) serializers.DecimalField(max_digits=19, decimal_places=10)
This field also takes an optional argument, `coerce_to_string`. If set to `True` the representation will be output as a string. If set to `False` the representation will be left as a `Decimal` instance and the final representation will be determined by the renderer.
If unset, this will default to the same value as the `COERCE_DECIMAL_TO_STRING` setting, which is `True` unless set otherwise.
--- ---
# Date and time fields # Date and time fields
@ -299,16 +317,17 @@ A date and time representation.
Corresponds to `django.db.models.fields.DateTimeField`. Corresponds to `django.db.models.fields.DateTimeField`.
**Signature:** `DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)` **Signature:** `DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None, default_timezone=None)`
* `format` - A string representing the output format. If not specified, this defaults to the same value as the `DATETIME_FORMAT` settings key, which will be `'iso-8601'` unless set. Setting to a format string indicates that `to_representation` return values should be coerced to string output. Format strings are described below. Setting this value to `None` indicates that Python `datetime` objects should be returned by `to_representation`. In this case the datetime encoding will be determined by the renderer. * `format` - A string representing the output format. If not specified, this defaults to the same value as the `DATETIME_FORMAT` settings key, which will be `'iso-8601'` unless set. Setting to a format string indicates that `to_representation` return values should be coerced to string output. Format strings are described below. Setting this value to `None` indicates that Python `datetime` objects should be returned by `to_representation`. In this case the datetime encoding will be determined by the renderer.
* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATETIME_INPUT_FORMATS` setting will be used, which defaults to `['iso-8601']`. * `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATETIME_INPUT_FORMATS` setting will be used, which defaults to `['iso-8601']`.
* `default_timezone` - A `tzinfo` subclass (`zoneinfo` or `pytz`) representing the timezone. If not specified and the `USE_TZ` setting is enabled, this defaults to the [current timezone][django-current-timezone]. If `USE_TZ` is disabled, then datetime objects will be naive.
#### `DateTimeField` format strings. #### `DateTimeField` format strings.
Format strings may either be [Python strftime formats][strftime] which explicitly specify the format, or the special string `'iso-8601'`, which indicates that [ISO 8601][iso8601] style datetimes should be used. (eg `'2013-01-29T12:34:56.000000Z'`) Format strings may either be [Python strftime formats][strftime] which explicitly specify the format, or the special string `'iso-8601'`, which indicates that [ISO 8601][iso8601] style datetimes should be used. (eg `'2013-01-29T12:34:56.000000Z'`)
When a value of `None` is used for the format `datetime` objects will be returned by `to_representation` and the final output representation will determined by the renderer class. When a value of `None` is used for the format `datetime` objects will be returned by `to_representation` and the final output representation will be determined by the renderer class.
#### `auto_now` and `auto_now_add` model fields. #### `auto_now` and `auto_now_add` model fields.
@ -348,7 +367,7 @@ Corresponds to `django.db.models.fields.TimeField`
* `format` - A string representing the output format. If not specified, this defaults to the same value as the `TIME_FORMAT` settings key, which will be `'iso-8601'` unless set. Setting to a format string indicates that `to_representation` return values should be coerced to string output. Format strings are described below. Setting this value to `None` indicates that Python `time` objects should be returned by `to_representation`. In this case the time encoding will be determined by the renderer. * `format` - A string representing the output format. If not specified, this defaults to the same value as the `TIME_FORMAT` settings key, which will be `'iso-8601'` unless set. Setting to a format string indicates that `to_representation` return values should be coerced to string output. Format strings are described below. Setting this value to `None` indicates that Python `time` objects should be returned by `to_representation`. In this case the time encoding will be determined by the renderer.
* `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `TIME_INPUT_FORMATS` setting will be used, which defaults to `['iso-8601']`. * `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `TIME_INPUT_FORMATS` setting will be used, which defaults to `['iso-8601']`.
#### `TimeField` format strings #### `TimeField` format strings
Format strings may either be [Python strftime formats][strftime] which explicitly specify the format, or the special string `'iso-8601'`, which indicates that [ISO 8601][iso8601] style times should be used. (eg `'12:34:56.000000'`) Format strings may either be [Python strftime formats][strftime] which explicitly specify the format, or the special string `'iso-8601'`, which indicates that [ISO 8601][iso8601] style times should be used. (eg `'12:34:56.000000'`)
@ -360,7 +379,10 @@ Corresponds to `django.db.models.fields.DurationField`
The `validated_data` for these fields will contain a `datetime.timedelta` instance. The `validated_data` for these fields will contain a `datetime.timedelta` instance.
The representation is a string following this format `'[DD] [HH:[MM:]]ss[.uuuuuu]'`. The representation is a string following this format `'[DD] [HH:[MM:]]ss[.uuuuuu]'`.
**Signature:** `DurationField()` **Signature:** `DurationField(max_value=None, min_value=None)`
* `max_value` Validate that the duration provided is no greater than this value.
* `min_value` Validate that the duration provided is no less than this value.
--- ---
@ -374,10 +396,10 @@ Used by `ModelSerializer` to automatically generate fields if the corresponding
**Signature:** `ChoiceField(choices)` **Signature:** `ChoiceField(choices)`
- `choices` - A list of valid values, or a list of `(key, display_name)` tuples. * `choices` - A list of valid values, or a list of `(key, display_name)` tuples.
- `allow_blank` - If set to `True` then the empty string should be considered a valid value. If set to `False` then the empty string is considered invalid and will raise a validation error. Defaults to `False`. * `allow_blank` - If set to `True` then the empty string should be considered a valid value. If set to `False` then the empty string is considered invalid and will raise a validation error. Defaults to `False`.
- `html_cutoff` - If set this will be the maximum number of choices that will be displayed by a HTML select drop down. Can be used to ensure that automatically generated ChoiceFields with very large possible selections do not prevent a template from rendering. Defaults to `None`. * `html_cutoff` - If set this will be the maximum number of choices that will be displayed by a HTML select drop down. Can be used to ensure that automatically generated ChoiceFields with very large possible selections do not prevent a template from rendering. Defaults to `None`.
- `html_cutoff_text` - If set this will display a textual indicator if the maximum number of items have been cutoff in an HTML select drop down. Defaults to `"More than {count} items…"` * `html_cutoff_text` - If set this will display a textual indicator if the maximum number of items have been cutoff in an HTML select drop down. Defaults to `"More than {count} items…"`
Both the `allow_blank` and `allow_null` are valid options on `ChoiceField`, although it is highly recommended that you only use one and not both. `allow_blank` should be preferred for textual choices, and `allow_null` should be preferred for numeric or other non-textual choices. Both the `allow_blank` and `allow_null` are valid options on `ChoiceField`, although it is highly recommended that you only use one and not both. `allow_blank` should be preferred for textual choices, and `allow_null` should be preferred for numeric or other non-textual choices.
@ -387,10 +409,10 @@ A field that can accept a set of zero, one or many values, chosen from a limited
**Signature:** `MultipleChoiceField(choices)` **Signature:** `MultipleChoiceField(choices)`
- `choices` - A list of valid values, or a list of `(key, display_name)` tuples. * `choices` - A list of valid values, or a list of `(key, display_name)` tuples.
- `allow_blank` - If set to `True` then the empty string should be considered a valid value. If set to `False` then the empty string is considered invalid and will raise a validation error. Defaults to `False`. * `allow_blank` - If set to `True` then the empty string should be considered a valid value. If set to `False` then the empty string is considered invalid and will raise a validation error. Defaults to `False`.
- `html_cutoff` - If set this will be the maximum number of choices that will be displayed by a HTML select drop down. Can be used to ensure that automatically generated ChoiceFields with very large possible selections do not prevent a template from rendering. Defaults to `None`. * `html_cutoff` - If set this will be the maximum number of choices that will be displayed by a HTML select drop down. Can be used to ensure that automatically generated ChoiceFields with very large possible selections do not prevent a template from rendering. Defaults to `None`.
- `html_cutoff_text` - If set this will display a textual indicator if the maximum number of items have been cutoff in an HTML select drop down. Defaults to `"More than {count} items…"` * `html_cutoff_text` - If set this will display a textual indicator if the maximum number of items have been cutoff in an HTML select drop down. Defaults to `"More than {count} items…"`
As with `ChoiceField`, both the `allow_blank` and `allow_null` options are valid, although it is highly recommended that you only use one and not both. `allow_blank` should be preferred for textual choices, and `allow_null` should be preferred for numeric or other non-textual choices. As with `ChoiceField`, both the `allow_blank` and `allow_null` options are valid, although it is highly recommended that you only use one and not both. `allow_blank` should be preferred for textual choices, and `allow_null` should be preferred for numeric or other non-textual choices.
@ -411,9 +433,9 @@ Corresponds to `django.forms.fields.FileField`.
**Signature:** `FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)` **Signature:** `FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)`
- `max_length` - Designates the maximum length for the file name. * `max_length` - Designates the maximum length for the file name.
- `allow_empty_file` - Designates if empty files are allowed. * `allow_empty_file` - Designates if empty files are allowed.
- `use_url` - If set to `True` then URL string values will be used for the output representation. If set to `False` then filename string values will be used for the output representation. Defaults to the value of the `UPLOADED_FILES_USE_URL` settings key, which is `True` unless set otherwise. * `use_url` - If set to `True` then URL string values will be used for the output representation. If set to `False` then filename string values will be used for the output representation. Defaults to the value of the `UPLOADED_FILES_USE_URL` settings key, which is `True` unless set otherwise.
## ImageField ## ImageField
@ -423,9 +445,9 @@ Corresponds to `django.forms.fields.ImageField`.
**Signature:** `ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)` **Signature:** `ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)`
- `max_length` - Designates the maximum length for the file name. * `max_length` - Designates the maximum length for the file name.
- `allow_empty_file` - Designates if empty files are allowed. * `allow_empty_file` - Designates if empty files are allowed.
- `use_url` - If set to `True` then URL string values will be used for the output representation. If set to `False` then filename string values will be used for the output representation. Defaults to the value of the `UPLOADED_FILES_USE_URL` settings key, which is `True` unless set otherwise. * `use_url` - If set to `True` then URL string values will be used for the output representation. If set to `False` then filename string values will be used for the output representation. Defaults to the value of the `UPLOADED_FILES_USE_URL` settings key, which is `True` unless set otherwise.
Requires either the `Pillow` package or `PIL` package. The `Pillow` package is recommended, as `PIL` is no longer actively maintained. Requires either the `Pillow` package or `PIL` package. The `Pillow` package is recommended, as `PIL` is no longer actively maintained.
@ -437,11 +459,12 @@ Requires either the `Pillow` package or `PIL` package. The `Pillow` package is
A field class that validates a list of objects. A field class that validates a list of objects.
**Signature**: `ListField(child=<A_FIELD_INSTANCE>, min_length=None, max_length=None)` **Signature**: `ListField(child=<A_FIELD_INSTANCE>, allow_empty=True, min_length=None, max_length=None)`
- `child` - A field instance that should be used for validating the objects in the list. If this argument is not provided then objects in the list will not be validated. * `child` - A field instance that should be used for validating the objects in the list. If this argument is not provided then objects in the list will not be validated.
- `min_length` - Validates that the list contains no fewer than this number of elements. * `allow_empty` - Designates if empty lists are allowed.
- `max_length` - Validates that the list contains no more than this number of elements. * `min_length` - Validates that the list contains no fewer than this number of elements.
* `max_length` - Validates that the list contains no more than this number of elements.
For example, to validate a list of integers you might use something like the following: For example, to validate a list of integers you might use something like the following:
@ -460,9 +483,10 @@ We can now reuse our custom `StringListField` class throughout our application,
A field class that validates a dictionary of objects. The keys in `DictField` are always assumed to be string values. A field class that validates a dictionary of objects. The keys in `DictField` are always assumed to be string values.
**Signature**: `DictField(child=<A_FIELD_INSTANCE>)` **Signature**: `DictField(child=<A_FIELD_INSTANCE>, allow_empty=True)`
- `child` - A field instance that should be used for validating the values in the dictionary. If this argument is not provided then values in the mapping will not be validated. * `child` - A field instance that should be used for validating the values in the dictionary. If this argument is not provided then values in the mapping will not be validated.
* `allow_empty` - Designates if empty dictionaries are allowed.
For example, to create a field that validates a mapping of strings to strings, you would write something like this: For example, to create a field that validates a mapping of strings to strings, you would write something like this:
@ -477,9 +501,10 @@ You can also use the declarative style, as with `ListField`. For example:
A preconfigured `DictField` that is compatible with Django's postgres `HStoreField`. A preconfigured `DictField` that is compatible with Django's postgres `HStoreField`.
**Signature**: `HStoreField(child=<A_FIELD_INSTANCE>)` **Signature**: `HStoreField(child=<A_FIELD_INSTANCE>, allow_empty=True)`
- `child` - A field instance that is used for validating the values in the dictionary. The default child field accepts both empty strings and null values. * `child` - A field instance that is used for validating the values in the dictionary. The default child field accepts both empty strings and null values.
* `allow_empty` - Designates if empty dictionaries are allowed.
Note that the child field **must** be an instance of `CharField`, as the hstore extension stores values as strings. Note that the child field **must** be an instance of `CharField`, as the hstore extension stores values as strings.
@ -487,9 +512,10 @@ Note that the child field **must** be an instance of `CharField`, as the hstore
A field class that validates that the incoming data structure consists of valid JSON primitives. In its alternate binary mode, it will represent and validate JSON-encoded binary strings. A field class that validates that the incoming data structure consists of valid JSON primitives. In its alternate binary mode, it will represent and validate JSON-encoded binary strings.
**Signature**: `JSONField(binary)` **Signature**: `JSONField(binary, encoder)`
- `binary` - If set to `True` then the field will output and validate a JSON encoded string, rather than a primitive data structure. Defaults to `False`. * `binary` - If set to `True` then the field will output and validate a JSON encoded string, rather than a primitive data structure. Defaults to `False`.
* `encoder` - Use this JSON encoder to serialize input object. Defaults to `None`.
--- ---
@ -508,7 +534,7 @@ For example, if `has_expired` was a property on the `Account` model, then the fo
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Account model = Account
fields = ('id', 'account_name', 'has_expired') fields = ['id', 'account_name', 'has_expired']
## HiddenField ## HiddenField
@ -524,6 +550,12 @@ The `HiddenField` class is usually only needed if you have some validation that
For further examples on `HiddenField` see the [validators](validators.md) documentation. For further examples on `HiddenField` see the [validators](validators.md) documentation.
---
**Note:** `HiddenField()` does not appear in `partial=True` serializer (when making `PATCH` request).
---
## ModelField ## ModelField
A generic field that can be tied to any arbitrary model field. The `ModelField` class delegates the task of serialization/deserialization to its associated model field. This field can be used to create serializer fields for custom model fields, without having to create a new custom serializer field. A generic field that can be tied to any arbitrary model field. The `ModelField` class delegates the task of serialization/deserialization to its associated model field. This field can be used to create serializer fields for custom model fields, without having to create a new custom serializer field.
@ -540,7 +572,7 @@ This is a read-only field. It gets its value by calling a method on the serializ
**Signature**: `SerializerMethodField(method_name=None)` **Signature**: `SerializerMethodField(method_name=None)`
- `method_name` - The name of the method on the serializer to be called. If not included this defaults to `get_<field_name>`. * `method_name` - The name of the method on the serializer to be called. If not included this defaults to `get_<field_name>`.
The serializer method referred to by the `method_name` argument should accept a single argument (in addition to `self`), which is the object being serialized. It should return whatever you want to be included in the serialized representation of the object. For example: The serializer method referred to by the `method_name` argument should accept a single argument (in addition to `self`), which is the object being serialized. It should return whatever you want to be included in the serialized representation of the object. For example:
@ -553,6 +585,7 @@ The serializer method referred to by the `method_name` argument should accept a
class Meta: class Meta:
model = User model = User
fields = '__all__'
def get_days_since_joined(self, obj): def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days return (now() - obj.date_joined).days
@ -565,9 +598,7 @@ If you want to create a custom field, you'll need to subclass `Field` and then o
The `.to_representation()` method is called to convert the initial datatype into a primitive, serializable datatype. The `.to_representation()` method is called to convert the initial datatype into a primitive, serializable datatype.
The `to_internal_value()` method is called to restore a primitive datatype into its internal python representation. This method should raise a `serializers.ValidationError` if the data is invalid. The `.to_internal_value()` method is called to restore a primitive datatype into its internal python representation. This method should raise a `serializers.ValidationError` if the data is invalid.
Note that the `WritableField` class that was present in version 2.x no longer exists. You should subclass `Field` and override `to_internal_value()` if the field supports data input.
## Examples ## Examples
@ -575,7 +606,7 @@ Note that the `WritableField` class that was present in version 2.x no longer ex
Let's look at an example of serializing a class that represents an RGB color value: Let's look at an example of serializing a class that represents an RGB color value:
class Color(object): class Color:
""" """
A color represented in the RGB colorspace. A color represented in the RGB colorspace.
""" """
@ -588,8 +619,8 @@ Let's look at an example of serializing a class that represents an RGB color val
""" """
Color objects are serialized into 'rgb(#, #, #)' notation. Color objects are serialized into 'rgb(#, #, #)' notation.
""" """
def to_representation(self, obj): def to_representation(self, value):
return "rgb(%d, %d, %d)" % (obj.red, obj.green, obj.blue) return "rgb(%d, %d, %d)" % (value.red, value.green, value.blue)
def to_internal_value(self, data): def to_internal_value(self, data):
data = data.strip('rgb(').rstrip(')') data = data.strip('rgb(').rstrip(')')
@ -601,16 +632,16 @@ By default field values are treated as mapping to an attribute on the object. I
As an example, let's create a field that can be used to represent the class name of the object being serialized: As an example, let's create a field that can be used to represent the class name of the object being serialized:
class ClassNameField(serializers.Field): class ClassNameField(serializers.Field):
def get_attribute(self, obj): def get_attribute(self, instance):
# We pass the object instance onto `to_representation`, # We pass the object instance onto `to_representation`,
# not just the field attribute. # not just the field attribute.
return obj return instance
def to_representation(self, obj): def to_representation(self, value):
""" """
Serialize the object's class name. Serialize the value's class name.
""" """
return obj.__class__.__name__ return value.__class__.__name__
### Raising validation errors ### Raising validation errors
@ -618,7 +649,7 @@ Our `ColorField` class above currently does not perform any data validation.
To indicate invalid data, we should raise a `serializers.ValidationError`, like so: To indicate invalid data, we should raise a `serializers.ValidationError`, like so:
def to_internal_value(self, data): def to_internal_value(self, data):
if not isinstance(data, six.text_type): if not isinstance(data, str):
msg = 'Incorrect type. Expected a string, but got %s' msg = 'Incorrect type. Expected a string, but got %s'
raise ValidationError(msg % type(data).__name__) raise ValidationError(msg % type(data).__name__)
@ -642,7 +673,7 @@ The `.fail()` method is a shortcut for raising `ValidationError` that takes a me
} }
def to_internal_value(self, data): def to_internal_value(self, data):
if not isinstance(data, six.text_type): if not isinstance(data, str):
self.fail('incorrect_type', input_type=type(data).__name__) self.fail('incorrect_type', input_type=type(data).__name__)
if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data): if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
@ -672,10 +703,10 @@ the coordinate pair:
class CoordinateField(serializers.Field): class CoordinateField(serializers.Field):
def to_representation(self, obj): def to_representation(self, value):
ret = { ret = {
"x": obj.x_coordinate, "x": value.x_coordinate,
"y": obj.y_coordinate "y": value.y_coordinate
} }
return ret return ret
@ -695,7 +726,7 @@ the coordinate pair:
fields = ['label', 'coordinates'] fields = ['label', 'coordinates']
Note that this example doesn't handle validation. Partly for that reason, in a Note that this example doesn't handle validation. Partly for that reason, in a
real project, the coordinate nesting might be better handled with a nested serialiser real project, the coordinate nesting might be better handled with a nested serializer
using `source='*'`, with two `IntegerField` instances, each with their own `source` using `source='*'`, with two `IntegerField` instances, each with their own `source`
pointing to the relevant field. pointing to the relevant field.
@ -707,7 +738,7 @@ to the desired output.
>>> instance = DataPoint(label='Example', x_coordinate=1, y_coordinate=2) >>> instance = DataPoint(label='Example', x_coordinate=1, y_coordinate=2)
>>> out_serializer = DataPointSerializer(instance) >>> out_serializer = DataPointSerializer(instance)
>>> out_serializer.data >>> out_serializer.data
ReturnDict([('label', 'testing'), ('coordinates', {'x': 1, 'y': 2})]) ReturnDict([('label', 'Example'), ('coordinates', {'x': 1, 'y': 2})])
* Unless our field is to be read-only, `to_internal_value` must map back to a dict * Unless our field is to be read-only, `to_internal_value` must map back to a dict
suitable for updating our target object. With `source='*'`, the return from suitable for updating our target object. With `source='*'`, the return from
@ -728,7 +759,7 @@ suitable for updating our target object. With `source='*'`, the return from
('y_coordinate', 4), ('y_coordinate', 4),
('x_coordinate', 3)]) ('x_coordinate', 3)])
For completeness lets do the same thing again but with the nested serialiser For completeness lets do the same thing again but with the nested serializer
approach suggested above: approach suggested above:
class NestedCoordinateSerializer(serializers.Serializer): class NestedCoordinateSerializer(serializers.Serializer):
@ -747,17 +778,17 @@ Here the mapping between the target and source attribute pairs (`x` and
`x_coordinate`, `y` and `y_coordinate`) is handled in the `IntegerField` `x_coordinate`, `y` and `y_coordinate`) is handled in the `IntegerField`
declarations. It's our `NestedCoordinateSerializer` that takes `source='*'`. declarations. It's our `NestedCoordinateSerializer` that takes `source='*'`.
Our new `DataPointSerializer` exhibits the same behaviour as the custom field Our new `DataPointSerializer` exhibits the same behavior as the custom field
approach. approach.
Serialising: Serializing:
>>> out_serializer = DataPointSerializer(instance) >>> out_serializer = DataPointSerializer(instance)
>>> out_serializer.data >>> out_serializer.data
ReturnDict([('label', 'testing'), ReturnDict([('label', 'testing'),
('coordinates', OrderedDict([('x', 1), ('y', 2)]))]) ('coordinates', OrderedDict([('x', 1), ('y', 2)]))])
Deserialising: Deserializing:
>>> in_serializer = DataPointSerializer(data=data) >>> in_serializer = DataPointSerializer(data=data)
>>> in_serializer.is_valid() >>> in_serializer.is_valid()
@ -784,8 +815,8 @@ But we also get the built-in validation for free:
{'x': ['A valid integer is required.'], {'x': ['A valid integer is required.'],
'y': ['A valid integer is required.']})]) 'y': ['A valid integer is required.']})])
For this reason, the nested serialiser approach would be the first to try. You For this reason, the nested serializer approach would be the first to try. You
would use the custom field approach when the nested serialiser becomes infeasible would use the custom field approach when the nested serializer becomes infeasible
or overly complex. or overly complex.
@ -807,7 +838,7 @@ the [djangorestframework-recursive][djangorestframework-recursive] package provi
## django-rest-framework-gis ## django-rest-framework-gis
The [django-rest-framework-gis][django-rest-framework-gis] package provides geographic addons for django rest framework like a `GeometryField` field and a GeoJSON serializer. The [django-rest-framework-gis][django-rest-framework-gis] package provides geographic addons for django rest framework like a `GeometryField` field and a GeoJSON serializer.
## django-rest-framework-hstore ## django-rest-framework-hstore
@ -825,3 +856,5 @@ The [django-rest-framework-hstore][django-rest-framework-hstore] package provide
[django-rest-framework-hstore]: https://github.com/djangonauts/django-rest-framework-hstore [django-rest-framework-hstore]: https://github.com/djangonauts/django-rest-framework-hstore
[django-hstore]: https://github.com/djangonauts/django-hstore [django-hstore]: https://github.com/djangonauts/django-hstore
[python-decimal-rounding-modes]: https://docs.python.org/3/library/decimal.html#rounding-modes [python-decimal-rounding-modes]: https://docs.python.org/3/library/decimal.html#rounding-modes
[django-current-timezone]: https://docs.djangoproject.com/en/stable/topics/i18n/timezones/#default-time-zone-and-current-time-zone
[django-docs-select-related]: https://docs.djangoproject.com/en/stable/ref/models/querysets/#django.db.models.query.QuerySet.select_related

View File

@ -1,4 +1,7 @@
source: filters.py ---
source:
- filters.py
---
# Filtering # Filtering
@ -42,7 +45,7 @@ Another style of filtering might involve restricting the queryset based on some
For example if your URL config contained an entry like this: For example if your URL config contained an entry like this:
url('^purchases/(?P<username>.+)/$', PurchaseList.as_view()), re_path('^purchases/(?P<username>.+)/$', PurchaseList.as_view()),
You could then write a view that returned a purchase queryset filtered by the username portion of the URL: You could then write a view that returned a purchase queryset filtered by the username portion of the URL:
@ -72,7 +75,7 @@ We can override `.get_queryset()` to deal with URLs such as `http://example.com/
by filtering against a `username` query parameter in the URL. by filtering against a `username` query parameter in the URL.
""" """
queryset = Purchase.objects.all() queryset = Purchase.objects.all()
username = self.request.query_params.get('username', None) username = self.request.query_params.get('username')
if username is not None: if username is not None:
queryset = queryset.filter(purchaser__username=username) queryset = queryset.filter(purchaser__username=username)
return queryset return queryset
@ -92,7 +95,7 @@ Generic filters can also present themselves as HTML controls in the browsable AP
The default filter backends may be set globally, using the `DEFAULT_FILTER_BACKENDS` setting. For example. The default filter backends may be set globally, using the `DEFAULT_FILTER_BACKENDS` setting. For example.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
} }
You can also set the filter backends on a per-view, or per-viewset basis, You can also set the filter backends on a per-view, or per-viewset basis,
@ -106,7 +109,7 @@ using the `GenericAPIView` class-based views.
class UserListView(generics.ListAPIView): class UserListView(generics.ListAPIView):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,) filter_backends = [django_filters.rest_framework.DjangoFilterBackend]
## Filtering and object lookups ## Filtering and object lookups
@ -127,7 +130,7 @@ Note that you can use both an overridden `.get_queryset()` and generic filtering
""" """
model = Product model = Product
serializer_class = ProductSerializer serializer_class = ProductSerializer
filter_class = ProductFilter filterset_class = ProductFilter
def get_queryset(self): def get_queryset(self):
user = self.request.user user = self.request.user
@ -139,17 +142,25 @@ Note that you can use both an overridden `.get_queryset()` and generic filtering
## DjangoFilterBackend ## DjangoFilterBackend
The `django-filter` library includes a `DjangoFilterBackend` class which The [`django-filter`][django-filter-docs] library includes a `DjangoFilterBackend` class which
supports highly customizable field filtering for REST framework. supports highly customizable field filtering for REST framework.
To use `DjangoFilterBackend`, first install `django-filter`. Then add `django_filters` to Django's `INSTALLED_APPS` To use `DjangoFilterBackend`, first install `django-filter`.
pip install django-filter pip install django-filter
Then add `'django_filters'` to Django's `INSTALLED_APPS`:
INSTALLED_APPS = [
...
'django_filters',
...
]
You should now either add the filter backend to your settings: You should now either add the filter backend to your settings:
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
} }
Or add the filter backend to an individual View or ViewSet. Or add the filter backend to an individual View or ViewSet.
@ -158,15 +169,15 @@ Or add the filter backend to an individual View or ViewSet.
class UserListView(generics.ListAPIView): class UserListView(generics.ListAPIView):
... ...
filter_backends = (DjangoFilterBackend,) filter_backends = [DjangoFilterBackend]
If all you need is simple equality-based filtering, you can set a `filter_fields` attribute on the view, or viewset, listing the set of fields you wish to filter against. If all you need is simple equality-based filtering, you can set a `filterset_fields` attribute on the view, or viewset, listing the set of fields you wish to filter against.
class ProductList(generics.ListAPIView): class ProductList(generics.ListAPIView):
queryset = Product.objects.all() queryset = Product.objects.all()
serializer_class = ProductSerializer serializer_class = ProductSerializer
filter_backends = (DjangoFilterBackend,) filter_backends = [DjangoFilterBackend]
filter_fields = ('category', 'in_stock') filterset_fields = ['category', 'in_stock']
This will automatically create a `FilterSet` class for the given fields, and will allow you to make requests such as: This will automatically create a `FilterSet` class for the given fields, and will allow you to make requests such as:
@ -187,11 +198,13 @@ When in use, the browsable API will include a `SearchFilter` control:
The `SearchFilter` class will only be applied if the view has a `search_fields` attribute set. The `search_fields` attribute should be a list of names of text type fields on the model, such as `CharField` or `TextField`. The `SearchFilter` class will only be applied if the view has a `search_fields` attribute set. The `search_fields` attribute should be a list of names of text type fields on the model, such as `CharField` or `TextField`.
from rest_framework import filters
class UserListView(generics.ListAPIView): class UserListView(generics.ListAPIView):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
filter_backends = (filters.SearchFilter,) filter_backends = [filters.SearchFilter]
search_fields = ('username', 'email') search_fields = ['username', 'email']
This will allow the client to filter the items in the list by making queries such as: This will allow the client to filter the items in the list by making queries such as:
@ -199,22 +212,40 @@ This will allow the client to filter the items in the list by making queries suc
You can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API double-underscore notation: You can also perform a related lookup on a ForeignKey or ManyToManyField with the lookup API double-underscore notation:
search_fields = ('username', 'email', 'profile__profession') search_fields = ['username', 'email', 'profile__profession']
By default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched. For [JSONField][JSONField] and [HStoreField][HStoreField] fields you can filter based on nested values within the data structure using the same double-underscore notation:
The search behavior may be restricted by prepending various characters to the `search_fields`. search_fields = ['data__breed', 'data__owner__other_pets__0__name']
* '^' Starts-with search. By default, searches will use case-insensitive partial matches. The search parameter may contain multiple search terms, which should be whitespace and/or comma separated. If multiple search terms are used then objects will be returned in the list only if all the provided terms are matched. Searches may contain _quoted phrases_ with spaces, each phrase is considered as a single search term.
* '=' Exact matches.
* '@' Full-text search. (Currently only supported Django's MySQL backend.)
* '$' Regex search. The search behavior may be specified by prefixing field names in `search_fields` with one of the following characters (which is equivalent to adding `__<lookup>` to the field):
| Prefix | Lookup | |
| ------ | --------------| ------------------ |
| `^` | `istartswith` | Starts-with search.|
| `=` | `iexact` | Exact matches. |
| `$` | `iregex` | Regex search. |
| `@` | `search` | Full-text search (Currently only supported Django's [PostgreSQL backend][postgres-search]). |
| None | `icontains` | Contains search (Default). |
For example: For example:
search_fields = ('=username', '=email') search_fields = ['=username', '=email']
By default, the search parameter is named `'search`', but this may be overridden with the `SEARCH_PARAM` setting. By default, the search parameter is named `'search'`, but this may be overridden with the `SEARCH_PARAM` setting.
To dynamically change search fields based on request content, it's possible to subclass the `SearchFilter` and override the `get_search_fields()` function. For example, the following subclass will only search on `title` if the query parameter `title_only` is in the request:
from rest_framework import filters
class CustomSearchFilter(filters.SearchFilter):
def get_search_fields(self, view, request):
if request.query_params.get('title_only'):
return ['title']
return super().get_search_fields(view, request)
For more details, see the [Django documentation][search-django-admin]. For more details, see the [Django documentation][search-django-admin].
@ -226,7 +257,7 @@ The `OrderingFilter` class supports simple query parameter controlled ordering o
![Ordering Filter](../img/ordering-filter.png) ![Ordering Filter](../img/ordering-filter.png)
By default, the query parameter is named `'ordering'`, but this may by overridden with the `ORDERING_PARAM` setting. By default, the query parameter is named `'ordering'`, but this may be overridden with the `ORDERING_PARAM` setting.
For example, to order users by username: For example, to order users by username:
@ -242,13 +273,13 @@ Multiple orderings may also be specified:
### Specifying which fields may be ordered against ### Specifying which fields may be ordered against
It's recommended that you explicitly specify which fields the API should allowing in the ordering filter. You can do this by setting an `ordering_fields` attribute on the view, like so: It's recommended that you explicitly specify which fields the API should allow in the ordering filter. You can do this by setting an `ordering_fields` attribute on the view, like so:
class UserListView(generics.ListAPIView): class UserListView(generics.ListAPIView):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,) filter_backends = [filters.OrderingFilter]
ordering_fields = ('username', 'email') ordering_fields = ['username', 'email']
This helps prevent unexpected data leakage, such as allowing users to order against a password hash field or other sensitive data. This helps prevent unexpected data leakage, such as allowing users to order against a password hash field or other sensitive data.
@ -259,7 +290,7 @@ If you are confident that the queryset being used by the view doesn't contain an
class BookingsListView(generics.ListAPIView): class BookingsListView(generics.ListAPIView):
queryset = Booking.objects.all() queryset = Booking.objects.all()
serializer_class = BookingSerializer serializer_class = BookingSerializer
filter_backends = (filters.OrderingFilter,) filter_backends = [filters.OrderingFilter]
ordering_fields = '__all__' ordering_fields = '__all__'
### Specifying a default ordering ### Specifying a default ordering
@ -271,55 +302,14 @@ Typically you'd instead control this by setting `order_by` on the initial querys
class UserListView(generics.ListAPIView): class UserListView(generics.ListAPIView):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
filter_backends = (filters.OrderingFilter,) filter_backends = [filters.OrderingFilter]
ordering_fields = ('username', 'email') ordering_fields = ['username', 'email']
ordering = ('username',) ordering = ['username']
The `ordering` attribute may be either a string or a list/tuple of strings. The `ordering` attribute may be either a string or a list/tuple of strings.
--- ---
## DjangoObjectPermissionsFilter
The `DjangoObjectPermissionsFilter` is intended to be used together with the [`django-guardian`][guardian] package, with custom `'view'` permissions added. The filter will ensure that querysets only returns objects for which the user has the appropriate view permission.
If you're using `DjangoObjectPermissionsFilter`, you'll probably also want to add an appropriate object permissions class, to ensure that users can only operate on instances if they have the appropriate object permissions. The easiest way to do this is to subclass `DjangoObjectPermissions` and add `'view'` permissions to the `perms_map` attribute.
A complete example using both `DjangoObjectPermissionsFilter` and `DjangoObjectPermissions` might look something like this.
**permissions.py**:
class CustomObjectPermissions(permissions.DjangoObjectPermissions):
"""
Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
"""
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
'HEAD': ['%(app_label)s.view_%(model_name)s'],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
**views.py**:
class EventViewSet(viewsets.ModelViewSet):
"""
Viewset that only lists events if user has 'view' permissions, and only
allows operations on individual events if user has appropriate 'view', 'add',
'change' or 'delete' permissions.
"""
queryset = Event.objects.all()
serializer_class = EventSerializer
filter_backends = (filters.DjangoObjectPermissionsFilter,)
permission_classes = (myapp.permissions.CustomObjectPermissions,)
For more information on adding `'view'` permissions for models, see the [relevant section][view-permissions] of the `django-guardian` documentation, and [this blogpost][view-permissions-blogpost].
---
# Custom generic filtering # Custom generic filtering
You can also provide your own generic filtering backend, or write an installable app for other developers to use. You can also provide your own generic filtering backend, or write an installable app for other developers to use.
@ -349,15 +339,6 @@ Generic filters may also present an interface in the browsable API. To do so you
The method should return a rendered HTML string. The method should return a rendered HTML string.
## Pagination & schemas
You can also make the filter controls available to the schema autogeneration
that REST framework provides, by implementing a `get_schema_fields()` method. This method should have the following signature:
`get_schema_fields(self, view)`
The method should return a list of `coreapi.Field` instances.
# Third party packages # Third party packages
The following third party packages provide additional filter implementations. The following third party packages provide additional filter implementations.
@ -381,11 +362,11 @@ The [djangorestframework-word-filter][django-rest-framework-word-search-filter]
[cite]: https://docs.djangoproject.com/en/stable/topics/db/queries/#retrieving-specific-objects-with-filters [cite]: https://docs.djangoproject.com/en/stable/topics/db/queries/#retrieving-specific-objects-with-filters
[django-filter-docs]: https://django-filter.readthedocs.io/en/latest/index.html [django-filter-docs]: https://django-filter.readthedocs.io/en/latest/index.html
[django-filter-drf-docs]: https://django-filter.readthedocs.io/en/latest/guide/rest_framework.html [django-filter-drf-docs]: https://django-filter.readthedocs.io/en/latest/guide/rest_framework.html
[guardian]: https://django-guardian.readthedocs.io/
[view-permissions]: https://django-guardian.readthedocs.io/en/latest/userguide/assign.html
[view-permissions-blogpost]: https://blog.nyaruka.com/adding-a-view-permission-to-django-models
[search-django-admin]: https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields [search-django-admin]: https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields
[django-rest-framework-filters]: https://github.com/philipn/django-rest-framework-filters [django-rest-framework-filters]: https://github.com/philipn/django-rest-framework-filters
[django-rest-framework-word-search-filter]: https://github.com/trollknurr/django-rest-framework-word-search-filter [django-rest-framework-word-search-filter]: https://github.com/trollknurr/django-rest-framework-word-search-filter
[django-url-filter]: https://github.com/miki725/django-url-filter [django-url-filter]: https://github.com/miki725/django-url-filter
[drf-url-filter]: https://github.com/manjitkumar/drf-url-filters [drf-url-filter]: https://github.com/manjitkumar/drf-url-filters
[HStoreField]: https://docs.djangoproject.com/en/stable/ref/contrib/postgres/fields/#hstorefield
[JSONField]: https://docs.djangoproject.com/en/stable/ref/models/fields/#django.db.models.JSONField
[postgres-search]: https://docs.djangoproject.com/en/stable/ref/contrib/postgres/search/

View File

@ -1,4 +1,7 @@
source: urlpatterns.py ---
source:
- urlpatterns.py
---
# Format suffixes # Format suffixes
@ -20,8 +23,8 @@ Returns a URL pattern list which includes format suffix patterns appended to eac
Arguments: Arguments:
* **urlpatterns**: Required. A URL pattern list. * **urlpatterns**: Required. A URL pattern list.
* **suffix_required**: Optional. A boolean indicating if suffixes in the URLs should be optional or mandatory. Defaults to `False`, meaning that suffixes are optional by default. * **suffix_required**: Optional. A boolean indicating if suffixes in the URLs should be optional or mandatory. Defaults to `False`, meaning that suffixes are optional by default.
* **allowed**: Optional. A list or tuple of valid format suffixes. If not provided, a wildcard format suffix pattern will be used. * **allowed**: Optional. A list or tuple of valid format suffixes. If not provided, a wildcard format suffix pattern will be used.
Example: Example:
@ -29,16 +32,16 @@ Example:
from blog import views from blog import views
urlpatterns = [ urlpatterns = [
url(r'^/$', views.apt_root), path('', views.apt_root),
url(r'^comments/$', views.comment_list), path('comments/', views.comment_list),
url(r'^comments/(?P<pk>[0-9]+)/$', views.comment_detail) path('comments/<int:pk>/', views.comment_detail)
] ]
urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html']) urlpatterns = format_suffix_patterns(urlpatterns, allowed=['json', 'html'])
When using `format_suffix_patterns`, you must make sure to add the `'format'` keyword argument to the corresponding views. For example: When using `format_suffix_patterns`, you must make sure to add the `'format'` keyword argument to the corresponding views. For example:
@api_view(('GET', 'POST')) @api_view(['GET', 'POST'])
def comment_list(request, format=None): def comment_list(request, format=None):
# do stuff... # do stuff...
@ -59,7 +62,7 @@ Also note that `format_suffix_patterns` does not support descending into `includ
If using the `i18n_patterns` function provided by Django, as well as `format_suffix_patterns` you should make sure that the `i18n_patterns` function is applied as the final, or outermost function. For example: If using the `i18n_patterns` function provided by Django, as well as `format_suffix_patterns` you should make sure that the `i18n_patterns` function is applied as the final, or outermost function. For example:
url patterns = [ urlpatterns = [
] ]
@ -90,4 +93,4 @@ It is actually a misconception. For example, take the following quote from Roy
The quote does not mention Accept headers, but it does make it clear that format suffixes should be considered an acceptable pattern. The quote does not mention Accept headers, but it does make it clear that format suffixes should be considered an acceptable pattern.
[cite]: http://tech.groups.yahoo.com/group/rest-discuss/message/5857 [cite]: http://tech.groups.yahoo.com/group/rest-discuss/message/5857
[cite2]: http://tech.groups.yahoo.com/group/rest-discuss/message/14844 [cite2]: https://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/14844

View File

@ -1,5 +1,8 @@
source: mixins.py ---
generics.py source:
- mixins.py
- generics.py
---
# Generic views # Generic views
@ -25,14 +28,14 @@ Typically when using the generic views, you'll override the view, and set severa
class UserList(generics.ListCreateAPIView): class UserList(generics.ListCreateAPIView):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
permission_classes = (IsAdminUser,) permission_classes = [IsAdminUser]
For more complex cases you might also want to override various methods on the view class. For example. For more complex cases you might also want to override various methods on the view class. For example.
class UserList(generics.ListCreateAPIView): class UserList(generics.ListCreateAPIView):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
permission_classes = (IsAdminUser,) permission_classes = [IsAdminUser]
def list(self, request): def list(self, request):
# Note the use of `get_queryset()` instead of `self.queryset` # Note the use of `get_queryset()` instead of `self.queryset`
@ -42,7 +45,7 @@ For more complex cases you might also want to override various methods on the vi
For very simple cases you might want to pass through any class attributes using the `.as_view()` method. For example, your URLconf might include something like the following entry: For very simple cases you might want to pass through any class attributes using the `.as_view()` method. For example, your URLconf might include something like the following entry:
url(r'^/users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list') path('users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')
--- ---
@ -62,7 +65,7 @@ The following attributes control the basic view behavior.
* `queryset` - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the `get_queryset()` method. If you are overriding a view method, it is important that you call `get_queryset()` instead of accessing this property directly, as `queryset` will get evaluated once, and those results will be cached for all subsequent requests. * `queryset` - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the `get_queryset()` method. If you are overriding a view method, it is important that you call `get_queryset()` instead of accessing this property directly, as `queryset` will get evaluated once, and those results will be cached for all subsequent requests.
* `serializer_class` - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the `get_serializer_class()` method. * `serializer_class` - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the `get_serializer_class()` method.
* `lookup_field` - The model field that should be used to for performing object lookup of individual model instances. Defaults to `'pk'`. Note that when using hyperlinked APIs you'll need to ensure that *both* the API views *and* the serializer classes set the lookup fields if you need to use a custom value. * `lookup_field` - The model field that should be used for performing object lookup of individual model instances. Defaults to `'pk'`. Note that when using hyperlinked APIs you'll need to ensure that *both* the API views *and* the serializer classes set the lookup fields if you need to use a custom value.
* `lookup_url_kwarg` - The URL keyword argument that should be used for object lookup. The URL conf should include a keyword argument corresponding to this value. If unset this defaults to using the same value as `lookup_field`. * `lookup_url_kwarg` - The URL keyword argument that should be used for object lookup. The URL conf should include a keyword argument corresponding to this value. If unset this defaults to using the same value as `lookup_field`.
**Pagination**: **Pagination**:
@ -93,6 +96,12 @@ For example:
user = self.request.user user = self.request.user
return user.accounts.all() return user.accounts.all()
---
**Note:** If the `serializer_class` used in the generic view spans orm relations, leading to an n+1 problem, you could optimize your queryset in this method using `select_related` and `prefetch_related`. To get more information about n+1 problem and use cases of the mentioned methods refer to related section in [django documentation][django-docs-select-related].
---
#### `get_object(self)` #### `get_object(self)`
Returns an object instance that should be used for detail views. Defaults to using the `lookup_field` parameter to filter the base queryset. Returns an object instance that should be used for detail views. Defaults to using the `lookup_field` parameter to filter the base queryset.
@ -120,12 +129,12 @@ Given a queryset, filter it with whichever filter backends are in use, returning
For example: For example:
def filter_queryset(self, queryset): def filter_queryset(self, queryset):
filter_backends = (CategoryFilter,) filter_backends = [CategoryFilter]
if 'geo_route' in self.request.query_params: if 'geo_route' in self.request.query_params:
filter_backends = (GeoRouteFilter, CategoryFilter) filter_backends = [GeoRouteFilter, CategoryFilter]
elif 'geo_point' in self.request.query_params: elif 'geo_point' in self.request.query_params:
filter_backends = (GeoPointFilter, CategoryFilter) filter_backends = [GeoPointFilter, CategoryFilter]
for backend in list(filter_backends): for backend in list(filter_backends):
queryset = backend().filter_queryset(self.request, queryset, view=self) queryset = backend().filter_queryset(self.request, queryset, view=self)
@ -172,8 +181,6 @@ You can also use these hooks to provide additional validation, by raising a `Val
raise ValidationError('You have already signed up') raise ValidationError('You have already signed up')
serializer.save(user=self.request.user) serializer.save(user=self.request.user)
**Note**: These methods replace the old-style version 2.x `pre_save`, `post_save`, `pre_delete` and `post_delete` methods, which are no longer available.
**Other methods**: **Other methods**:
You won't typically need to override the following methods, although you might need to call into them if you're writing custom views using `GenericAPIView`. You won't typically need to override the following methods, although you might need to call into them if you're writing custom views using `GenericAPIView`.
@ -210,7 +217,7 @@ If the request data provided for creating the object was invalid, a `400 Bad Req
Provides a `.retrieve(request, *args, **kwargs)` method, that implements returning an existing model instance in a response. Provides a `.retrieve(request, *args, **kwargs)` method, that implements returning an existing model instance in a response.
If an object can be retrieved this returns a `200 OK` response, with a serialized representation of the object as the body of the response. Otherwise it will return a `404 Not Found`. If an object can be retrieved this returns a `200 OK` response, with a serialized representation of the object as the body of the response. Otherwise, it will return a `404 Not Found`.
## UpdateModelMixin ## UpdateModelMixin
@ -318,7 +325,7 @@ Often you'll want to use the existing generic views, but use some slightly custo
For example, if you need to lookup objects based on multiple fields in the URL conf, you could create a mixin class like the following: For example, if you need to lookup objects based on multiple fields in the URL conf, you could create a mixin class like the following:
class MultipleFieldLookupMixin(object): class MultipleFieldLookupMixin:
""" """
Apply this mixin to any view or viewset to get multiple field filtering Apply this mixin to any view or viewset to get multiple field filtering
based on a `lookup_fields` attribute, instead of the default single field filtering. based on a `lookup_fields` attribute, instead of the default single field filtering.
@ -328,7 +335,7 @@ For example, if you need to lookup objects based on multiple fields in the URL c
queryset = self.filter_queryset(queryset) # Apply any filter backends queryset = self.filter_queryset(queryset) # Apply any filter backends
filter = {} filter = {}
for field in self.lookup_fields: for field in self.lookup_fields:
if self.kwargs[field]: # Ignore empty fields. if self.kwargs.get(field): # Ignore empty fields.
filter[field] = self.kwargs[field] filter[field] = self.kwargs[field]
obj = get_object_or_404(queryset, **filter) # Lookup the object obj = get_object_or_404(queryset, **filter) # Lookup the object
self.check_object_permissions(self.request, obj) self.check_object_permissions(self.request, obj)
@ -339,7 +346,7 @@ You can then simply apply this mixin to a view or viewset anytime you need to ap
class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView): class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
lookup_fields = ('account', 'username') 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.
@ -375,10 +382,6 @@ If you need to generic PUT-as-create behavior you may want to include something
The following third party packages provide additional generic view implementations. The following third party packages provide additional generic view implementations.
## Django REST Framework bulk
The [django-rest-framework-bulk package][django-rest-framework-bulk] implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.
## Django Rest Multiple Models ## Django Rest Multiple Models
[Django Rest Multiple Models][django-rest-multiple-models] provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request. [Django Rest Multiple Models][django-rest-multiple-models] provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request.
@ -391,5 +394,5 @@ The [django-rest-framework-bulk package][django-rest-framework-bulk] implements
[RetrieveModelMixin]: #retrievemodelmixin [RetrieveModelMixin]: #retrievemodelmixin
[UpdateModelMixin]: #updatemodelmixin [UpdateModelMixin]: #updatemodelmixin
[DestroyModelMixin]: #destroymodelmixin [DestroyModelMixin]: #destroymodelmixin
[django-rest-framework-bulk]: https://github.com/miki725/django-rest-framework-bulk
[django-rest-multiple-models]: https://github.com/MattBroach/DjangoRestMultipleModels [django-rest-multiple-models]: https://github.com/MattBroach/DjangoRestMultipleModels
[django-docs-select-related]: https://docs.djangoproject.com/en/stable/ref/models/querysets/#django.db.models.query.QuerySet.select_related

View File

@ -1,4 +1,7 @@
source: metadata.py ---
source:
- metadata.py
---
# Metadata # Metadata
@ -68,7 +71,7 @@ If you have specific requirements for creating schema endpoints that are accesse
For example, the following additional route could be used on a viewset to provide a linkable schema endpoint. For example, the following additional route could be used on a viewset to provide a linkable schema endpoint.
@action(methods=['GET'], detail=False) @action(methods=['GET'], detail=False)
def schema(self, request): def api_schema(self, request):
meta = self.metadata_class() meta = self.metadata_class()
data = meta.determine_metadata(request, self) data = meta.determine_metadata(request, self)
return Response(data) return Response(data)
@ -117,5 +120,5 @@ If you wish to do so, it also provides an exporter that can export those schema
[cite]: https://tools.ietf.org/html/rfc7231#section-4.3.7 [cite]: https://tools.ietf.org/html/rfc7231#section-4.3.7
[no-options]: https://www.mnot.net/blog/2012/10/29/NO_OPTIONS [no-options]: https://www.mnot.net/blog/2012/10/29/NO_OPTIONS
[json-schema]: http://json-schema.org/ [json-schema]: https://json-schema.org/
[drf-schema-adapter]: https://github.com/drf-forms/drf-schema-adapter [drf-schema-adapter]: https://github.com/drf-forms/drf-schema-adapter

View File

@ -1,4 +1,7 @@
source: pagination.py ---
source:
- pagination.py
---
# Pagination # Pagination
@ -46,7 +49,7 @@ If you want to modify particular aspects of the pagination style, you'll want to
page_size_query_param = 'page_size' page_size_query_param = 'page_size'
max_page_size = 1000 max_page_size = 1000
You can then apply your new style to a view using the `.pagination_class` attribute: You can then apply your new style to a view using the `pagination_class` attribute:
class BillingRecordsView(generics.ListAPIView): class BillingRecordsView(generics.ListAPIView):
queryset = Billing.objects.all() queryset = Billing.objects.all()
@ -75,7 +78,7 @@ This pagination style accepts a single number page number in the request query p
HTTP 200 OK HTTP 200 OK
{ {
"count": 1023 "count": 1023,
"next": "https://api.example.org/accounts/?page=5", "next": "https://api.example.org/accounts/?page=5",
"previous": "https://api.example.org/accounts/?page=3", "previous": "https://api.example.org/accounts/?page=3",
"results": [ "results": [
@ -123,7 +126,7 @@ This pagination style mirrors the syntax used when looking up multiple database
HTTP 200 OK HTTP 200 OK
{ {
"count": 1023 "count": 1023,
"next": "https://api.example.org/accounts/?limit=100&offset=500", "next": "https://api.example.org/accounts/?limit=100&offset=500",
"previous": "https://api.example.org/accounts/?limit=100&offset=300", "previous": "https://api.example.org/accounts/?limit=100&offset=300",
"results": [ "results": [
@ -215,16 +218,16 @@ To set these attributes you should override the `CursorPagination` class, and th
# Custom pagination styles # Custom pagination styles
To create a custom pagination serializer class you should subclass `pagination.BasePagination` and override the `paginate_queryset(self, queryset, request, view=None)` and `get_paginated_response(self, data)` methods: To create a custom pagination serializer class, you should inherit the subclass `pagination.BasePagination`, override the `paginate_queryset(self, queryset, request, view=None)`, and `get_paginated_response(self, data)` methods:
* The `paginate_queryset` method is passed the initial queryset and should return an iterable object that contains only the data in the requested page. * The `paginate_queryset` method is passed to the initial queryset and should return an iterable object. That object contains only the data in the requested page.
* The `get_paginated_response` method is passed the serialized page data and should return a `Response` instance. * The `get_paginated_response` method is passed to the serialized page data and should return a `Response` instance.
Note that the `paginate_queryset` method may set state on the pagination instance, that may later be used by the `get_paginated_response` method. Note that the `paginate_queryset` method may set state on the pagination instance, that may later be used by the `get_paginated_response` method.
## Example ## Example
Suppose we want to replace the default pagination output style with a modified format that includes the next and previous links under in a nested 'links' key. We could specify a custom pagination class like so: Suppose we want to replace the default pagination output style with a modified format that includes the next and previous links under in a nested 'links' key. We could specify a custom pagination class like so:
class CustomPagination(pagination.PageNumberPagination): class CustomPagination(pagination.PageNumberPagination):
def get_paginated_response(self, data): def get_paginated_response(self, data):
@ -237,7 +240,7 @@ Suppose we want to replace the default pagination output style with a modified f
'results': data 'results': data
}) })
We'd then need to setup the custom class in our configuration: We'd then need to set up the custom class in our configuration:
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination', 'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
@ -257,20 +260,9 @@ To have your custom pagination class be used by default, use the `DEFAULT_PAGINA
API responses for list endpoints will now include a `Link` header, instead of including the pagination links as part of the body of the response, for example: API responses for list endpoints will now include a `Link` header, instead of including the pagination links as part of the body of the response, for example:
## Pagination & schemas
You can also make the pagination controls available to the schema autogeneration
that REST framework provides, by implementing a `get_schema_fields()` method. This method should have the following signature:
`get_schema_fields(self, view)`
The method should return a list of `coreapi.Field` instances.
---
![Link Header][link-header] ![Link Header][link-header]
*A custom pagination style, using the 'Link' header'* *A custom pagination style, using the 'Link' header*
--- ---
@ -311,7 +303,7 @@ The [`drf-proxy-pagination` package][drf-proxy-pagination] includes a `ProxyPagi
## link-header-pagination ## link-header-pagination
The [`django-rest-framework-link-header-pagination` package][drf-link-header-pagination] includes a `LinkHeaderPagination` class which provides pagination via an HTTP `Link` header as desribed in [Github's developer documentation](github-link-pagination). The [`django-rest-framework-link-header-pagination` package][drf-link-header-pagination] includes a `LinkHeaderPagination` class which provides pagination via an HTTP `Link` header as described in [GitHub REST API documentation][github-traversing-with-pagination].
[cite]: https://docs.djangoproject.com/en/stable/topics/pagination/ [cite]: https://docs.djangoproject.com/en/stable/topics/pagination/
[link-header]: ../img/link-header-pagination.png [link-header]: ../img/link-header-pagination.png
@ -319,5 +311,6 @@ The [`django-rest-framework-link-header-pagination` package][drf-link-header-pag
[paginate-by-max-mixin]: https://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin [paginate-by-max-mixin]: https://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin
[drf-proxy-pagination]: https://github.com/tuffnatty/drf-proxy-pagination [drf-proxy-pagination]: https://github.com/tuffnatty/drf-proxy-pagination
[drf-link-header-pagination]: https://github.com/tbeadle/django-rest-framework-link-header-pagination [drf-link-header-pagination]: https://github.com/tbeadle/django-rest-framework-link-header-pagination
[disqus-cursor-api]: http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api [disqus-cursor-api]: https://cra.mr/2011/03/08/building-cursors-for-the-disqus-api
[float_cursor_pagination_example]: https://gist.github.com/keturn/8bc88525a183fd41c73ffb729b8865be#file-fpcursorpagination-py [float_cursor_pagination_example]: https://gist.github.com/keturn/8bc88525a183fd41c73ffb729b8865be#file-fpcursorpagination-py
[github-traversing-with-pagination]: https://docs.github.com/en/rest/guides/traversing-with-pagination

View File

@ -1,4 +1,7 @@
source: parsers.py ---
source:
- parsers.py
---
# Parsers # Parsers
@ -8,11 +11,11 @@ sending more complex data than simple forms
> >
> &mdash; Malcom Tredinnick, [Django developers group][cite] > &mdash; Malcom Tredinnick, [Django developers group][cite]
REST framework includes a number of built in Parser classes, that allow you to accept requests with various media types. There is also support for defining your own custom parsers, which gives you the flexibility to design the media types that your API accepts. REST framework includes a number of built-in Parser classes, that allow you to accept requests with various media types. There is also support for defining your own custom parsers, which gives you the flexibility to design the media types that your API accepts.
## How the parser is determined ## How the parser is determined
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. 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.
--- ---
@ -29,9 +32,9 @@ As an example, if you are sending `json` encoded data using jQuery with the [.aj
The default set of parsers may be set globally, using the `DEFAULT_PARSER_CLASSES` setting. For example, the following settings would allow only requests with `JSON` content, instead of the default of JSON or form data. The default set of parsers may be set globally, using the `DEFAULT_PARSER_CLASSES` setting. For example, the following settings would allow only requests with `JSON` content, instead of the default of JSON or form data.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': ( 'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser', 'rest_framework.parsers.JSONParser',
) ]
} }
You can also set the parsers used for an individual view, or viewset, You can also set the parsers used for an individual view, or viewset,
@ -45,7 +48,7 @@ using the `APIView` class-based views.
""" """
A view that can accept POST requests with JSON content. A view that can accept POST requests with JSON content.
""" """
parser_classes = (JSONParser,) parser_classes = [JSONParser]
def post(self, request, format=None): def post(self, request, format=None):
return Response({'received data': request.data}) return Response({'received data': request.data})
@ -57,7 +60,7 @@ Or, if you're using the `@api_view` decorator with function based views.
from rest_framework.parsers import JSONParser from rest_framework.parsers import JSONParser
@api_view(['POST']) @api_view(['POST'])
@parser_classes((JSONParser,)) @parser_classes([JSONParser])
def example_view(request, format=None): def example_view(request, format=None):
""" """
A view that can accept POST requests with JSON content. A view that can accept POST requests with JSON content.
@ -70,7 +73,7 @@ Or, if you're using the `@api_view` decorator with function based views.
## JSONParser ## JSONParser
Parses `JSON` request content. Parses `JSON` request content. `request.data` will be populated with a dictionary of data.
**.media_type**: `application/json` **.media_type**: `application/json`
@ -84,7 +87,7 @@ You will typically want to use both `FormParser` and `MultiPartParser` together
## MultiPartParser ## MultiPartParser
Parses multipart HTML form content, which supports file uploads. Both `request.data` will be populated with a `QueryDict`. Parses multipart HTML form content, which supports file uploads. `request.data` and `request.FILES` will be populated with a `QueryDict` and `MultiValueDict` respectively.
You will typically want to use both `FormParser` and `MultiPartParser` together in order to fully support HTML form data. You will typically want to use both `FormParser` and `MultiPartParser` together in order to fully support HTML form data.
@ -102,7 +105,7 @@ If it is called without a `filename` URL keyword argument, then the client must
##### Notes: ##### Notes:
* The `FileUploadParser` is for usage with native clients that can upload the file as a raw data request. For web-based uploads, or for native clients with multipart upload support, you should use the `MultiPartParser` parser instead. * The `FileUploadParser` is for usage with native clients that can upload the file as a raw data request. For web-based uploads, or for native clients with multipart upload support, you should use the `MultiPartParser` instead.
* Since this parser's `media_type` matches any content type, `FileUploadParser` should generally be the only parser set on an API view. * Since this parser's `media_type` matches any content type, `FileUploadParser` should generally be the only parser set on an API view.
* `FileUploadParser` respects Django's standard `FILE_UPLOAD_HANDLERS` setting, and the `request.upload_handlers` attribute. See the [Django documentation][upload-handlers] for more details. * `FileUploadParser` respects Django's standard `FILE_UPLOAD_HANDLERS` setting, and the `request.upload_handlers` attribute. See the [Django documentation][upload-handlers] for more details.
@ -110,7 +113,7 @@ If it is called without a `filename` URL keyword argument, then the client must
# views.py # views.py
class FileUploadView(views.APIView): class FileUploadView(views.APIView):
parser_classes = (FileUploadParser,) parser_classes = [FileUploadParser]
def put(self, request, filename, format=None): def put(self, request, filename, format=None):
file_obj = request.data['file'] file_obj = request.data['file']
@ -122,7 +125,7 @@ If it is called without a `filename` URL keyword argument, then the client must
# urls.py # urls.py
urlpatterns = [ urlpatterns = [
# ... # ...
url(r'^upload/(?P<filename>[^/]+)$', FileUploadView.as_view()) re_path(r'^upload/(?P<filename>[^/]+)$', FileUploadView.as_view())
] ]
--- ---
@ -186,12 +189,12 @@ Install using pip.
Modify your REST framework settings. Modify your REST framework settings.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': ( 'DEFAULT_PARSER_CLASSES': [
'rest_framework_yaml.parsers.YAMLParser', 'rest_framework_yaml.parsers.YAMLParser',
), ],
'DEFAULT_RENDERER_CLASSES': ( 'DEFAULT_RENDERER_CLASSES': [
'rest_framework_yaml.renderers.YAMLRenderer', 'rest_framework_yaml.renderers.YAMLRenderer',
), ],
} }
## XML ## XML
@ -207,12 +210,12 @@ Install using pip.
Modify your REST framework settings. Modify your REST framework settings.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': ( 'DEFAULT_PARSER_CLASSES': [
'rest_framework_xml.parsers.XMLParser', 'rest_framework_xml.parsers.XMLParser',
), ],
'DEFAULT_RENDERER_CLASSES': ( 'DEFAULT_RENDERER_CLASSES': [
'rest_framework_xml.renderers.XMLRenderer', 'rest_framework_xml.renderers.XMLRenderer',
), ],
} }
## MessagePack ## MessagePack

View File

@ -1,4 +1,7 @@
source: permissions.py ---
source:
- permissions.py
---
# Permissions # Permissions
@ -10,9 +13,9 @@ Together with [authentication] and [throttling], permissions determine whether a
Permission checks are always run at the very start of the view, before any other code is allowed to proceed. Permission checks will typically use the authentication information in the `request.user` and `request.auth` properties to determine if the incoming request should be permitted. Permission checks are always run at the very start of the view, before any other code is allowed to proceed. Permission checks will typically use the authentication information in the `request.user` and `request.auth` properties to determine if the incoming request should be permitted.
Permissions are used to grant or deny access different classes of users to different parts of the API. Permissions are used to grant or deny access for different classes of users to different parts of the API.
The simplest style of permission would be to allow access to any authenticated user, and deny access to any unauthenticated user. This corresponds the `IsAuthenticated` class in REST framework. The simplest style of permission would be to allow access to any authenticated user, and deny access to any unauthenticated user. This corresponds to the `IsAuthenticated` class in REST framework.
A slightly less strict style of permission would be to allow full access to authenticated users, but allow read-only access to unauthenticated users. This corresponds to the `IsAuthenticatedOrReadOnly` class in REST framework. A slightly less strict style of permission would be to allow full access to authenticated users, but allow read-only access to unauthenticated users. This corresponds to the `IsAuthenticatedOrReadOnly` class in REST framework.
@ -21,9 +24,9 @@ A slightly less strict style of permission would be to allow full access to auth
Permissions in REST framework are always defined as a list of permission classes. Permissions in REST framework are always defined as a list of permission classes.
Before running the main body of the view each permission in the list is checked. Before running the main body of the view each permission in the list is checked.
If any permission check fails an `exceptions.PermissionDenied` or `exceptions.NotAuthenticated` exception will be raised, and the main body of the view will not run. If any permission check fails, an `exceptions.PermissionDenied` or `exceptions.NotAuthenticated` exception will be raised, and the main body of the view will not run.
When the permissions checks fail either a "403 Forbidden" or a "401 Unauthorized" response will be returned, according to the following rules: When the permission checks fail, either a "403 Forbidden" or a "401 Unauthorized" response will be returned, according to the following rules:
* The request was successfully authenticated, but permission was denied. *&mdash; An HTTP 403 Forbidden response will be returned.* * The request was successfully authenticated, but permission was denied. *&mdash; An HTTP 403 Forbidden response will be returned.*
* The request was not successfully authenticated, and the highest priority authentication class *does not* use `WWW-Authenticate` headers. *&mdash; An HTTP 403 Forbidden response will be returned.* * The request was not successfully authenticated, and the highest priority authentication class *does not* use `WWW-Authenticate` headers. *&mdash; An HTTP 403 Forbidden response will be returned.*
@ -48,27 +51,42 @@ For example:
self.check_object_permissions(self.request, obj) self.check_object_permissions(self.request, obj)
return obj return obj
---
**Note**: With the exception of `DjangoObjectPermissions`, the provided
permission classes in `rest_framework.permissions` **do not** implement the
methods necessary to check object permissions.
If you wish to use the provided permission classes in order to check object
permissions, **you must** subclass them and implement the
`has_object_permission()` method described in the [_Custom
permissions_](#custom-permissions) section (below).
---
#### Limitations of object level permissions #### Limitations of object level permissions
For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects. For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects.
Often when you're using object level permissions you'll also want to [filter the queryset][filtering] appropriately, to ensure that users only have visibility onto instances that they are permitted to view. Often when you're using object level permissions you'll also want to [filter the queryset][filtering] appropriately, to ensure that users only have visibility onto instances that they are permitted to view.
Because the `get_object()` method is not called, object level permissions from the `has_object_permission()` method **are not applied** when creating objects. In order to restrict object creation you need to implement the permission check either in your Serializer class or override the `perform_create()` method of your ViewSet class.
## Setting the permission policy ## Setting the permission policy
The default permission policy may be set globally, using the `DEFAULT_PERMISSION_CLASSES` setting. For example. The default permission policy may be set globally, using the `DEFAULT_PERMISSION_CLASSES` setting. For example.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ( 'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated', 'rest_framework.permissions.IsAuthenticated',
) ]
} }
If not specified, this setting defaults to allowing unrestricted access: If not specified, this setting defaults to allowing unrestricted access:
'DEFAULT_PERMISSION_CLASSES': ( 'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny', 'rest_framework.permissions.AllowAny',
) ]
You can also set the authentication policy on a per-view, or per-viewset basis, You can also set the authentication policy on a per-view, or per-viewset basis,
using the `APIView` class-based views. using the `APIView` class-based views.
@ -78,7 +96,7 @@ using the `APIView` class-based views.
from rest_framework.views import APIView from rest_framework.views import APIView
class ExampleView(APIView): class ExampleView(APIView):
permission_classes = (IsAuthenticated,) permission_classes = [IsAuthenticated]
def get(self, request, format=None): def get(self, request, format=None):
content = { content = {
@ -93,14 +111,35 @@ Or, if you're using the `@api_view` decorator with function based views.
from rest_framework.response import Response from rest_framework.response import Response
@api_view(['GET']) @api_view(['GET'])
@permission_classes((IsAuthenticated, )) @permission_classes([IsAuthenticated])
def example_view(request, format=None): def example_view(request, format=None):
content = { content = {
'status': 'request was permitted' 'status': 'request was permitted'
} }
return Response(content) return Response(content)
__Note:__ when you set new permission classes through class attribute or decorators you're telling the view to ignore the default list set over the __settings.py__ file. __Note:__ when you set new permission classes via the class attribute or decorators you're telling the view to ignore the default list set in the __settings.py__ file.
Provided they inherit from `rest_framework.permissions.BasePermission`, permissions can be composed using standard Python bitwise operators. For example, `IsAuthenticatedOrReadOnly` could be written:
from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
from rest_framework.views import APIView
class ReadOnly(BasePermission):
def has_permission(self, request, view):
return request.method in SAFE_METHODS
class ExampleView(APIView):
permission_classes = [IsAuthenticated|ReadOnly]
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
__Note:__ it supports & (and), | (or) and ~ (not).
--- ---
@ -126,28 +165,22 @@ This permission is suitable if you want your API to only be accessible to a subs
## IsAuthenticatedOrReadOnly ## IsAuthenticatedOrReadOnly
The `IsAuthenticatedOrReadOnly` will allow authenticated users to perform any request. Requests for unauthorised users will only be permitted if the request method is one of the "safe" methods; `GET`, `HEAD` or `OPTIONS`. The `IsAuthenticatedOrReadOnly` will allow authenticated users to perform any request. Requests for unauthenticated users will only be permitted if the request method is one of the "safe" methods; `GET`, `HEAD` or `OPTIONS`.
This permission is suitable if you want to your API to allow read permissions to anonymous users, and only allow write permissions to authenticated users. This permission is suitable if you want to your API to allow read permissions to anonymous users, and only allow write permissions to authenticated users.
## DjangoModelPermissions ## DjangoModelPermissions
This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth]. This permission must only be applied to views that have a `.queryset` property set. Authorization will only be granted if the user *is authenticated* and has the *relevant model permissions* assigned. This permission class ties into Django's standard `django.contrib.auth` [model permissions][contribauth]. This permission must only be applied to views that have a `.queryset` property or `get_queryset()` method. Authorization will only be granted if the user *is authenticated* and has the *relevant model permissions* assigned. The appropriate model is determined by checking `get_queryset().model` or `queryset.model`.
* `POST` requests require the user to have the `add` permission on the model. * `POST` requests require the user to have the `add` permission on the model.
* `PUT` and `PATCH` requests require the user to have the `change` permission on the model. * `PUT` and `PATCH` requests require the user to have the `change` permission on the model.
* `DELETE` requests require the user to have the `delete` permission on the model. * `DELETE` requests require the user to have the `delete` permission on the model.
The default behaviour can also be overridden to support custom model permissions. For example, you might want to include a `view` model permission for `GET` requests. The default behavior can also be overridden to support custom model permissions. For example, you might want to include a `view` model permission for `GET` requests.
To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property. Refer to the source code for details. To use custom model permissions, override `DjangoModelPermissions` and set the `.perms_map` property. Refer to the source code for details.
#### Using with views that do not include a `queryset` attribute.
If you're using this permission with a view that uses an overridden `get_queryset()` method there may not be a `queryset` attribute on the view. In this case we suggest also marking the view with a sentinel queryset, so that this class can determine the required permissions. For example:
queryset = User.objects.none() # Required for DjangoModelPermissions
## DjangoModelPermissionsOrAnonReadOnly ## DjangoModelPermissionsOrAnonReadOnly
Similar to `DjangoModelPermissions`, but also allows unauthenticated users to have read-only access to the API. Similar to `DjangoModelPermissions`, but also allows unauthenticated users to have read-only access to the API.
@ -168,9 +201,7 @@ As with `DjangoModelPermissions` you can use custom model permissions by overrid
--- ---
**Note**: If you need object level `view` permissions for `GET`, `HEAD` and `OPTIONS` requests, you'll want to consider also adding the `DjangoObjectPermissionsFilter` class to ensure that list endpoints only return results including objects for which the user has appropriate view permissions. **Note**: If you need object level `view` permissions for `GET`, `HEAD` and `OPTIONS` requests and are using django-guardian for your object-level permissions backend, you'll want to consider using the `DjangoObjectPermissionsFilter` class provided by the [`djangorestframework-guardian` package][django-rest-framework-guardian]. It ensures that list endpoints only return results including objects for which the user has appropriate view permissions.
---
--- ---
@ -196,7 +227,7 @@ If you need to test if a request is a read operation or a write operation, you s
--- ---
Custom permissions will raise a `PermissionDenied` exception if the test fails. To change the error message associated with the exception, implement a `message` attribute directly on your custom permission. Otherwise the `default_detail` attribute from `PermissionDenied` will be used. Custom permissions will raise a `PermissionDenied` exception if the test fails. To change the error message associated with the exception, implement a `message` attribute directly on your custom permission. Otherwise the `default_detail` attribute from `PermissionDenied` will be used. Similarly, to change the code identifier associated with the exception, implement a `code` attribute directly on your custom permission - otherwise the `default_code` attribute from `PermissionDenied` will be used.
from rest_framework import permissions from rest_framework import permissions
@ -208,19 +239,19 @@ Custom permissions will raise a `PermissionDenied` exception if the test fails.
## Examples ## Examples
The following is an example of a permission class that checks the incoming request's IP address against a blacklist, and denies the request if the IP has been blacklisted. The following is an example of a permission class that checks the incoming request's IP address against a blocklist, and denies the request if the IP has been blocked.
from rest_framework import permissions from rest_framework import permissions
class BlacklistPermission(permissions.BasePermission): class BlocklistPermission(permissions.BasePermission):
""" """
Global permission check for blacklisted IPs. Global permission check for blocked IPs.
""" """
def has_permission(self, request, view): def has_permission(self, request, view):
ip_addr = request.META['REMOTE_ADDR'] ip_addr = request.META['REMOTE_ADDR']
blacklisted = Blacklist.objects.filter(ip_addr=ip_addr).exists() blocked = Blocklist.objects.filter(ip_addr=ip_addr).exists()
return not blacklisted return not blocked
As well as global permissions, that are run against all incoming requests, you can also create object-level permissions, that are only run against operations that affect a particular object instance. For example: As well as global permissions, that are run against all incoming requests, you can also create object-level permissions, that are only run against operations that affect a particular object instance. For example:
@ -243,19 +274,47 @@ Note that the generic views will check the appropriate object level permissions,
Also note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you'll need to filter the queryset separately. See the [filtering documentation][filtering] for more details. Also note that the generic views will only check the object-level permissions for views that retrieve a single model instance. If you require object-level filtering of list views, you'll need to filter the queryset separately. See the [filtering documentation][filtering] for more details.
# Overview of access restriction methods
REST framework offers three different methods to customize access restrictions on a case-by-case basis. These apply in different scenarios and have different effects and limitations.
* `queryset`/`get_queryset()`: Limits the general visibility of existing objects from the database. The queryset limits which objects will be listed and which objects can be modified or deleted. The `get_queryset()` method can apply different querysets based on the current action.
* `permission_classes`/`get_permissions()`: General permission checks based on the current action, request and targeted object. Object level permissions can only be applied to retrieve, modify and deletion actions. Permission checks for list and create will be applied to the entire object type. (In case of list: subject to restrictions in the queryset.)
* `serializer_class`/`get_serializer()`: Instance level restrictions that apply to all objects on input and output. The serializer may have access to the request context. The `get_serializer()` method can apply different serializers based on the current action.
The following table lists the access restriction methods and the level of control they offer over which actions.
| | `queryset` | `permission_classes` | `serializer_class` |
|------------------------------------|------------|----------------------|--------------------|
| Action: list | global | global | object-level* |
| Action: create | no | global | object-level |
| Action: retrieve | global | object-level | object-level |
| Action: update | global | object-level | object-level |
| Action: partial_update | global | object-level | object-level |
| Action: destroy | global | object-level | no |
| Can reference action in decision | no** | yes | no** |
| Can reference request in decision | no** | yes | yes |
\* A Serializer class should not raise PermissionDenied in a list action, or the entire list would not be returned. <br>
\** The `get_*()` methods have access to the current view and can return different Serializer or QuerySet instances based on the request or action.
--- ---
# Third party packages # Third party packages
The following third party packages are also available. The following third party packages are also available.
## DRF - Access Policy
The [Django REST - Access Policy][drf-access-policy] package provides a way to define complex access rules in declarative policy classes that are attached to view sets or function-based views. The policies are defined in JSON in a format similar to AWS' Identity & Access Management policies.
## Composed Permissions ## Composed Permissions
The [Composed Permissions][composed-permissions] package provides a simple way to define complex and multi-depth (with logic operators) permission objects, using small and reusable components. The [Composed Permissions][composed-permissions] package provides a simple way to define complex and multi-depth (with logic operators) permission objects, using small and reusable components.
## REST Condition ## REST Condition
The [REST Condition][rest-condition] package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators. The [REST Condition][rest-condition] package is another extension for building complex permissions in a simple and convenient way. The extension allows you to combine permissions with logical operators.
## DRY Rest Permissions ## DRY Rest Permissions
@ -265,14 +324,23 @@ The [DRY Rest Permissions][dry-rest-permissions] package provides the ability to
The [Django Rest Framework Roles][django-rest-framework-roles] package makes it easier to parameterize your API over multiple types of users. The [Django Rest Framework Roles][django-rest-framework-roles] package makes it easier to parameterize your API over multiple types of users.
## Django Rest Framework API Key ## Rest Framework Roles
The [Django Rest Framework API Key][django-rest-framework-api-key] package allows you to ensure that every request made to the server requires an API key header. You can generate one from the django admin interface. The [Rest Framework Roles][rest-framework-roles] makes it super easy to protect views based on roles. Most importantly allows you to decouple accessibility logic from models and views in a clean human-readable way.
## Django REST Framework API Key
The [Django REST Framework API Key][djangorestframework-api-key] package provides permissions classes, models and helpers to add API key authorization to your API. It can be used to authorize internal or third-party backends and services (i.e. _machines_) which do not have a user account. API keys are stored securely using Django's password hashing infrastructure, and they can be viewed, edited and revoked at anytime in the Django admin.
## Django Rest Framework Role Filters ## Django Rest Framework Role Filters
The [Django Rest Framework Role Filters][django-rest-framework-role-filters] package provides simple filtering over multiple types of roles. The [Django Rest Framework Role Filters][django-rest-framework-role-filters] package provides simple filtering over multiple types of roles.
## Django Rest Framework PSQ
The [Django Rest Framework PSQ][drf-psq] package is an extension that gives support for having action-based **permission_classes**, **serializer_class**, and **queryset** dependent on permission-based rules.
[cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html [cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html
[authentication]: authentication.md [authentication]: authentication.md
[throttling]: throttling.md [throttling]: throttling.md
@ -283,7 +351,11 @@ The [Django Rest Framework Role Filters][django-rest-framework-role-filters] pac
[filtering]: filtering.md [filtering]: filtering.md
[composed-permissions]: https://github.com/niwibe/djangorestframework-composed-permissions [composed-permissions]: https://github.com/niwibe/djangorestframework-composed-permissions
[rest-condition]: https://github.com/caxap/rest_condition [rest-condition]: https://github.com/caxap/rest_condition
[dry-rest-permissions]: https://github.com/Helioscene/dry-rest-permissions [dry-rest-permissions]: https://github.com/FJNR-inc/dry-rest-permissions
[django-rest-framework-roles]: https://github.com/computer-lab/django-rest-framework-roles [django-rest-framework-roles]: https://github.com/computer-lab/django-rest-framework-roles
[django-rest-framework-api-key]: https://github.com/manosim/django-rest-framework-api-key [rest-framework-roles]: https://github.com/Pithikos/rest-framework-roles
[djangorestframework-api-key]: https://florimondmanca.github.io/djangorestframework-api-key/
[django-rest-framework-role-filters]: https://github.com/allisson/django-rest-framework-role-filters [django-rest-framework-role-filters]: https://github.com/allisson/django-rest-framework-role-filters
[django-rest-framework-guardian]: https://github.com/rpkilby/django-rest-framework-guardian
[drf-access-policy]: https://github.com/rsinger86/drf-access-policy
[drf-psq]: https://github.com/drf-psq/drf-psq

View File

@ -1,12 +1,13 @@
source: relations.py ---
source:
- relations.py
---
# Serializer relations # Serializer relations
> Bad programmers worry about the code. > Data structures, not algorithms, are central to programming.
> Good programmers worry about data structures and their relationships.
> >
> &mdash; [Linus Torvalds][cite] > &mdash; [Rob Pike][cite]
Relational fields are used to represent model relationships. They can be applied to `ForeignKey`, `ManyToManyField` and `OneToOneField` relationships, as well as to reverse relationships, and custom relationships such as `GenericForeignKey`. Relational fields are used to represent model relationships. They can be applied to `ForeignKey`, `ManyToManyField` and `OneToOneField` relationships, as well as to reverse relationships, and custom relationships such as `GenericForeignKey`.
@ -16,6 +17,37 @@ Relational fields are used to represent model relationships. They can be applie
--- ---
---
**Note:** REST Framework does not attempt to automatically optimize querysets passed to serializers in terms of `select_related` and `prefetch_related` since it would be too much magic. A serializer with a field spanning an orm relation through its source attribute could require an additional database hit to fetch related objects from the database. It is the programmer's responsibility to optimize queries to avoid additional database hits which could occur while using such a serializer.
For example, the following serializer would lead to a database hit each time evaluating the tracks field if it is not prefetched:
class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.SlugRelatedField(
many=True,
read_only=True,
slug_field='title'
)
class Meta:
model = Album
fields = ['album_name', 'artist', 'tracks']
# For each album object, tracks should be fetched from database
qs = Album.objects.all()
print(AlbumSerializer(qs, many=True).data)
If `AlbumSerializer` is used to serialize a fairly large queryset with `many=True` then it could be a serious performance problem. Optimizing the queryset passed to `AlbumSerializer` with:
qs = Album.objects.prefetch_related('tracks')
# No additional database hits required
print(AlbumSerializer(qs, many=True).data)
would solve the issue.
---
#### Inspecting relationships. #### Inspecting relationships.
When using the `ModelSerializer` class, serializer fields and relationships will be automatically generated for you. Inspecting these automatically generated fields can be a useful tool for determining how to customize the relationship style. When using the `ModelSerializer` class, serializer fields and relationships will be automatically generated for you. Inspecting these automatically generated fields can be a useful tool for determining how to customize the relationship style.
@ -24,7 +56,7 @@ To do so, open the Django shell, using `python manage.py shell`, then import the
>>> from myapp.serializers import AccountSerializer >>> from myapp.serializers import AccountSerializer
>>> serializer = AccountSerializer() >>> serializer = AccountSerializer()
>>> print repr(serializer) # Or `print(repr(serializer))` in Python 3.x. >>> print(repr(serializer))
AccountSerializer(): AccountSerializer():
id = IntegerField(label='ID', read_only=True) id = IntegerField(label='ID', read_only=True)
name = CharField(allow_blank=True, max_length=100, required=False) name = CharField(allow_blank=True, max_length=100, required=False)
@ -45,26 +77,26 @@ In order to explain the various types of relational fields, we'll use a couple o
duration = models.IntegerField() duration = models.IntegerField()
class Meta: class Meta:
unique_together = ('album', 'order') unique_together = ['album', 'order']
ordering = ['order'] ordering = ['order']
def __unicode__(self): def __str__(self):
return '%d: %s' % (self.order, self.title) return '%d: %s' % (self.order, self.title)
## StringRelatedField ## StringRelatedField
`StringRelatedField` may be used to represent the target of the relationship using its `__unicode__` method. `StringRelatedField` may be used to represent the target of the relationship using its `__str__` method.
For example, the following serializer. For example, the following serializer:
class AlbumSerializer(serializers.ModelSerializer): class AlbumSerializer(serializers.ModelSerializer):
tracks = serializers.StringRelatedField(many=True) tracks = serializers.StringRelatedField(many=True)
class Meta: class Meta:
model = Album model = Album
fields = ('album_name', 'artist', 'tracks') fields = ['album_name', 'artist', 'tracks']
Would serialize to the following representation. Would serialize to the following representation:
{ {
'album_name': 'Things We Lost In The Fire', 'album_name': 'Things We Lost In The Fire',
@ -94,7 +126,7 @@ For example, the following serializer:
class Meta: class Meta:
model = Album model = Album
fields = ('album_name', 'artist', 'tracks') fields = ['album_name', 'artist', 'tracks']
Would serialize to a representation like this: Would serialize to a representation like this:
@ -134,7 +166,7 @@ For example, the following serializer:
class Meta: class Meta:
model = Album model = Album
fields = ('album_name', 'artist', 'tracks') fields = ['album_name', 'artist', 'tracks']
Would serialize to a representation like this: Would serialize to a representation like this:
@ -186,7 +218,7 @@ For example, the following serializer:
class Meta: class Meta:
model = Album model = Album
fields = ('album_name', 'artist', 'tracks') fields = ['album_name', 'artist', 'tracks']
Would serialize to a representation like this: Would serialize to a representation like this:
@ -214,14 +246,14 @@ When using `SlugRelatedField` as a read-write field, you will normally want to e
## HyperlinkedIdentityField ## HyperlinkedIdentityField
This field can be applied as an identity relationship, such as the `'url'` field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer: This field can be applied as an identity relationship, such as the `'url'` field on a HyperlinkedModelSerializer. It can also be used for an attribute on the object. For example, the following serializer:
class AlbumSerializer(serializers.HyperlinkedModelSerializer): class AlbumSerializer(serializers.HyperlinkedModelSerializer):
track_listing = serializers.HyperlinkedIdentityField(view_name='track-list') track_listing = serializers.HyperlinkedIdentityField(view_name='track-list')
class Meta: class Meta:
model = Album model = Album
fields = ('album_name', 'artist', 'track_listing') fields = ['album_name', 'artist', 'track_listing']
Would serialize to a representation like this: Would serialize to a representation like this:
@ -244,7 +276,9 @@ This field is always read-only.
# Nested relationships # Nested relationships
Nested relationships can be expressed by using serializers as fields. As opposed to previously discussed _references_ to another entity, the referred entity can instead also be embedded or _nested_
in the representation of the object that refers to it.
Such nested relationships can be expressed by using serializers as fields.
If the field is used to represent a to-many relationship, you should add the `many=True` flag to the serializer field. If the field is used to represent a to-many relationship, you should add the `many=True` flag to the serializer field.
@ -255,14 +289,14 @@ For example, the following serializer:
class TrackSerializer(serializers.ModelSerializer): class TrackSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Track model = Track
fields = ('order', 'title', 'duration') fields = ['order', 'title', 'duration']
class AlbumSerializer(serializers.ModelSerializer): class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True, read_only=True) tracks = TrackSerializer(many=True, read_only=True)
class Meta: class Meta:
model = Album model = Album
fields = ('album_name', 'artist', 'tracks') fields = ['album_name', 'artist', 'tracks']
Would serialize to a nested representation like this: Would serialize to a nested representation like this:
@ -288,19 +322,19 @@ Would serialize to a nested representation like this:
## Writable nested serializers ## Writable nested serializers
By default nested serializers are read-only. If you want to support write-operations to a nested serializer field you'll need to create `create()` and/or `update()` methods in order to explicitly specify how the child relationships should be saved. By default nested serializers are read-only. If you want to support write-operations to a nested serializer field you'll need to create `create()` and/or `update()` methods in order to explicitly specify how the child relationships should be saved:
class TrackSerializer(serializers.ModelSerializer): class TrackSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Track model = Track
fields = ('order', 'title', 'duration') fields = ['order', 'title', 'duration']
class AlbumSerializer(serializers.ModelSerializer): class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True) tracks = TrackSerializer(many=True)
class Meta: class Meta:
model = Album model = Album
fields = ('album_name', 'artist', 'tracks') fields = ['album_name', 'artist', 'tracks']
def create(self, validated_data): def create(self, validated_data):
tracks_data = validated_data.pop('tracks') tracks_data = validated_data.pop('tracks')
@ -334,13 +368,13 @@ output representation should be generated from the model instance.
To implement a custom relational field, you should override `RelatedField`, and implement the `.to_representation(self, value)` method. This method takes the target of the field as the `value` argument, and should return the representation that should be used to serialize the target. The `value` argument will typically be a model instance. To implement a custom relational field, you should override `RelatedField`, and implement the `.to_representation(self, value)` method. This method takes the target of the field as the `value` argument, and should return the representation that should be used to serialize the target. The `value` argument will typically be a model instance.
If you want to implement a read-write relational field, you must also implement the `.to_internal_value(self, data)` method. If you want to implement a read-write relational field, you must also implement the [`.to_internal_value(self, data)` method][to_internal_value].
To provide a dynamic queryset based on the `context`, you can also override `.get_queryset(self)` instead of specifying `.queryset` on the class or when initializing the field. To provide a dynamic queryset based on the `context`, you can also override `.get_queryset(self)` instead of specifying `.queryset` on the class or when initializing the field.
## Example ## Example
For example, we could define a relational field to serialize a track to a custom string representation, using its ordering, title, and duration. For example, we could define a relational field to serialize a track to a custom string representation, using its ordering, title, and duration:
import time import time
@ -354,9 +388,9 @@ For example, we could define a relational field to serialize a track to a custom
class Meta: class Meta:
model = Album model = Album
fields = ('album_name', 'artist', 'tracks') fields = ['album_name', 'artist', 'tracks']
This custom field would then serialize to the following representation. This custom field would then serialize to the following representation:
{ {
'album_name': 'Sometimes I Wish We Were an Eagle', 'album_name': 'Sometimes I Wish We Were an Eagle',
@ -384,7 +418,7 @@ The `get_url` method is used to map the object instance to its URL representatio
May raise a `NoReverseMatch` if the `view_name` and `lookup_field` May raise a `NoReverseMatch` if the `view_name` and `lookup_field`
attributes are not configured to correctly match the URL conf. attributes are not configured to correctly match the URL conf.
**get_object(self, queryset, view_name, view_args, view_kwargs)** **get_object(self, view_name, view_args, view_kwargs)**
If you want to support a writable hyperlinked field then you'll also want to override `get_object`, in order to map incoming URLs back to the object they represent. For read-only hyperlinked fields there is no need to override this method. If you want to support a writable hyperlinked field then you'll also want to override `get_object`, in order to map incoming URLs back to the object they represent. For read-only hyperlinked fields there is no need to override this method.
@ -460,8 +494,8 @@ This behavior is intended to prevent a template from being unable to render in a
There are two keyword arguments you can use to control this behavior: There are two keyword arguments you can use to control this behavior:
- `html_cutoff` - If set this will be the maximum number of choices that will be displayed by a HTML select drop down. Set to `None` to disable any limiting. Defaults to `1000`. * `html_cutoff` - If set this will be the maximum number of choices that will be displayed by a HTML select drop down. Set to `None` to disable any limiting. Defaults to `1000`.
- `html_cutoff_text` - If set this will display a textual indicator if the maximum number of items have been cutoff in an HTML select drop down. Defaults to `"More than {count} items…"` * `html_cutoff_text` - If set this will display a textual indicator if the maximum number of items have been cutoff in an HTML select drop down. Defaults to `"More than {count} items…"`
You can also control these globally using the settings `HTML_SELECT_CUTOFF` and `HTML_SELECT_CUTOFF_TEXT`. You can also control these globally using the settings `HTML_SELECT_CUTOFF` and `HTML_SELECT_CUTOFF_TEXT`.
@ -479,7 +513,7 @@ Note that reverse relationships are not automatically included by the `ModelSeri
class AlbumSerializer(serializers.ModelSerializer): class AlbumSerializer(serializers.ModelSerializer):
class Meta: class Meta:
fields = ('tracks', ...) fields = ['tracks', ...]
You'll normally want to ensure that you've set an appropriate `related_name` argument on the relationship, that you can use as the field name. For example: You'll normally want to ensure that you've set an appropriate `related_name` argument on the relationship, that you can use as the field name. For example:
@ -491,7 +525,7 @@ If you have not set a related name for the reverse relationship, you'll need to
class AlbumSerializer(serializers.ModelSerializer): class AlbumSerializer(serializers.ModelSerializer):
class Meta: class Meta:
fields = ('track_set', ...) fields = ['track_set', ...]
See the Django documentation on [reverse relationships][reverse-relationships] for more details. See the Django documentation on [reverse relationships][reverse-relationships] for more details.
@ -512,7 +546,7 @@ For example, given the following model for a tag, which has a generic relationsh
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
tagged_object = GenericForeignKey('content_type', 'object_id') tagged_object = GenericForeignKey('content_type', 'object_id')
def __unicode__(self): def __str__(self):
return self.tag_name return self.tag_name
And the following two models, which may have associated tags: And the following two models, which may have associated tags:
@ -532,7 +566,7 @@ And the following two models, which may have associated tags:
text = models.CharField(max_length=1000) text = models.CharField(max_length=1000)
tags = GenericRelation(TaggedItem) tags = GenericRelation(TaggedItem)
We could define a custom field that could be used to serialize tagged instances, using the type of each instance to determine how it should be serialized. We could define a custom field that could be used to serialize tagged instances, using the type of each instance to determine how it should be serialized:
class TaggedObjectRelatedField(serializers.RelatedField): class TaggedObjectRelatedField(serializers.RelatedField):
""" """
@ -578,6 +612,8 @@ If you explicitly specify a relational field pointing to a
``ManyToManyField`` with a through model, be sure to set ``read_only`` ``ManyToManyField`` with a through model, be sure to set ``read_only``
to ``True``. to ``True``.
If you wish to represent [extra fields on a through model][django-intermediary-manytomany] then you may serialize the through model as [a nested object][dealing-with-nested-objects].
--- ---
# Third Party Packages # Third Party Packages
@ -592,9 +628,16 @@ The [drf-nested-routers package][drf-nested-routers] provides routers and relati
The [rest-framework-generic-relations][drf-nested-relations] library provides read/write serialization for generic foreign keys. The [rest-framework-generic-relations][drf-nested-relations] library provides read/write serialization for generic foreign keys.
[cite]: https://lwn.net/Articles/193245/ The [rest-framework-gm2m-relations][drf-gm2m-relations] library provides read/write serialization for [django-gm2m][django-gm2m-field].
[cite]: http://users.ece.utexas.edu/~adnan/pike.html
[reverse-relationships]: https://docs.djangoproject.com/en/stable/topics/db/queries/#following-relationships-backward [reverse-relationships]: https://docs.djangoproject.com/en/stable/topics/db/queries/#following-relationships-backward
[routers]: http://www.django-rest-framework.org/api-guide/routers#defaultrouter [routers]: https://www.django-rest-framework.org/api-guide/routers#defaultrouter
[generic-relations]: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#id1 [generic-relations]: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#id1
[drf-nested-routers]: https://github.com/alanjds/drf-nested-routers [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers
[drf-nested-relations]: https://github.com/Ian-Foote/rest-framework-generic-relations [drf-nested-relations]: https://github.com/Ian-Foote/rest-framework-generic-relations
[drf-gm2m-relations]: https://github.com/mojtabaakbari221b/rest-framework-gm2m-relations
[django-gm2m-field]: https://github.com/tkhyn/django-gm2m
[django-intermediary-manytomany]: https://docs.djangoproject.com/en/stable/topics/db/models/#intermediary-manytomany
[dealing-with-nested-objects]: https://www.django-rest-framework.org/api-guide/serializers/#dealing-with-nested-objects
[to_internal_value]: https://www.django-rest-framework.org/api-guide/serializers/#to_internal_valueself-data

View File

@ -1,4 +1,7 @@
source: renderers.py ---
source:
- renderers.py
---
# Renderers # Renderers
@ -21,10 +24,10 @@ For more information see the documentation on [content negotiation][conneg].
The default set of renderers may be set globally, using the `DEFAULT_RENDERER_CLASSES` setting. For example, the following settings would use `JSON` as the main media type and also include the self describing API. The default set of renderers may be set globally, using the `DEFAULT_RENDERER_CLASSES` setting. For example, the following settings would use `JSON` as the main media type and also include the self describing API.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( 'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer', 'rest_framework.renderers.BrowsableAPIRenderer',
) ]
} }
You can also set the renderers used for an individual view, or viewset, You can also set the renderers used for an individual view, or viewset,
@ -39,7 +42,7 @@ using the `APIView` class-based views.
""" """
A view that returns the count of active users in JSON. A view that returns the count of active users in JSON.
""" """
renderer_classes = (JSONRenderer, ) renderer_classes = [JSONRenderer]
def get(self, request, format=None): def get(self, request, format=None):
user_count = User.objects.filter(active=True).count() user_count = User.objects.filter(active=True).count()
@ -49,7 +52,7 @@ using the `APIView` class-based views.
Or, if you're using the `@api_view` decorator with function based views. Or, if you're using the `@api_view` decorator with function based views.
@api_view(['GET']) @api_view(['GET'])
@renderer_classes((JSONRenderer,)) @renderer_classes([JSONRenderer])
def user_count_view(request, format=None): def user_count_view(request, format=None):
""" """
A view that returns the count of active users in JSON. A view that returns the count of active users in JSON.
@ -89,7 +92,7 @@ The default JSON encoding style can be altered using the `UNICODE_JSON` and `COM
**.media_type**: `application/json` **.media_type**: `application/json`
**.format**: `'.json'` **.format**: `'json'`
**.charset**: `None` **.charset**: `None`
@ -100,6 +103,16 @@ Unlike other renderers, the data passed to the `Response` does not need to be se
The TemplateHTMLRenderer will create a `RequestContext`, using the `response.data` as the context dict, and determine a template name to use to render the context. The TemplateHTMLRenderer will create a `RequestContext`, using the `response.data` as the context dict, and determine a template name to use to render the context.
---
**Note:** When used with a view that makes use of a serializer the `Response` sent for rendering may not be a dictionary and will need to be wrapped in a dict before returning to allow the `TemplateHTMLRenderer` to render it. For example:
```
response.data = {'results': response.data}
```
---
The template name is determined by (in order of preference): The template name is determined by (in order of preference):
1. An explicit `template_name` argument passed to the response. 1. An explicit `template_name` argument passed to the response.
@ -113,7 +126,7 @@ An example of a view that uses `TemplateHTMLRenderer`:
A view that returns a templated HTML representation of a given user. A view that returns a templated HTML representation of a given user.
""" """
queryset = User.objects.all() queryset = User.objects.all()
renderer_classes = (TemplateHTMLRenderer,) renderer_classes = [TemplateHTMLRenderer]
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
@ -127,7 +140,7 @@ See the [_HTML & Forms_ Topic Page][html-and-forms] for further examples of `Tem
**.media_type**: `text/html` **.media_type**: `text/html`
**.format**: `'.html'` **.format**: `'html'`
**.charset**: `utf-8` **.charset**: `utf-8`
@ -139,8 +152,8 @@ A simple renderer that simply returns pre-rendered HTML. Unlike other renderers
An example of a view that uses `StaticHTMLRenderer`: An example of a view that uses `StaticHTMLRenderer`:
@api_view(('GET',)) @api_view(['GET'])
@renderer_classes((StaticHTMLRenderer,)) @renderer_classes([StaticHTMLRenderer])
def simple_html_view(request): def simple_html_view(request):
data = '<html><body><h1>Hello, world</h1></body></html>' data = '<html><body><h1>Hello, world</h1></body></html>'
return Response(data) return Response(data)
@ -149,7 +162,7 @@ You can use `StaticHTMLRenderer` either to return regular HTML pages using REST
**.media_type**: `text/html` **.media_type**: `text/html`
**.format**: `'.html'` **.format**: `'html'`
**.charset**: `utf-8` **.charset**: `utf-8`
@ -165,7 +178,7 @@ This renderer will determine which other renderer would have been given highest
**.media_type**: `text/html` **.media_type**: `text/html`
**.format**: `'.api'` **.format**: `'api'`
**.charset**: `utf-8` **.charset**: `utf-8`
@ -179,7 +192,7 @@ By default the response content will be rendered with the highest priority rende
def get_default_renderer(self, view): def get_default_renderer(self, view):
return JSONRenderer() return JSONRenderer()
## AdminRenderer ## AdminRenderer
Renders data into HTML for an admin-like display: Renders data into HTML for an admin-like display:
@ -200,7 +213,7 @@ Note that views that have nested or list serializers for their input won't work
**.media_type**: `text/html` **.media_type**: `text/html`
**.format**: `'.admin'` **.format**: `'admin'`
**.charset**: `utf-8` **.charset**: `utf-8`
@ -224,7 +237,7 @@ For more information see the [HTML & Forms][html-and-forms] documentation.
**.media_type**: `text/html` **.media_type**: `text/html`
**.format**: `'.form'` **.format**: `'form'`
**.charset**: `utf-8` **.charset**: `utf-8`
@ -236,7 +249,7 @@ This renderer is used for rendering HTML multipart form data. **It is not suita
**.media_type**: `multipart/form-data; boundary=BoUnDaRyStRiNg` **.media_type**: `multipart/form-data; boundary=BoUnDaRyStRiNg`
**.format**: `'.multipart'` **.format**: `'multipart'`
**.charset**: `utf-8` **.charset**: `utf-8`
@ -244,7 +257,7 @@ This renderer is used for rendering HTML multipart form data. **It is not suita
# Custom renderers # Custom renderers
To implement a custom renderer, you should override `BaseRenderer`, set the `.media_type` and `.format` properties, and implement the `.render(self, data, media_type=None, renderer_context=None)` method. To implement a custom renderer, you should override `BaseRenderer`, set the `.media_type` and `.format` properties, and implement the `.render(self, data, accepted_media_type=None, renderer_context=None)` method.
The method should return a bytestring, which will be used as the body of the HTTP response. The method should return a bytestring, which will be used as the body of the HTTP response.
@ -254,7 +267,7 @@ The arguments passed to the `.render()` method are:
The request data, as set by the `Response()` instantiation. The request data, as set by the `Response()` instantiation.
### `media_type=None` ### `accepted_media_type=None`
Optional. If provided, this is the accepted media type, as determined by the content negotiation stage. Optional. If provided, this is the accepted media type, as determined by the content negotiation stage.
@ -270,7 +283,7 @@ By default this will include the following keys: `view`, `request`, `response`,
The following is an example plaintext renderer that will return a response with the `data` parameter as the content of the response. The following is an example plaintext renderer that will return a response with the `data` parameter as the content of the response.
from django.utils.encoding import smart_unicode from django.utils.encoding import smart_str
from rest_framework import renderers from rest_framework import renderers
@ -278,8 +291,8 @@ The following is an example plaintext renderer that will return a response with
media_type = 'text/plain' media_type = 'text/plain'
format = 'txt' format = 'txt'
def render(self, data, media_type=None, renderer_context=None): def render(self, data, accepted_media_type=None, renderer_context=None):
return data.encode(self.charset) return smart_str(data, encoding=self.charset)
## Setting the character set ## Setting the character set
@ -290,7 +303,7 @@ By default renderer classes are assumed to be using the `UTF-8` encoding. To us
format = 'txt' format = 'txt'
charset = 'iso-8859-1' charset = 'iso-8859-1'
def render(self, data, media_type=None, renderer_context=None): def render(self, data, accepted_media_type=None, renderer_context=None):
return data.encode(self.charset) return data.encode(self.charset)
Note that if a renderer class returns a unicode string, then the response content will be coerced into a bytestring by the `Response` class, with the `charset` attribute set on the renderer used to determine the encoding. Note that if a renderer class returns a unicode string, then the response content will be coerced into a bytestring by the `Response` class, with the `charset` attribute set on the renderer used to determine the encoding.
@ -305,7 +318,7 @@ In some cases you may also want to set the `render_style` attribute to `'binary'
charset = None charset = None
render_style = 'binary' render_style = 'binary'
def render(self, data, media_type=None, renderer_context=None): def render(self, data, accepted_media_type=None, renderer_context=None):
return data return data
--- ---
@ -319,14 +332,14 @@ You can do some pretty flexible things using REST framework's renderers. Some e
* Specify multiple types of HTML representation for API clients to use. * Specify multiple types of HTML representation for API clients to use.
* Underspecify a renderer's media type, such as using `media_type = 'image/*'`, and use the `Accept` header to vary the encoding of the response. * Underspecify a renderer's media type, such as using `media_type = 'image/*'`, and use the `Accept` header to vary the encoding of the response.
## Varying behaviour by media type ## Varying behavior by media type
In some cases you might want your view to use different serialization styles depending on the accepted media type. If you need to do this you can access `request.accepted_renderer` to determine the negotiated renderer that will be used for the response. In some cases you might want your view to use different serialization styles depending on the accepted media type. If you need to do this you can access `request.accepted_renderer` to determine the negotiated renderer that will be used for the response.
For example: For example:
@api_view(('GET',)) @api_view(['GET'])
@renderer_classes((TemplateHTMLRenderer, JSONRenderer)) @renderer_classes([TemplateHTMLRenderer, JSONRenderer])
def list_users(request): def list_users(request):
""" """
A view that can return JSON or HTML representations A view that can return JSON or HTML representations
@ -398,12 +411,12 @@ Install using pip.
Modify your REST framework settings. Modify your REST framework settings.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': ( 'DEFAULT_PARSER_CLASSES': [
'rest_framework_yaml.parsers.YAMLParser', 'rest_framework_yaml.parsers.YAMLParser',
), ],
'DEFAULT_RENDERER_CLASSES': ( 'DEFAULT_RENDERER_CLASSES': [
'rest_framework_yaml.renderers.YAMLRenderer', 'rest_framework_yaml.renderers.YAMLRenderer',
), ],
} }
## XML ## XML
@ -419,12 +432,12 @@ Install using pip.
Modify your REST framework settings. Modify your REST framework settings.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES': ( 'DEFAULT_PARSER_CLASSES': [
'rest_framework_xml.parsers.XMLParser', 'rest_framework_xml.parsers.XMLParser',
), ],
'DEFAULT_RENDERER_CLASSES': ( 'DEFAULT_RENDERER_CLASSES': [
'rest_framework_xml.renderers.XMLRenderer', 'rest_framework_xml.renderers.XMLRenderer',
), ],
} }
## JSONP ## JSONP
@ -448,22 +461,59 @@ Install using pip.
Modify your REST framework settings. Modify your REST framework settings.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( 'DEFAULT_RENDERER_CLASSES': [
'rest_framework_jsonp.renderers.JSONPRenderer', 'rest_framework_jsonp.renderers.JSONPRenderer',
), ],
} }
## MessagePack ## MessagePack
[MessagePack][messagepack] is a fast, efficient binary serialization format. [Juan Riaza][juanriaza] maintains the [djangorestframework-msgpack][djangorestframework-msgpack] package which provides MessagePack renderer and parser support for REST framework. [MessagePack][messagepack] is a fast, efficient binary serialization format. [Juan Riaza][juanriaza] maintains the [djangorestframework-msgpack][djangorestframework-msgpack] package which provides MessagePack renderer and parser support for REST framework.
## Microsoft Excel: XLSX (Binary Spreadsheet Endpoints)
XLSX is the world's most popular binary spreadsheet format. [Tim Allen][flipperpa] of [The Wharton School][wharton] maintains [drf-excel][drf-excel], which renders an endpoint as an XLSX spreadsheet using OpenPyXL, and allows the client to download it. Spreadsheets can be styled on a per-view basis.
#### Installation & configuration
Install using pip.
$ pip install drf-excel
Modify your REST framework settings.
REST_FRAMEWORK = {
...
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
'drf_excel.renderers.XLSXRenderer',
],
}
To avoid having a file streamed without a filename (which the browser will often default to the filename "download", with no extension), we need to use a mixin to override the `Content-Disposition` header. If no filename is provided, it will default to `export.xlsx`. For example:
from rest_framework.viewsets import ReadOnlyModelViewSet
from drf_excel.mixins import XLSXFileMixin
from drf_excel.renderers import XLSXRenderer
from .models import MyExampleModel
from .serializers import MyExampleSerializer
class MyExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet):
queryset = MyExampleModel.objects.all()
serializer_class = MyExampleSerializer
renderer_classes = [XLSXRenderer]
filename = 'my_export.xlsx'
## CSV ## CSV
Comma-separated values are a plain-text tabular data format, that can be easily imported into spreadsheet applications. [Mjumbe Poe][mjumbewu] maintains the [djangorestframework-csv][djangorestframework-csv] package which provides CSV renderer support for REST framework. Comma-separated values are a plain-text tabular data format, that can be easily imported into spreadsheet applications. [Mjumbe Poe][mjumbewu] maintains the [djangorestframework-csv][djangorestframework-csv] package which provides CSV renderer support for REST framework.
## UltraJSON ## UltraJSON
[UltraJSON][ultrajson] is an optimized C JSON encoder which can give significantly faster JSON rendering. [Jacob Haslehurst][hzy] maintains the [drf-ujson-renderer][drf-ujson-renderer] package which implements JSON rendering using the UJSON package. [UltraJSON][ultrajson] is an optimized C JSON encoder which can give significantly faster JSON rendering. [Adam Mertz][Amertz08] maintains [drf_ujson2][drf_ujson2], a fork of the now unmaintained [drf-ujson-renderer][drf-ujson-renderer], which implements JSON rendering using the UJSON package.
## CamelCase JSON ## CamelCase JSON
@ -475,28 +525,31 @@ Comma-separated values are a plain-text tabular data format, that can be easily
## LaTeX ## LaTeX
[Rest Framework Latex] provides a renderer that outputs PDFs using Laulatex. It is maintained by [Pebble (S/F Software)][mypebble]. [Rest Framework Latex] provides a renderer that outputs PDFs using Lualatex. It is maintained by [Pebble (S/F Software)][mypebble].
[cite]: https://docs.djangoproject.com/en/stable/stable/template-response/#the-rendering-process [cite]: https://docs.djangoproject.com/en/stable/ref/template-response/#the-rendering-process
[conneg]: content-negotiation.md [conneg]: content-negotiation.md
[html-and-forms]: ../topics/html-and-forms.md [html-and-forms]: ../topics/html-and-forms.md
[browser-accept-headers]: http://www.gethifi.com/blog/browser-rest-http-accept-headers [browser-accept-headers]: http://www.gethifi.com/blog/browser-rest-http-accept-headers
[testing]: testing.md [testing]: testing.md
[HATEOAS]: http://timelessrepo.com/haters-gonna-hateoas [HATEOAS]: http://timelessrepo.com/haters-gonna-hateoas
[quote]: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven [quote]: https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
[application/vnd.github+json]: https://developer.github.com/v3/media/ [application/vnd.github+json]: https://developer.github.com/v3/media/
[application/vnd.collection+json]: http://www.amundsen.com/media-types/collection/ [application/vnd.collection+json]: http://www.amundsen.com/media-types/collection/
[django-error-views]: https://docs.djangoproject.com/en/stable/topics/http/views/#customizing-error-views [django-error-views]: https://docs.djangoproject.com/en/stable/topics/http/views/#customizing-error-views
[rest-framework-jsonp]: https://jpadilla.github.io/django-rest-framework-jsonp/ [rest-framework-jsonp]: https://jpadilla.github.io/django-rest-framework-jsonp/
[cors]: https://www.w3.org/TR/cors/ [cors]: https://www.w3.org/TR/cors/
[cors-docs]: http://www.django-rest-framework.org/topics/ajax-csrf-cors/ [cors-docs]: https://www.django-rest-framework.org/topics/ajax-csrf-cors/
[jsonp-security]: https://stackoverflow.com/questions/613962/is-jsonp-safe-to-use [jsonp-security]: https://stackoverflow.com/questions/613962/is-jsonp-safe-to-use
[rest-framework-yaml]: https://jpadilla.github.io/django-rest-framework-yaml/ [rest-framework-yaml]: https://jpadilla.github.io/django-rest-framework-yaml/
[rest-framework-xml]: https://jpadilla.github.io/django-rest-framework-xml/ [rest-framework-xml]: https://jpadilla.github.io/django-rest-framework-xml/
[messagepack]: https://msgpack.org/ [messagepack]: https://msgpack.org/
[juanriaza]: https://github.com/juanriaza [juanriaza]: https://github.com/juanriaza
[mjumbewu]: https://github.com/mjumbewu [mjumbewu]: https://github.com/mjumbewu
[flipperpa]: https://github.com/flipperpa
[wharton]: https://github.com/wharton
[drf-excel]: https://github.com/wharton/drf-excel
[vbabiy]: https://github.com/vbabiy [vbabiy]: https://github.com/vbabiy
[rest-framework-yaml]: https://jpadilla.github.io/django-rest-framework-yaml/ [rest-framework-yaml]: https://jpadilla.github.io/django-rest-framework-yaml/
[rest-framework-xml]: https://jpadilla.github.io/django-rest-framework-xml/ [rest-framework-xml]: https://jpadilla.github.io/django-rest-framework-xml/
@ -504,8 +557,9 @@ Comma-separated values are a plain-text tabular data format, that can be easily
[djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack [djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack
[djangorestframework-csv]: https://github.com/mjumbewu/django-rest-framework-csv [djangorestframework-csv]: https://github.com/mjumbewu/django-rest-framework-csv
[ultrajson]: https://github.com/esnme/ultrajson [ultrajson]: https://github.com/esnme/ultrajson
[hzy]: https://github.com/hzy [Amertz08]: https://github.com/Amertz08
[drf-ujson-renderer]: https://github.com/gizmag/drf-ujson-renderer [drf-ujson-renderer]: https://github.com/gizmag/drf-ujson-renderer
[drf_ujson2]: https://github.com/Amertz08/drf_ujson2
[djangorestframework-camel-case]: https://github.com/vbabiy/djangorestframework-camel-case [djangorestframework-camel-case]: https://github.com/vbabiy/djangorestframework-camel-case
[Django REST Pandas]: https://github.com/wq/django-rest-pandas [Django REST Pandas]: https://github.com/wq/django-rest-pandas
[Pandas]: https://pandas.pydata.org/ [Pandas]: https://pandas.pydata.org/

View File

@ -1,4 +1,7 @@
source: request.py ---
source:
- request.py
---
# Requests # Requests
@ -20,7 +23,7 @@ REST framework's Request objects provide flexible request parsing that allows yo
* It includes all parsed content, including *file and non-file* inputs. * 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 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. * It supports REST framework's flexible request parsing, rather than just supporting form data. For example you can handle incoming [JSON data] similarly to how you handle incoming [form data].
For more details see the [parsers documentation]. For more details see the [parsers documentation].
@ -46,11 +49,11 @@ If a client sends a request with a content-type that cannot be parsed then a `Un
# Content negotiation # Content negotiation
The request exposes some properties that allow you to determine the result of the content negotiation stage. This allows you to implement behaviour such as selecting a different serialisation schemes for different media types. The request exposes some properties that allow you to determine the result of the content negotiation stage. This allows you to implement behavior such as selecting a different serialization schemes for different media types.
## .accepted_renderer ## .accepted_renderer
The renderer instance what was selected by the content negotiation stage. The renderer instance that was selected by the content negotiation stage.
## .accepted_media_type ## .accepted_media_type
@ -90,7 +93,7 @@ You won't typically need to access this property.
--- ---
**Note:** You may see a `WrappedAttributeError` raised when calling the `.user` or `.auth` properties. These errors originate from an authenticator as a standard `AttributeError`, however it's necessary that they be re-raised as a different exception type in order to prevent them from being suppressed by the outer property access. Python will not recognize that the `AttributeError` orginates from the authenticator and will instaed assume that the request object does not have a `.user` or `.auth` property. The authenticator will need to be fixed. **Note:** You may see a `WrappedAttributeError` raised when calling the `.user` or `.auth` properties. These errors originate from an authenticator as a standard `AttributeError`, however it's necessary that they be re-raised as a different exception type in order to prevent them from being suppressed by the outer property access. Python will not recognize that the `AttributeError` originates from the authenticator and will instead assume that the request object does not have a `.user` or `.auth` property. The authenticator will need to be fixed.
--- ---
@ -133,5 +136,7 @@ Note that due to implementation reasons the `Request` class does not inherit fro
[cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion [cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion
[parsers documentation]: parsers.md [parsers documentation]: parsers.md
[JSON data]: parsers.md#jsonparser
[form data]: parsers.md#formparser
[authentication documentation]: authentication.md [authentication documentation]: authentication.md
[browser enhancements documentation]: ../topics/browser-enhancements.md [browser enhancements documentation]: ../topics/browser-enhancements.md

View File

@ -1,4 +1,7 @@
source: response.py ---
source:
- response.py
---
# Responses # Responses
@ -91,5 +94,5 @@ As with any other `TemplateResponse`, this method is called to render the serial
You won't typically need to call `.render()` yourself, as it's handled by Django's standard response cycle. You won't typically need to call `.render()` yourself, as it's handled by Django's standard response cycle.
[cite]: https://docs.djangoproject.com/en/stable/stable/template-response/ [cite]: https://docs.djangoproject.com/en/stable/ref/template-response/
[statuscodes]: status-codes.md [statuscodes]: status-codes.md

View File

@ -1,4 +1,7 @@
source: reverse.py ---
source:
- reverse.py
---
# Returning URLs # Returning URLs
@ -29,16 +32,16 @@ You should **include the request as a keyword argument** to the function, for ex
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
from rest_framework.views import APIView from rest_framework.views import APIView
from django.utils.timezone import now from django.utils.timezone import now
class APIRootView(APIView): class APIRootView(APIView):
def get(self, request): def get(self, request):
year = now().year year = now().year
data = { data = {
... ...
'year-summary-url': reverse('year-summary', args=[year], request=request) 'year-summary-url': reverse('year-summary', args=[year], request=request)
} }
return Response(data) return Response(data)
## reverse_lazy ## reverse_lazy
@ -51,5 +54,5 @@ As with the `reverse` function, you should **include the request as a keyword ar
api_root = reverse_lazy('api-root', request=request) api_root = reverse_lazy('api-root', request=request)
[cite]: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5 [cite]: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5
[reverse]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse [reverse]: https://docs.djangoproject.com/en/stable/ref/urlresolvers/#reverse
[reverse-lazy]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse-lazy [reverse-lazy]: https://docs.djangoproject.com/en/stable/ref/urlresolvers/#reverse-lazy

View File

@ -1,4 +1,7 @@
source: routers.py ---
source:
- routers.py
---
# Routers # Routers
@ -28,7 +31,7 @@ There are two mandatory arguments to the `register()` method:
Optionally, you may also specify an additional argument: Optionally, you may also specify an additional argument:
* `base_name` - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the `queryset` attribute of the viewset, if it has one. Note that if the viewset does not include a `queryset` attribute then you must set `base_name` when registering the viewset. * `basename` - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the `queryset` attribute of the viewset, if it has one. Note that if the viewset does not include a `queryset` attribute then you must set `basename` when registering the viewset.
The example above would generate the following URL patterns: The example above would generate the following URL patterns:
@ -39,13 +42,13 @@ The example above would generate the following URL patterns:
--- ---
**Note**: The `base_name` argument is used to specify the initial part of the view name pattern. In the example above, that's the `user` or `account` part. **Note**: The `basename` argument is used to specify the initial part of the view name pattern. In the example above, that's the `user` or `account` part.
Typically you won't *need* to specify the `base_name` argument, but if you have a viewset where you've defined a custom `get_queryset` method, then the viewset may not have a `.queryset` attribute set. If you try to register that viewset you'll see an error like this: Typically you won't *need* to specify the `basename` argument, but if you have a viewset where you've defined a custom `get_queryset` method, then the viewset may not have a `.queryset` attribute set. If you try to register that viewset you'll see an error like this:
'base_name' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute. 'basename' argument not specified, and could not automatically determine the name from the viewset, as it does not have a '.queryset' attribute.
This means you'll need to explicitly set the `base_name` argument when registering the viewset, as it could not be automatically determined from the model name. This means you'll need to explicitly set the `basename` argument when registering the viewset, as it could not be automatically determined from the model name.
--- ---
@ -53,37 +56,37 @@ This means you'll need to explicitly set the `base_name` argument when registeri
The `.urls` attribute on a router instance is simply a standard list of URL patterns. There are a number of different styles for how you can include these URLs. The `.urls` attribute on a router instance is simply a standard list of URL patterns. There are a number of different styles for how you can include these URLs.
For example, you can append `router.urls` to a list of existing views For example, you can append `router.urls` to a list of existing views...
router = routers.SimpleRouter() router = routers.SimpleRouter()
router.register(r'users', UserViewSet) router.register(r'users', UserViewSet)
router.register(r'accounts', AccountViewSet) router.register(r'accounts', AccountViewSet)
urlpatterns = [ urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), path('forgot-password/', ForgotPasswordFormView.as_view()),
] ]
urlpatterns += router.urls urlpatterns += router.urls
Alternatively you can use Django's `include` function, like so Alternatively you can use Django's `include` function, like so...
urlpatterns = [ urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), path('forgot-password', ForgotPasswordFormView.as_view()),
url(r'^', include(router.urls)), path('', include(router.urls)),
] ]
You may use `include` with an application namespace: You may use `include` with an application namespace:
urlpatterns = [ urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), path('forgot-password/', ForgotPasswordFormView.as_view()),
url(r'^api/', include((router.urls, 'app_name'))), path('api/', include((router.urls, 'app_name'))),
] ]
Or both an application and instance namespace: Or both an application and instance namespace:
urlpatterns = [ urlpatterns = [
url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), path('forgot-password/', ForgotPasswordFormView.as_view()),
url(r'^api/', include((router.urls, 'app_name'), namespace='instance_name')), path('api/', include((router.urls, 'app_name'), namespace='instance_name')),
] ]
See Django's [URL namespaces docs][url-namespace-docs] and the [`include` API reference][include-api-reference] for more details. See Django's [URL namespaces docs][url-namespace-docs] and the [`include` API reference][include-api-reference] for more details.
@ -139,6 +142,24 @@ The above example would now generate the following URL pattern:
* URL path: `^users/{pk}/change-password/$` * URL path: `^users/{pk}/change-password/$`
* URL name: `'user-change_password'` * URL name: `'user-change_password'`
### Using Django `path()` with routers
By default, the URLs created by routers use regular expressions. This behavior can be modified by setting the `use_regex_path` argument to `False` when instantiating the router, in this case [path converters][path-converters-topic-reference] are used. For example:
router = SimpleRouter(use_regex_path=False)
The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the `lookup_value_regex` attribute on the viewset or `lookup_value_converter` if using path converters. For example, you can limit the lookup to valid UUIDs:
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_id'
lookup_value_regex = '[0-9a-f]{32}'
class MyPathModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_uuid'
lookup_value_converter = 'uuid'
Note that path converters will be used on all URLs registered in the router, including viewset actions.
# API Guide # API Guide
## SimpleRouter ## SimpleRouter
@ -157,19 +178,13 @@ This router includes routes for the standard set of `list`, `create`, `retrieve`
<tr><td>{prefix}/{lookup}/{url_path}/</td><td>GET, or as specified by `methods` argument</td><td>`@action(detail=True)` decorated method</td><td>{basename}-{url_name}</td></tr> <tr><td>{prefix}/{lookup}/{url_path}/</td><td>GET, or as specified by `methods` argument</td><td>`@action(detail=True)` decorated method</td><td>{basename}-{url_name}</td></tr>
</table> </table>
By default the URLs created by `SimpleRouter` are appended with a trailing slash. By default, the URLs created by `SimpleRouter` are appended with a trailing slash.
This behavior can be modified by setting the `trailing_slash` argument to `False` when instantiating the router. For example: This behavior can be modified by setting the `trailing_slash` argument to `False` when instantiating the router. For example:
router = SimpleRouter(trailing_slash=False) router = SimpleRouter(trailing_slash=False)
Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style. Trailing slashes are conventional in Django, but are not used by default in some other frameworks such as Rails. Which style you choose to use is largely a matter of preference, although some javascript frameworks may expect a particular routing style.
The router will match lookup values containing any characters except slashes and period characters. For a more restrictive (or lenient) lookup pattern, set the `lookup_value_regex` attribute on the viewset. For example, you can limit the lookup to valid UUIDs:
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'my_model_id'
lookup_value_regex = '[0-9a-f]{32}'
## DefaultRouter ## DefaultRouter
This router is similar to `SimpleRouter` as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional `.json` style format suffixes. This router is similar to `SimpleRouter` as above, but additionally includes a default API root view, that returns a response containing hyperlinks to all the list views. It also generates routes for optional `.json` style format suffixes.
@ -241,12 +256,14 @@ The following example will only route to the `list` and `retrieve` actions, and
url=r'^{prefix}$', url=r'^{prefix}$',
mapping={'get': 'list'}, mapping={'get': 'list'},
name='{basename}-list', name='{basename}-list',
detail=False,
initkwargs={'suffix': 'List'} initkwargs={'suffix': 'List'}
), ),
Route( Route(
url=r'^{prefix}/{lookup}$', url=r'^{prefix}/{lookup}$',
mapping={'get': 'retrieve'}, mapping={'get': 'retrieve'},
name='{basename}-detail', name='{basename}-detail',
detail=True,
initkwargs={'suffix': 'Detail'} initkwargs={'suffix': 'Detail'}
), ),
DynamicRoute( DynamicRoute(
@ -291,7 +308,7 @@ The following mappings would be generated...
<tr><th>URL</th><th>HTTP Method</th><th>Action</th><th>URL Name</th></tr> <tr><th>URL</th><th>HTTP Method</th><th>Action</th><th>URL Name</th></tr>
<tr><td>/users</td><td>GET</td><td>list</td><td>user-list</td></tr> <tr><td>/users</td><td>GET</td><td>list</td><td>user-list</td></tr>
<tr><td>/users/{username}</td><td>GET</td><td>retrieve</td><td>user-detail</td></tr> <tr><td>/users/{username}</td><td>GET</td><td>retrieve</td><td>user-detail</td></tr>
<tr><td>/users/{username}/group-names</td><td>GET</td><td>group_names</td><td>user-group-names</td></tr> <tr><td>/users/{username}/group_names</td><td>GET</td><td>group_names</td><td>user-group-names</td></tr>
</table> </table>
For another example of setting the `.routes` attribute, see the source code for the `SimpleRouter` class. For another example of setting the `.routes` attribute, see the source code for the `SimpleRouter` class.
@ -300,7 +317,7 @@ For another example of setting the `.routes` attribute, see the source code for
If you want to provide totally custom behavior, you can override `BaseRouter` and override the `get_urls(self)` method. The method should inspect 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. If you want to provide totally custom behavior, you can override `BaseRouter` and override the `get_urls(self)` method. The method should inspect 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.
You may also want to override the `get_default_base_name(self, viewset)` method, or else always explicitly set the `base_name` argument when registering your viewsets with the router. You may also want to override the `get_default_basename(self, viewset)` method, or else always explicitly set the `basename` argument when registering your viewsets with the router.
# Third Party Packages # Third Party Packages
@ -323,7 +340,7 @@ The [wq.db package][wq.db] provides an advanced [ModelRouter][wq.db-router] clas
The [`DRF-extensions` package][drf-extensions] provides [routers][drf-extensions-routers] for creating [nested viewsets][drf-extensions-nested-viewsets], [collection level controllers][drf-extensions-collection-level-controllers] with [customizable endpoint names][drf-extensions-customizable-endpoint-names]. The [`DRF-extensions` package][drf-extensions] provides [routers][drf-extensions-routers] for creating [nested viewsets][drf-extensions-nested-viewsets], [collection level controllers][drf-extensions-collection-level-controllers] with [customizable endpoint names][drf-extensions-customizable-endpoint-names].
[cite]: http://guides.rubyonrails.org/routing.html [cite]: https://guides.rubyonrails.org/routing.html
[route-decorators]: viewsets.md#marking-extra-actions-for-routing [route-decorators]: viewsets.md#marking-extra-actions-for-routing
[drf-nested-routers]: https://github.com/alanjds/drf-nested-routers [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers
[wq.db]: https://wq.io/wq.db [wq.db]: https://wq.io/wq.db
@ -333,5 +350,6 @@ The [`DRF-extensions` package][drf-extensions] provides [routers][drf-extensions
[drf-extensions-nested-viewsets]: https://chibisov.github.io/drf-extensions/docs/#nested-routes [drf-extensions-nested-viewsets]: https://chibisov.github.io/drf-extensions/docs/#nested-routes
[drf-extensions-collection-level-controllers]: https://chibisov.github.io/drf-extensions/docs/#collection-level-controllers [drf-extensions-collection-level-controllers]: https://chibisov.github.io/drf-extensions/docs/#collection-level-controllers
[drf-extensions-customizable-endpoint-names]: https://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name [drf-extensions-customizable-endpoint-names]: https://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name
[url-namespace-docs]: https://docs.djangoproject.com/en/1.11/topics/http/urls/#url-namespaces [url-namespace-docs]: https://docs.djangoproject.com/en/stable/topics/http/urls/#url-namespaces
[include-api-reference]: https://docs.djangoproject.com/en/2.0/ref/urls/#include [include-api-reference]: https://docs.djangoproject.com/en/stable/ref/urls/#include
[path-converters-topic-reference]: https://docs.djangoproject.com/en/stable/topics/http/urls/#path-converters

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,7 @@
source: serializers.py ---
source:
- serializers.py
---
# Serializers # Serializers
@ -18,7 +21,7 @@ Let's start by creating a simple object we can use for example purposes:
from datetime import datetime from datetime import datetime
class Comment(object): class Comment:
def __init__(self, email, content, created=None): def __init__(self, email, content, created=None):
self.email = email self.email = email
self.content = content self.content = content
@ -57,10 +60,10 @@ At this point we've translated the model instance into Python native datatypes.
Deserialization is similar. First we parse a stream into Python native datatypes... Deserialization is similar. First we parse a stream into Python native datatypes...
from django.utils.six import BytesIO import io
from rest_framework.parsers import JSONParser from rest_framework.parsers import JSONParser
stream = BytesIO(json) stream = io.BytesIO(json)
data = JSONParser().parse(stream) data = JSONParser().parse(stream)
...then we restore those native datatypes into a dictionary of validated data. ...then we restore those native datatypes into a dictionary of validated data.
@ -113,7 +116,7 @@ Calling `.save()` will either create a new instance, or update an existing insta
# .save() will update the existing `comment` instance. # .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data) serializer = CommentSerializer(comment, data=data)
Both the `.create()` and `.update()` methods are optional. You can implement either neither, one, or both of them, depending on the use-case for your serializer class. Both the `.create()` and `.update()` methods are optional. You can implement either none, one, or both of them, depending on the use-case for your serializer class.
#### Passing additional attributes to `.save()` #### Passing additional attributes to `.save()`
@ -152,13 +155,13 @@ When deserializing data, you always need to call `is_valid()` before attempting
serializer.is_valid() serializer.is_valid()
# False # False
serializer.errors serializer.errors
# {'email': [u'Enter a valid e-mail address.'], 'created': [u'This field is required.']} # {'email': ['Enter a valid e-mail address.'], 'created': ['This field is required.']}
Each key in the dictionary will be the field name, and the values will be lists of strings of any error messages corresponding to that field. The `non_field_errors` key may also be present, and will list any general validation errors. The name of the `non_field_errors` key may be customized using the `NON_FIELD_ERRORS_KEY` REST framework setting. Each key in the dictionary will be the field name, and the values will be lists of strings of any error messages corresponding to that field. The `non_field_errors` key may also be present, and will list any general validation errors. The name of the `non_field_errors` key may be customized using the `NON_FIELD_ERRORS_KEY` REST framework setting.
When deserializing a list of items, errors will be returned as a list of dictionaries representing each of the deserialized items. When deserializing a list of items, errors will be returned as a list of dictionaries representing each of the deserialized items.
#### Raising an exception on invalid data #### Raising an exception on invalid data
The `.is_valid()` method takes an optional `raise_exception` flag that will cause it to raise a `serializers.ValidationError` exception if there are validation errors. The `.is_valid()` method takes an optional `raise_exception` flag that will cause it to raise a `serializers.ValidationError` exception if there are validation errors.
@ -208,7 +211,7 @@ To do any other validation that requires access to multiple fields, add a method
def validate(self, data): def validate(self, data):
""" """
Check that the start is before the stop. Check that start is before finish.
""" """
if data['start'] > data['finish']: if data['start'] > data['finish']:
raise serializers.ValidationError("finish must occur after start") raise serializers.ValidationError("finish must occur after start")
@ -223,22 +226,24 @@ Individual fields on a serializer can include validators, by declaring them on t
raise serializers.ValidationError('Not a multiple of ten') raise serializers.ValidationError('Not a multiple of ten')
class GameRecord(serializers.Serializer): class GameRecord(serializers.Serializer):
score = IntegerField(validators=[multiple_of_ten]) score = serializers.IntegerField(validators=[multiple_of_ten])
... ...
Serializer classes can also include reusable validators that are applied to the complete set of field data. These validators are included by declaring them on an inner `Meta` class, like so: Serializer classes can also include reusable validators that are applied to the complete set of field data. These validators are included by declaring them on an inner `Meta` class, like so:
class EventSerializer(serializers.Serializer): class EventSerializer(serializers.Serializer):
name = serializers.CharField() name = serializers.CharField()
room_number = serializers.IntegerField(choices=[101, 102, 103, 201]) room_number = serializers.ChoiceField(choices=[101, 102, 103, 201])
date = serializers.DateField() date = serializers.DateField()
class Meta: class Meta:
# Each room only has one event per day. # Each room only has one event per day.
validators = UniqueTogetherValidator( validators = [
queryset=Event.objects.all(), UniqueTogetherValidator(
fields=['room_number', 'date'] queryset=Event.objects.all(),
) fields=['room_number', 'date']
)
]
For more information see the [validators documentation](validators.md). For more information see the [validators documentation](validators.md).
@ -246,14 +251,14 @@ For more information see the [validators documentation](validators.md).
When passing an initial object or queryset to a serializer instance, the object will be made available as `.instance`. If no initial object is passed then the `.instance` attribute will be `None`. When passing an initial object or queryset to a serializer instance, the object will be made available as `.instance`. If no initial object is passed then the `.instance` attribute will be `None`.
When passing data to a serializer instance, the unmodified data will be made available as `.initial_data`. If the data keyword argument is not passed then the `.initial_data` attribute will not exist. When passing data to a serializer instance, the unmodified data will be made available as `.initial_data`. If the `data` keyword argument is not passed then the `.initial_data` attribute will not exist.
## Partial updates ## Partial updates
By default, serializers must be passed values for all required fields or they will raise validation errors. You can use the `partial` argument in order to allow partial updates. By default, serializers must be passed values for all required fields or they will raise validation errors. You can use the `partial` argument in order to allow partial updates.
# Update `comment` with partial data # Update `comment` with partial data
serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True) serializer = CommentSerializer(comment, data={'content': 'foo bar'}, partial=True)
## Dealing with nested objects ## Dealing with nested objects
@ -277,7 +282,7 @@ If a nested representation may optionally accept the `None` value you should pas
content = serializers.CharField(max_length=200) content = serializers.CharField(max_length=200)
created = serializers.DateTimeField() created = serializers.DateTimeField()
Similarly if a nested representation should be a list of items, you should pass the `many=True` flag to the nested serialized. Similarly if a nested representation should be a list of items, you should pass the `many=True` flag to the nested serializer.
class CommentSerializer(serializers.Serializer): class CommentSerializer(serializers.Serializer):
user = UserSerializer(required=False) user = UserSerializer(required=False)
@ -293,7 +298,7 @@ When dealing with nested representations that support deserializing the data, an
serializer.is_valid() serializer.is_valid()
# False # False
serializer.errors serializer.errors
# {'user': {'email': [u'Enter a valid e-mail address.']}, 'created': [u'This field is required.']} # {'user': {'email': ['Enter a valid e-mail address.']}, 'created': ['This field is required.']}
Similarly, the `.validated_data` property will include nested data structures. Similarly, the `.validated_data` property will include nested data structures.
@ -308,7 +313,7 @@ The following example demonstrates how you might handle creating a user with a n
class Meta: class Meta:
model = User model = User
fields = ('username', 'email', 'profile') fields = ['username', 'email', 'profile']
def create(self, validated_data): def create(self, validated_data):
profile_data = validated_data.pop('profile') profile_data = validated_data.pop('profile')
@ -330,7 +335,7 @@ Here's an example for an `.update()` method on our previous `UserSerializer` cla
def update(self, instance, validated_data): def update(self, instance, validated_data):
profile_data = validated_data.pop('profile') profile_data = validated_data.pop('profile')
# Unless the application properly enforces that this field is # Unless the application properly enforces that this field is
# always set, the follow could raise a `DoesNotExist`, which # always set, the following could raise a `DoesNotExist`, which
# would need to be handled. # would need to be handled.
profile = instance.profile profile = instance.profile
@ -379,8 +384,8 @@ This manager class now more nicely encapsulates that user instances and profile
def create(self, validated_data): def create(self, validated_data):
return User.objects.create( return User.objects.create(
username=validated_data['username'], username=validated_data['username'],
email=validated_data['email'] email=validated_data['email'],
is_premium_member=validated_data['profile']['is_premium_member'] is_premium_member=validated_data['profile']['is_premium_member'],
has_support_contract=validated_data['profile']['has_support_contract'] has_support_contract=validated_data['profile']['has_support_contract']
) )
@ -415,7 +420,7 @@ You can provide arbitrary additional context by passing a `context` argument whe
serializer = AccountSerializer(account, context={'request': request}) serializer = AccountSerializer(account, context={'request': request})
serializer.data serializer.data
# {'id': 6, 'owner': u'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'} # {'id': 6, 'owner': 'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'}
The context dictionary can be used within any serializer field logic, such as a custom `.to_representation()` method, by accessing the `self.context` attribute. The context dictionary can be used within any serializer field logic, such as a custom `.to_representation()` method, by accessing the `self.context` attribute.
@ -438,7 +443,7 @@ Declaring a `ModelSerializer` looks like this:
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Account model = Account
fields = ('id', 'account_name', 'users', 'created') fields = ['id', 'account_name', 'users', 'created']
By default, all the model fields on the class will be mapped to a corresponding serializer fields. By default, all the model fields on the class will be mapped to a corresponding serializer fields.
@ -467,7 +472,7 @@ For example:
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Account model = Account
fields = ('id', 'account_name', 'users', 'created') fields = ['id', 'account_name', 'users', 'created']
You can also set the `fields` attribute to the special value `'__all__'` to indicate that all fields in the model should be used. You can also set the `fields` attribute to the special value `'__all__'` to indicate that all fields in the model should be used.
@ -485,7 +490,7 @@ For example:
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Account model = Account
exclude = ('users',) exclude = ['users']
In the example above, if the `Account` model had 3 fields `account_name`, `users`, and `created`, this will result in the fields `account_name` and `created` to be serialized. In the example above, if the `Account` model had 3 fields `account_name`, `users`, and `created`, this will result in the fields `account_name` and `created` to be serialized.
@ -502,7 +507,7 @@ The default `ModelSerializer` uses primary keys for relationships, but you can a
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Account model = Account
fields = ('id', 'account_name', 'users', 'created') fields = ['id', 'account_name', 'users', 'created']
depth = 1 depth = 1
The `depth` option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation. The `depth` option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation.
@ -519,6 +524,7 @@ You can add extra fields to a `ModelSerializer` or override the default fields b
class Meta: class Meta:
model = Account model = Account
fields = ['url', 'groups']
Extra fields can correspond to any property or callable on the model. Extra fields can correspond to any property or callable on the model.
@ -531,8 +537,8 @@ This option should be a list or tuple of field names, and is declared as follows
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Account model = Account
fields = ('id', 'account_name', 'users', 'created') fields = ['id', 'account_name', 'users', 'created']
read_only_fields = ('account_name',) read_only_fields = ['account_name']
Model fields which have `editable=False` set, and `AutoField` fields will be set to read-only by default, and do not need to be added to the `read_only_fields` option. Model fields which have `editable=False` set, and `AutoField` fields will be set to read-only by default, and do not need to be added to the `read_only_fields` option.
@ -560,7 +566,7 @@ This option is a dictionary, mapping field names to a dictionary of keyword argu
class CreateUserSerializer(serializers.ModelSerializer): class CreateUserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ('email', 'username', 'password') fields = ['email', 'username', 'password']
extra_kwargs = {'password': {'write_only': True}} extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data): def create(self, validated_data):
@ -572,6 +578,8 @@ This option is a dictionary, mapping field names to a dictionary of keyword argu
user.save() user.save()
return user return user
Please keep in mind that, if the field has already been explicitly declared on the serializer class, then the `extra_kwargs` option will be ignored.
## Relational fields ## Relational fields
When serializing model instances, there are a number of different ways you might choose to represent relationships. The default representation for `ModelSerializer` is to use the primary keys of the related instances. When serializing model instances, there are a number of different ways you might choose to represent relationships. The default representation for `ModelSerializer` is to use the primary keys of the related instances.
@ -586,15 +594,15 @@ The ModelSerializer class also exposes an API that you can override in order to
Normally if a `ModelSerializer` does not generate the fields you need by default then you should either add them to the class explicitly, or simply use a regular `Serializer` class instead. However in some cases you may want to create a new base class that defines how the serializer fields are created for any given model. Normally if a `ModelSerializer` does not generate the fields you need by default then you should either add them to the class explicitly, or simply use a regular `Serializer` class instead. However in some cases you may want to create a new base class that defines how the serializer fields are created for any given model.
### `.serializer_field_mapping` ### `serializer_field_mapping`
A mapping of Django model classes to REST framework serializer classes. You can override this mapping to alter the default serializer classes that should be used for each model class. A mapping of Django model fields to REST framework serializer fields. You can override this mapping to alter the default serializer fields that should be used for each model field.
### `.serializer_related_field` ### `serializer_related_field`
This property should be the serializer field class, that is used for relational fields by default. This property should be the serializer field class, that is used for relational fields by default.
For `ModelSerializer` this defaults to `PrimaryKeyRelatedField`. For `ModelSerializer` this defaults to `serializers.PrimaryKeyRelatedField`.
For `HyperlinkedModelSerializer` this defaults to `serializers.HyperlinkedRelatedField`. For `HyperlinkedModelSerializer` this defaults to `serializers.HyperlinkedRelatedField`.
@ -614,21 +622,21 @@ Defaults to `serializers.ChoiceField`
The following methods are called to determine the class and keyword arguments for each field that should be automatically included on the serializer. Each of these methods should return a two tuple of `(field_class, field_kwargs)`. The following methods are called to determine the class and keyword arguments for each field that should be automatically included on the serializer. Each of these methods should return a two tuple of `(field_class, field_kwargs)`.
### `.build_standard_field(self, field_name, model_field)` ### `build_standard_field(self, field_name, model_field)`
Called to generate a serializer field that maps to a standard model field. Called to generate a serializer field that maps to a standard model field.
The default implementation returns a serializer class based on the `serializer_field_mapping` attribute. The default implementation returns a serializer class based on the `serializer_field_mapping` attribute.
### `.build_relational_field(self, field_name, relation_info)` ### `build_relational_field(self, field_name, relation_info)`
Called to generate a serializer field that maps to a relational model field. Called to generate a serializer field that maps to a relational model field.
The default implementation returns a serializer class based on the `serializer_relational_field` attribute. The default implementation returns a serializer class based on the `serializer_related_field` attribute.
The `relation_info` argument is a named tuple, that contains `model_field`, `related_model`, `to_many` and `has_through_model` properties. The `relation_info` argument is a named tuple, that contains `model_field`, `related_model`, `to_many` and `has_through_model` properties.
### `.build_nested_field(self, field_name, relation_info, nested_depth)` ### `build_nested_field(self, field_name, relation_info, nested_depth)`
Called to generate a serializer field that maps to a relational model field, when the `depth` option has been set. Called to generate a serializer field that maps to a relational model field, when the `depth` option has been set.
@ -638,17 +646,17 @@ The `nested_depth` will be the value of the `depth` option, minus one.
The `relation_info` argument is a named tuple, that contains `model_field`, `related_model`, `to_many` and `has_through_model` properties. The `relation_info` argument is a named tuple, that contains `model_field`, `related_model`, `to_many` and `has_through_model` properties.
### `.build_property_field(self, field_name, model_class)` ### `build_property_field(self, field_name, model_class)`
Called to generate a serializer field that maps to a property or zero-argument method on the model class. Called to generate a serializer field that maps to a property or zero-argument method on the model class.
The default implementation returns a `ReadOnlyField` class. The default implementation returns a `ReadOnlyField` class.
### `.build_url_field(self, field_name, model_class)` ### `build_url_field(self, field_name, model_class)`
Called to generate a serializer field for the serializer's own `url` field. The default implementation returns a `HyperlinkedIdentityField` class. Called to generate a serializer field for the serializer's own `url` field. The default implementation returns a `HyperlinkedIdentityField` class.
### `.build_unknown_field(self, field_name, model_class)` ### `build_unknown_field(self, field_name, model_class)`
Called when the field name did not map to any model field or model property. Called when the field name did not map to any model field or model property.
The default implementation raises an error, although subclasses may customize this behavior. The default implementation raises an error, although subclasses may customize this behavior.
@ -668,7 +676,7 @@ You can explicitly include the primary key by adding it to the `fields` option,
class AccountSerializer(serializers.HyperlinkedModelSerializer): class AccountSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
model = Account model = Account
fields = ('url', 'id', 'account_name', 'users', 'created') fields = ['url', 'id', 'account_name', 'users', 'created']
## Absolute and relative URLs ## Absolute and relative URLs
@ -700,7 +708,7 @@ You can override a URL field view name and lookup field by using either, or both
class AccountSerializer(serializers.HyperlinkedModelSerializer): class AccountSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
model = Account model = Account
fields = ('account_url', 'account_name', 'users', 'created') fields = ['account_url', 'account_name', 'users', 'created']
extra_kwargs = { extra_kwargs = {
'url': {'view_name': 'accounts', 'lookup_field': 'account_name'}, 'url': {'view_name': 'accounts', 'lookup_field': 'account_name'},
'users': {'lookup_field': 'username'} 'users': {'lookup_field': 'username'}
@ -722,7 +730,7 @@ Alternatively you can set the fields on the serializer explicitly. For example:
class Meta: class Meta:
model = Account model = Account
fields = ('url', 'account_name', 'users', 'created') fields = ['url', 'account_name', 'users', 'created']
--- ---
@ -748,6 +756,14 @@ The following argument can also be passed to a `ListSerializer` field or a seria
This is `True` by default, but can be set to `False` if you want to disallow empty lists as valid input. This is `True` by default, but can be set to `False` if you want to disallow empty lists as valid input.
### `max_length`
This is `None` by default, but can be set to a positive integer if you want to validate that the list contains no more than this number of elements.
### `min_length`
This is `None` by default, but can be set to a positive integer if you want to validate that the list contains no fewer than this number of elements.
### Customizing `ListSerializer` behavior ### Customizing `ListSerializer` behavior
There *are* a few use cases when you might want to customize the `ListSerializer` behavior. For example: There *are* a few use cases when you might want to customize the `ListSerializer` behavior. For example:
@ -829,8 +845,6 @@ Here's an example of how you might choose to implement multiple updates:
class Meta: class Meta:
list_serializer_class = BookListSerializer list_serializer_class = BookListSerializer
It is possible that a third party package may be included alongside the 3.1 release that provides some automatic support for multiple update operations, similar to the `allow_add_remove` behavior that was present in REST framework 2.
#### Customizing ListSerializer initialization #### Customizing ListSerializer initialization
When a serializer with `many=True` is instantiated, we need to determine which arguments and keyword arguments should be passed to the `.__init__()` method for both the child `Serializer` class, and for the parent `ListSerializer` class. When a serializer with `many=True` is instantiated, we need to determine which arguments and keyword arguments should be passed to the `.__init__()` method for both the child `Serializer` class, and for the parent `ListSerializer` class.
@ -870,7 +884,7 @@ Because this class provides the same interface as the `Serializer` class, you ca
The only difference you'll notice when doing so is the `BaseSerializer` classes will not generate HTML forms in the browsable API. This is because the data they return does not include all the field information that would allow each field to be rendered into a suitable HTML input. The only difference you'll notice when doing so is the `BaseSerializer` classes will not generate HTML forms in the browsable API. This is because the data they return does not include all the field information that would allow each field to be rendered into a suitable HTML input.
##### Read-only `BaseSerializer` classes #### Read-only `BaseSerializer` classes
To implement a read-only serializer using the `BaseSerializer` class, we just need to override the `.to_representation()` method. Let's take a look at an example using a simple Django model: To implement a read-only serializer using the `BaseSerializer` class, we just need to override the `.to_representation()` method. Let's take a look at an example using a simple Django model:
@ -882,10 +896,10 @@ To implement a read-only serializer using the `BaseSerializer` class, we just ne
It's simple to create a read-only serializer for converting `HighScore` instances into primitive data types. It's simple to create a read-only serializer for converting `HighScore` instances into primitive data types.
class HighScoreSerializer(serializers.BaseSerializer): class HighScoreSerializer(serializers.BaseSerializer):
def to_representation(self, obj): def to_representation(self, instance):
return { return {
'score': obj.score, 'score': instance.score,
'player_name': obj.player_name 'player_name': instance.player_name
} }
We can now use this class to serialize single `HighScore` instances: We can now use this class to serialize single `HighScore` instances:
@ -894,7 +908,7 @@ We can now use this class to serialize single `HighScore` instances:
def high_score(request, pk): def high_score(request, pk):
instance = HighScore.objects.get(pk=pk) instance = HighScore.objects.get(pk=pk)
serializer = HighScoreSerializer(instance) serializer = HighScoreSerializer(instance)
return Response(serializer.data) return Response(serializer.data)
Or use it to serialize multiple instances: Or use it to serialize multiple instances:
@ -902,9 +916,9 @@ Or use it to serialize multiple instances:
def all_high_scores(request): def all_high_scores(request):
queryset = HighScore.objects.order_by('-score') queryset = HighScore.objects.order_by('-score')
serializer = HighScoreSerializer(queryset, many=True) serializer = HighScoreSerializer(queryset, many=True)
return Response(serializer.data) return Response(serializer.data)
##### Read-write `BaseSerializer` classes #### Read-write `BaseSerializer` classes
To create a read-write serializer we first need to implement a `.to_internal_value()` method. This method returns the validated values that will be used to construct the object instance, and may raise a `serializers.ValidationError` if the supplied data is in an incorrect format. To create a read-write serializer we first need to implement a `.to_internal_value()` method. This method returns the validated values that will be used to construct the object instance, and may raise a `serializers.ValidationError` if the supplied data is in an incorrect format.
@ -933,17 +947,17 @@ Here's a complete example of our previous `HighScoreSerializer`, that's been upd
'player_name': 'May not be more than 10 characters.' 'player_name': 'May not be more than 10 characters.'
}) })
# Return the validated values. This will be available as # Return the validated values. This will be available as
# the `.validated_data` property. # the `.validated_data` property.
return { return {
'score': int(score), 'score': int(score),
'player_name': player_name 'player_name': player_name
} }
def to_representation(self, obj): def to_representation(self, instance):
return { return {
'score': obj.score, 'score': instance.score,
'player_name': obj.player_name 'player_name': instance.player_name
} }
def create(self, validated_data): def create(self, validated_data):
@ -953,17 +967,18 @@ 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 `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 arbitrary objects into primitive representations. The following class is an example of a generic serializer that can handle coercing arbitrary complex objects into primitive representations.
class ObjectSerializer(serializers.BaseSerializer): class ObjectSerializer(serializers.BaseSerializer):
""" """
A read-only serializer that coerces arbitrary complex objects A read-only serializer that coerces arbitrary complex objects
into primitive representations. into primitive representations.
""" """
def to_representation(self, obj): def to_representation(self, instance):
for attribute_name in dir(obj): output = {}
attribute = getattr(obj, attribute_name) for attribute_name in dir(instance):
if attribute_name('_'): attribute = getattr(instance, attribute_name)
if attribute_name.startswith('_'):
# Ignore private attributes. # Ignore private attributes.
pass pass
elif hasattr(attribute, '__call__'): elif hasattr(attribute, '__call__'):
@ -986,6 +1001,7 @@ The following class is an example of a generic serializer that can handle coerci
else: else:
# Force anything else to its string representation. # Force anything else to its string representation.
output[attribute_name] = str(attribute) output[attribute_name] = str(attribute)
return output
--- ---
@ -1003,11 +1019,11 @@ Some reasons this might be useful include...
The signatures for these methods are as follows: The signatures for these methods are as follows:
#### `.to_representation(self, obj)` #### `to_representation(self, instance)`
Takes the object instance that requires serialization, and should return a primitive representation. Typically this means returning a structure of built-in Python datatypes. The exact types that can be handled will depend on the render classes you have configured for your API. Takes the object instance that requires serialization, and should return a primitive representation. Typically this means returning a structure of built-in Python datatypes. The exact types that can be handled will depend on the render classes you have configured for your API.
May be overridden in order modify the representation style. For example: May be overridden in order to modify the representation style. For example:
def to_representation(self, instance): def to_representation(self, instance):
"""Convert `username` to lowercase.""" """Convert `username` to lowercase."""
@ -1015,7 +1031,7 @@ May be overridden in order modify the representation style. For example:
ret['username'] = ret['username'].lower() ret['username'] = ret['username'].lower()
return ret return ret
#### ``.to_internal_value(self, data)`` #### ``to_internal_value(self, data)``
Takes the unvalidated incoming data as input and should return the validated data that will be made available as `serializer.validated_data`. The return value will also be passed to the `.create()` or `.update()` methods if `.save()` is called on the serializer class. Takes the unvalidated incoming data as input and should return the validated data that will be made available as `serializer.validated_data`. The return value will also be passed to the `.create()` or `.update()` methods if `.save()` is called on the serializer class.
@ -1030,7 +1046,7 @@ Similar to Django forms, you can extend and reuse serializers through inheritanc
class MyBaseSerializer(Serializer): class MyBaseSerializer(Serializer):
my_field = serializers.CharField() my_field = serializers.CharField()
def validate_my_field(self): def validate_my_field(self, value):
... ...
class MySerializer(MyBaseSerializer): class MySerializer(MyBaseSerializer):
@ -1078,7 +1094,7 @@ For example, if you wanted to be able to set which fields should be used by a se
fields = kwargs.pop('fields', None) fields = kwargs.pop('fields', None)
# Instantiate the superclass normally # Instantiate the superclass normally
super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if fields is not None: if fields is not None:
# Drop any fields that are not specified in the `fields` argument. # Drop any fields that are not specified in the `fields` argument.
@ -1092,12 +1108,12 @@ This would then allow you to do the following:
>>> class UserSerializer(DynamicFieldsModelSerializer): >>> class UserSerializer(DynamicFieldsModelSerializer):
>>> class Meta: >>> class Meta:
>>> model = User >>> model = User
>>> fields = ('id', 'username', 'email') >>> fields = ['id', 'username', 'email']
>>> >>>
>>> print UserSerializer(user) >>> print(UserSerializer(user))
{'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'} {'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'}
>>> >>>
>>> print UserSerializer(user, fields=('id', 'email')) >>> print(UserSerializer(user, fields=('id', 'email')))
{'id': 2, 'email': 'jon@example.com'} {'id': 2, 'email': 'jon@example.com'}
## Customizing the default fields ## Customizing the default fields
@ -1169,12 +1185,17 @@ The [html-json-forms][html-json-forms] package provides an algorithm and seriali
The [drf-writable-nested][drf-writable-nested] package provides writable nested model serializer which allows to create/update models with nested related data. The [drf-writable-nested][drf-writable-nested] package provides writable nested model serializer which allows to create/update models with nested related data.
## DRF Encrypt Content
The [drf-encrypt-content][drf-encrypt-content] package helps you encrypt your data, serialized through ModelSerializer. It also contains some helper functions. Which helps you to encrypt your data.
[cite]: https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion [cite]: https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion
[relations]: relations.md [relations]: relations.md
[model-managers]: https://docs.djangoproject.com/en/stable/topics/db/managers/ [model-managers]: https://docs.djangoproject.com/en/stable/topics/db/managers/
[encapsulation-blogpost]: https://www.dabapps.com/blog/django-models-and-encapsulation/ [encapsulation-blogpost]: https://www.dabapps.com/blog/django-models-and-encapsulation/
[thirdparty-writable-nested]: serializers.md#drf-writable-nested [thirdparty-writable-nested]: serializers.md#drf-writable-nested
[django-rest-marshmallow]: https://tomchristie.github.io/django-rest-marshmallow/ [django-rest-marshmallow]: https://marshmallow-code.github.io/django-rest-marshmallow/
[marshmallow]: https://marshmallow.readthedocs.io/en/latest/ [marshmallow]: https://marshmallow.readthedocs.io/en/latest/
[serpy]: https://github.com/clarkduvall/serpy [serpy]: https://github.com/clarkduvall/serpy
[mongoengine]: https://github.com/umutbozkurt/django-rest-framework-mongoengine [mongoengine]: https://github.com/umutbozkurt/django-rest-framework-mongoengine
@ -1190,3 +1211,4 @@ The [drf-writable-nested][drf-writable-nested] package provides writable nested
[drf-serializer-extensions]: https://github.com/evenicoulddoit/django-rest-framework-serializer-extensions [drf-serializer-extensions]: https://github.com/evenicoulddoit/django-rest-framework-serializer-extensions
[djangorestframework-queryfields]: https://djangorestframework-queryfields.readthedocs.io/ [djangorestframework-queryfields]: https://djangorestframework-queryfields.readthedocs.io/
[drf-writable-nested]: https://github.com/beda-software/drf-writable-nested [drf-writable-nested]: https://github.com/beda-software/drf-writable-nested
[drf-encrypt-content]: https://github.com/oguzhancelikarslan/drf-encrypt-content

View File

@ -1,4 +1,7 @@
source: settings.py ---
source:
- settings.py
---
# Settings # Settings
@ -11,12 +14,12 @@ Configuration for REST framework is all namespaced inside a single Django settin
For example your project's `settings.py` file might include something like this: For example your project's `settings.py` file might include something like this:
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( 'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.JSONRenderer',
), ],
'DEFAULT_PARSER_CLASSES': ( 'DEFAULT_PARSER_CLASSES': [
'rest_framework.parsers.JSONParser', 'rest_framework.parsers.JSONParser',
) ]
} }
## Accessing settings ## Accessing settings
@ -26,7 +29,7 @@ you should use the `api_settings` object. For example.
from rest_framework.settings import api_settings from rest_framework.settings import api_settings
print api_settings.DEFAULT_AUTHENTICATION_CLASSES print(api_settings.DEFAULT_AUTHENTICATION_CLASSES)
The `api_settings` object will check for any user-defined settings, and otherwise fall back to the default values. Any setting that uses string import paths to refer to a class will automatically import and return the referenced class, instead of the string literal. The `api_settings` object will check for any user-defined settings, and otherwise fall back to the default values. Any setting that uses string import paths to refer to a class will automatically import and return the referenced class, instead of the string literal.
@ -44,10 +47,10 @@ A list or tuple of renderer classes, that determines the default set of renderer
Default: Default:
( [
'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer', 'rest_framework.renderers.BrowsableAPIRenderer',
) ]
#### DEFAULT_PARSER_CLASSES #### DEFAULT_PARSER_CLASSES
@ -55,11 +58,11 @@ A list or tuple of parser classes, that determines the default set of parsers us
Default: Default:
( [
'rest_framework.parsers.JSONParser', 'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser', 'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser' 'rest_framework.parsers.MultiPartParser'
) ]
#### DEFAULT_AUTHENTICATION_CLASSES #### DEFAULT_AUTHENTICATION_CLASSES
@ -67,10 +70,10 @@ A list or tuple of authentication classes, that determines the default set of au
Default: Default:
( [
'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication' 'rest_framework.authentication.BasicAuthentication'
) ]
#### DEFAULT_PERMISSION_CLASSES #### DEFAULT_PERMISSION_CLASSES
@ -78,15 +81,15 @@ A list or tuple of permission classes, that determines the default set of permis
Default: Default:
( [
'rest_framework.permissions.AllowAny', 'rest_framework.permissions.AllowAny',
) ]
#### DEFAULT_THROTTLE_CLASSES #### DEFAULT_THROTTLE_CLASSES
A list or tuple of throttle classes, that determines the default set of throttles checked at the start of a view. A list or tuple of throttle classes, that determines the default set of throttles checked at the start of a view.
Default: `()` Default: `[]`
#### DEFAULT_CONTENT_NEGOTIATION_CLASS #### DEFAULT_CONTENT_NEGOTIATION_CLASS
@ -98,7 +101,7 @@ Default: `'rest_framework.negotiation.DefaultContentNegotiation'`
A view inspector class that will be used for schema generation. A view inspector class that will be used for schema generation.
Default: `'rest_framework.schemas.AutoSchema'` Default: `'rest_framework.schemas.openapi.AutoSchema'`
--- ---
@ -106,32 +109,19 @@ Default: `'rest_framework.schemas.AutoSchema'`
*The following settings control the behavior of the generic class-based views.* *The following settings control the behavior of the generic class-based views.*
#### DEFAULT_PAGINATION_SERIALIZER_CLASS
---
**This setting has been removed.**
The pagination API does not use serializers to determine the output format, and
you'll need to instead override the `get_paginated_response method on a
pagination class in order to specify how the output format is controlled.
---
#### DEFAULT_FILTER_BACKENDS #### DEFAULT_FILTER_BACKENDS
A list of filter backend classes that should be used for generic filtering. A list of filter backend classes that should be used for generic filtering.
If set to `None` then generic filtering is disabled. If set to `None` then generic filtering is disabled.
#### PAGINATE_BY #### DEFAULT_PAGINATION_CLASS
--- The default class to use for queryset pagination. If set to `None`, pagination
is disabled by default. See the pagination documentation for further guidance on
[setting](pagination.md#setting-the-pagination-style) and
[modifying](pagination.md#modifying-the-pagination-style) the pagination style.
**This setting has been removed.** Default: `None`
See the pagination documentation for further guidance on [setting the pagination style](pagination.md#modifying-the-pagination-style).
---
#### PAGE_SIZE #### PAGE_SIZE
@ -139,26 +129,6 @@ The default page size to use for pagination. If set to `None`, pagination is di
Default: `None` Default: `None`
#### PAGINATE_BY_PARAM
---
**This setting has been removed.**
See the pagination documentation for further guidance on [setting the pagination style](pagination.md#modifying-the-pagination-style).
---
#### MAX_PAGINATE_BY
---
**This setting has been removed.**
See the pagination documentation for further guidance on [setting the pagination style](pagination.md#modifying-the-pagination-style).
---
### SEARCH_PARAM ### SEARCH_PARAM
The name of a query parameter, which can be used to specify the search term used by `SearchFilter`. The name of a query parameter, which can be used to specify the search term used by `SearchFilter`.
@ -193,6 +163,12 @@ The string that should used for any versioning parameters, such as in the media
Default: `'version'` Default: `'version'`
#### DEFAULT_VERSIONING_CLASS
The default versioning scheme to use.
Default: `None`
--- ---
## Authentication settings ## Authentication settings
@ -235,10 +211,10 @@ The format of any of these renderer classes may be used when constructing a test
Default: Default:
( [
'rest_framework.renderers.MultiPartRenderer', 'rest_framework.renderers.MultiPartRenderer',
'rest_framework.renderers.JSONRenderer' 'rest_framework.renderers.JSONRenderer'
) ]
--- ---
@ -398,10 +374,15 @@ A string representing the function that should be used when generating view name
This should be a function with the following signature: This should be a function with the following signature:
view_name(cls, suffix=None) view_name(self)
* `cls`: The view class. Typically the name function would inspect the name of the class when generating a descriptive name, by accessing `cls.__name__`. * `self`: The view instance. Typically the name function would inspect the name of the class when generating a descriptive name, by accessing `self.__class__.__name__`.
* `suffix`: The optional suffix used when differentiating individual views in a viewset.
If the view instance inherits `ViewSet`, it may have been initialized with several optional arguments:
* `name`: A name explicitly provided to a view in the viewset. Typically, this value should be used as-is when provided.
* `suffix`: Text used when differentiating individual views in a viewset. This argument is mutually exclusive to `name`.
* `detail`: Boolean that differentiates an individual view in a viewset as either being a 'list' or 'detail' view.
Default: `'rest_framework.views.get_view_name'` Default: `'rest_framework.views.get_view_name'`
@ -413,11 +394,15 @@ This setting can be changed to support markup styles other than the default mark
This should be a function with the following signature: This should be a function with the following signature:
view_description(cls, html=False) view_description(self, html=False)
* `cls`: The view class. Typically the description function would inspect the docstring of the class when generating a description, by accessing `cls.__doc__` * `self`: The view instance. Typically the description function would inspect the docstring of the class when generating a description, by accessing `self.__class__.__doc__`
* `html`: A boolean indicating if HTML output is required. `True` when used in the browsable API, and `False` when used in generating `OPTIONS` responses. * `html`: A boolean indicating if HTML output is required. `True` when used in the browsable API, and `False` when used in generating `OPTIONS` responses.
If the view instance inherits `ViewSet`, it may have been initialized with several optional arguments:
* `description`: A description explicitly provided to the view in the viewset. Typically, this is set by extra viewset `action`s, and should be used as-is.
Default: `'rest_framework.views.get_view_description'` Default: `'rest_framework.views.get_view_description'`
## HTML Select Field cutoffs ## HTML Select Field cutoffs
@ -475,4 +460,4 @@ Default: `None`
[cite]: https://www.python.org/dev/peps/pep-0020/ [cite]: https://www.python.org/dev/peps/pep-0020/
[rfc4627]: https://www.ietf.org/rfc/rfc4627.txt [rfc4627]: https://www.ietf.org/rfc/rfc4627.txt
[heroku-minified-json]: https://github.com/interagent/http-api-design#keep-json-minified-in-all-responses [heroku-minified-json]: https://github.com/interagent/http-api-design#keep-json-minified-in-all-responses
[strftime]: https://docs.python.org/3/library/time.html#time.strftime [strftime]: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes

View File

@ -1,4 +1,7 @@
source: status.py ---
source:
- status.py
---
# Status Codes # Status Codes
@ -20,13 +23,13 @@ The full set of HTTP status codes included in the `status` module is listed belo
The module also includes a set of helper functions for testing if a status code is in a given range. The module also includes a set of helper functions for testing if a status code is in a given range.
from rest_framework import status from rest_framework import status
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
class ExampleTestCase(APITestCase): class ExampleTestCase(APITestCase):
def test_url_root(self): def test_url_root(self):
url = reverse('index') url = reverse('index')
response = self.client.get(url) response = self.client.get(url)
self.assertTrue(status.is_success(response.status_code)) self.assertTrue(status.is_success(response.status_code))
For more information on proper usage of HTTP status codes see [RFC 2616][rfc2616] For more information on proper usage of HTTP status codes see [RFC 2616][rfc2616]
@ -38,6 +41,8 @@ This class of status code indicates a provisional response. There are no 1xx st
HTTP_100_CONTINUE HTTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS HTTP_101_SWITCHING_PROTOCOLS
HTTP_102_PROCESSING
HTTP_103_EARLY_HINTS
## Successful - 2xx ## Successful - 2xx
@ -51,6 +56,8 @@ This class of status code indicates that the client's request was successfully r
HTTP_205_RESET_CONTENT HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS HTTP_207_MULTI_STATUS
HTTP_208_ALREADY_REPORTED
HTTP_226_IM_USED
## Redirection - 3xx ## Redirection - 3xx
@ -64,6 +71,7 @@ This class of status code indicates that further action needs to be taken by the
HTTP_305_USE_PROXY HTTP_305_USE_PROXY
HTTP_306_RESERVED HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT HTTP_307_TEMPORARY_REDIRECT
HTTP_308_PERMANENT_REDIRECT
## Client Error - 4xx ## Client Error - 4xx
@ -87,9 +95,12 @@ The 4xx class of status code is intended for cases in which the client seems to
HTTP_415_UNSUPPORTED_MEDIA_TYPE HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED HTTP_417_EXPECTATION_FAILED
HTTP_421_MISDIRECTED_REQUEST
HTTP_422_UNPROCESSABLE_ENTITY HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY HTTP_424_FAILED_DEPENDENCY
HTTP_425_TOO_EARLY
HTTP_426_UPGRADE_REQUIRED
HTTP_428_PRECONDITION_REQUIRED HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
@ -105,7 +116,11 @@ Response status codes beginning with the digit "5" indicate cases in which the s
HTTP_503_SERVICE_UNAVAILABLE HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_506_VARIANT_ALSO_NEGOTIATES
HTTP_507_INSUFFICIENT_STORAGE HTTP_507_INSUFFICIENT_STORAGE
HTTP_508_LOOP_DETECTED
HTTP_509_BANDWIDTH_LIMIT_EXCEEDED
HTTP_510_NOT_EXTENDED
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED HTTP_511_NETWORK_AUTHENTICATION_REQUIRED
## Helper functions ## Helper functions

View File

@ -1,4 +1,7 @@
source: test.py ---
source:
- test.py
---
# Testing # Testing
@ -22,9 +25,12 @@ The `APIRequestFactory` class supports an almost identical API to Django's stand
factory = APIRequestFactory() factory = APIRequestFactory()
request = factory.post('/notes/', {'title': 'new idea'}) request = factory.post('/notes/', {'title': 'new idea'})
# Using the standard RequestFactory API to encode JSON data
request = factory.post('/notes/', {'title': 'new idea'}, content_type='application/json')
#### Using the `format` argument #### Using the `format` argument
Methods which create a request body, such as `post`, `put` and `patch`, include a `format` argument, which make it easy to generate requests using a content type other than multipart form data. For example: Methods which create a request body, such as `post`, `put` and `patch`, include a `format` argument, which make it easy to generate requests using a wide set of request formats. When using this argument, the factory will select an appropriate renderer and its configured `content_type`. For example:
# Create a JSON POST request # Create a JSON POST request
factory = APIRequestFactory() factory = APIRequestFactory()
@ -38,7 +44,7 @@ To support a wider set of request formats, or change the default format, [see th
If you need to explicitly encode the request body, you can do so by setting the `content_type` flag. For example: If you need to explicitly encode the request body, you can do so by setting the `content_type` flag. For example:
request = factory.post('/notes/', json.dumps({'title': 'new idea'}), content_type='application/json') request = factory.post('/notes/', yaml.dump({'title': 'new idea'}), content_type='application/yaml')
#### PUT and PATCH with form data #### PUT and PATCH with form data
@ -119,7 +125,7 @@ Extends [Django's existing `Client` class][client].
## Making requests ## Making requests
The `APIClient` class supports the same request interface as Django's standard `Client` class. This means the that standard `.get()`, `.post()`, `.put()`, `.patch()`, `.delete()`, `.head()` and `.options()` methods are all available. For example: The `APIClient` class supports the same request interface as Django's standard `Client` class. This means that the standard `.get()`, `.post()`, `.put()`, `.patch()`, `.delete()`, `.head()` and `.options()` methods are all available. For example:
from rest_framework.test import APIClient from rest_framework.test import APIClient
@ -201,13 +207,15 @@ live environment. (See "Live tests" below.)
This exposes exactly the same interface as if you were using a requests session This exposes exactly the same interface as if you were using a requests session
directly. directly.
from rest_framework.test import RequestsClient
client = RequestsClient() client = RequestsClient()
response = client.get('http://testserver/users/') response = client.get('http://testserver/users/')
assert response.status_code == 200 assert response.status_code == 200
Note that the requests client requires you to pass fully qualified URLs. Note that the requests client requires you to pass fully qualified URLs.
## `RequestsClient` and working with the database ## RequestsClient and working with the database
The `RequestsClient` class is useful if you want to write tests that solely interact with the service interface. This is a little stricter than using the standard Django test client, as it means that all interactions should be via the API. The `RequestsClient` class is useful if you want to write tests that solely interact with the service interface. This is a little stricter than using the standard Django test client, as it means that all interactions should be via the API.
@ -216,7 +224,7 @@ If you're using `RequestsClient` you'll want to ensure that test setup, and resu
## Headers & Authentication ## Headers & Authentication
Custom headers and authentication credentials can be provided in the same way Custom headers and authentication credentials can be provided in the same way
as [when using a standard `requests.Session` instance](http://docs.python-requests.org/en/master/user/advanced/#session-objects). as [when using a standard `requests.Session` instance][session_objects].
from requests.auth import HTTPBasicAuth from requests.auth import HTTPBasicAuth
@ -229,7 +237,7 @@ If you're using `SessionAuthentication` then you'll need to include a CSRF token
for any `POST`, `PUT`, `PATCH` or `DELETE` requests. for any `POST`, `PUT`, `PATCH` or `DELETE` requests.
You can do so by following the same flow that a JavaScript based client would use. You can do so by following the same flow that a JavaScript based client would use.
First make a `GET` request in order to obtain a CRSF token, then present that First, make a `GET` request in order to obtain a CSRF token, then present that
token in the following request. token in the following request.
For example... For example...
@ -237,12 +245,12 @@ For example...
client = RequestsClient() client = RequestsClient()
# Obtain a CSRF token. # Obtain a CSRF token.
response = client.get('/homepage/') response = client.get('http://testserver/homepage/')
assert response.status_code == 200 assert response.status_code == 200
csrftoken = response.cookies['csrftoken'] csrftoken = response.cookies['csrftoken']
# Interact with the API. # Interact with the API.
response = client.post('/organisations/', json={ response = client.post('http://testserver/organisations/', json={
'name': 'MegaCorp', 'name': 'MegaCorp',
'status': 'active' 'status': 'active'
}, headers={'X-CSRFToken': csrftoken}) }, headers={'X-CSRFToken': csrftoken})
@ -254,7 +262,7 @@ With careful usage both the `RequestsClient` and the `CoreAPIClient` provide
the ability to write test cases that can run either in development, or be run the ability to write test cases that can run either in development, or be run
directly against your staging server or production environment. directly against your staging server or production environment.
Using this style to create basic tests of a few core piece of functionality is Using this style to create basic tests of a few core pieces of functionality is
a powerful way to validate your live service. Doing so may require some careful a powerful way to validate your live service. Doing so may require some careful
attention to setup and teardown to ensure that the tests run in a way that they attention to setup and teardown to ensure that the tests run in a way that they
do not directly affect customer data. do not directly affect customer data.
@ -294,7 +302,7 @@ similar way as with `RequestsClient`.
# API Test cases # API Test cases
REST framework includes the following test case classes, that mirror the existing Django test case classes, but use `APIClient` instead of Django's default `Client`. REST framework includes the following test case classes, that mirror the existing [Django's test case classes][provided_test_case_classes], but use `APIClient` instead of Django's default `Client`.
* `APISimpleTestCase` * `APISimpleTestCase`
* `APITransactionTestCase` * `APITransactionTestCase`
@ -397,15 +405,17 @@ For example, to add support for using `format='html'` in test requests, you migh
REST_FRAMEWORK = { REST_FRAMEWORK = {
... ...
'TEST_REQUEST_RENDERER_CLASSES': ( 'TEST_REQUEST_RENDERER_CLASSES': [
'rest_framework.renderers.MultiPartRenderer', 'rest_framework.renderers.MultiPartRenderer',
'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.TemplateHTMLRenderer' 'rest_framework.renderers.TemplateHTMLRenderer'
) ]
} }
[cite]: https://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper [cite]: https://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper
[client]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#the-test-client [client]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#the-test-client
[requestfactory]: https://docs.djangoproject.com/en/stable/topics/testing/advanced/#django.test.client.RequestFactory [requestfactory]: https://docs.djangoproject.com/en/stable/topics/testing/advanced/#django.test.client.RequestFactory
[configuration]: #configuration [configuration]: #configuration
[refresh_from_db_docs]: https://docs.djangoproject.com/en/1.11/ref/models/instances/#django.db.models.Model.refresh_from_db [refresh_from_db_docs]: https://docs.djangoproject.com/en/stable/ref/models/instances/#django.db.models.Model.refresh_from_db
[session_objects]: https://requests.readthedocs.io/en/master/user/advanced/#session-objects
[provided_test_case_classes]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#provided-test-case-classes

View File

@ -1,4 +1,7 @@
source: throttling.py ---
source:
- throttling.py
---
# Throttling # Throttling
@ -16,6 +19,10 @@ Multiple throttles can also be used if you want to impose both burst throttling
Throttles do not necessarily only refer to rate-limiting requests. For example a storage service might also need to throttle against bandwidth, and a paid data service might want to throttle against a certain number of a records being accessed. Throttles do not necessarily only refer to rate-limiting requests. For example a storage service might also need to throttle against bandwidth, and a paid data service might want to throttle against a certain number of a records being accessed.
**The application-level throttling that REST framework provides should not be considered a security measure or protection against brute forcing or denial-of-service attacks. Deliberately malicious actors will always be able to spoof IP origins. In addition to this, the built-in throttling implementations are implemented using Django's cache framework, and use non-atomic operations to determine the request rate, which may sometimes result in some fuzziness.
The application-level throttling provided by REST framework is intended for implementing policies such as different business tiers and basic protections against service over-use.**
## How throttling is determined ## How throttling is determined
As with permissions and authentication, throttling in REST framework is always defined as a list of classes. As with permissions and authentication, throttling in REST framework is always defined as a list of classes.
@ -28,27 +35,27 @@ If any throttle check fails an `exceptions.Throttled` exception will be raised,
The default throttling policy may be set globally, using the `DEFAULT_THROTTLE_CLASSES` and `DEFAULT_THROTTLE_RATES` settings. For example. The default throttling policy may be set globally, using the `DEFAULT_THROTTLE_CLASSES` and `DEFAULT_THROTTLE_RATES` settings. For example.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': ( 'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle' 'rest_framework.throttling.UserRateThrottle'
), ],
'DEFAULT_THROTTLE_RATES': { 'DEFAULT_THROTTLE_RATES': {
'anon': '100/day', 'anon': '100/day',
'user': '1000/day' 'user': '1000/day'
} }
} }
The rate descriptions used in `DEFAULT_THROTTLE_RATES` may include `second`, `minute`, `hour` or `day` as the throttle period. The rates used in `DEFAULT_THROTTLE_RATES` can be specified over a period of second, minute, hour or day. The period must be specified after the `/` separator using `s`, `m`, `h` or `d`, respectively. For increased clarity, extended units such as `second`, `minute`, `hour`, `day` or even abbreviations like `sec`, `min`, `hr` are allowed, as only the first character is relevant to identify the rate.
You can also set the throttling policy on a per-view or per-viewset basis, You can also set the throttling policy on a per-view or per-viewset basis,
using the `APIView` class-based views. using the `APIView` class-based views.
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.throttling import UserRateThrottle from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView from rest_framework.views import APIView
class ExampleView(APIView): class ExampleView(APIView):
throttle_classes = (UserRateThrottle,) throttle_classes = [UserRateThrottle]
def get(self, request, format=None): def get(self, request, format=None):
content = { content = {
@ -56,7 +63,7 @@ using the `APIView` class-based views.
} }
return Response(content) return Response(content)
Or, if you're using the `@api_view` decorator with function based views. If you're using the `@api_view` decorator with function based views you can use the following decorator.
@api_view(['GET']) @api_view(['GET'])
@throttle_classes([UserRateThrottle]) @throttle_classes([UserRateThrottle])
@ -66,7 +73,17 @@ Or, if you're using the `@api_view` decorator with function based views.
} }
return Response(content) return Response(content)
## How clients are identified It's also possible to set throttle classes for routes that are created using the `@action` decorator.
Throttle classes set in this way will override any viewset level class settings.
@action(detail=True, methods=["post"], throttle_classes=[UserRateThrottle])
def example_adhoc_method(request, pk=None):
content = {
'status': 'request was permitted'
}
return Response(content)
## How clients are identified
The `X-Forwarded-For` HTTP header and `REMOTE_ADDR` WSGI variable are used to uniquely identify client IP addresses for throttling. If the `X-Forwarded-For` header is present then it will be used, otherwise the value of the `REMOTE_ADDR` variable from the WSGI environment will be used. The `X-Forwarded-For` HTTP header and `REMOTE_ADDR` WSGI variable are used to uniquely identify client IP addresses for throttling. If the `X-Forwarded-For` header is present then it will be used, otherwise the value of the `REMOTE_ADDR` variable from the WSGI environment will be used.
@ -74,7 +91,7 @@ If you need to strictly identify unique client IP addresses, you'll need to firs
It is important to understand that if you configure the `NUM_PROXIES` setting, then all clients behind a unique [NAT'd](https://en.wikipedia.org/wiki/Network_address_translation) gateway will be treated as a single client. It is important to understand that if you configure the `NUM_PROXIES` setting, then all clients behind a unique [NAT'd](https://en.wikipedia.org/wiki/Network_address_translation) gateway will be treated as a single client.
Further context on how the `X-Forwarded-For` header works, and identifying a remote client IP can be [found here][identifing-clients]. Further context on how the `X-Forwarded-For` header works, and identifying a remote client IP can be [found here][identifying-clients].
## Setting up the cache ## Setting up the cache
@ -82,11 +99,19 @@ The throttle classes provided by REST framework use Django's cache backend. You
If you need to use a cache other than `'default'`, you can do so by creating a custom throttle class and setting the `cache` attribute. For example: If you need to use a cache other than `'default'`, you can do so by creating a custom throttle class and setting the `cache` attribute. For example:
from django.core.cache import caches
class CustomAnonRateThrottle(AnonRateThrottle): class CustomAnonRateThrottle(AnonRateThrottle):
cache = get_cache('alternate') cache = caches['alternate']
You'll need to remember to also set your custom throttle class in the `'DEFAULT_THROTTLE_CLASSES'` settings key, or using the `throttle_classes` view attribute. You'll need to remember to also set your custom throttle class in the `'DEFAULT_THROTTLE_CLASSES'` settings key, or using the `throttle_classes` view attribute.
## A note on concurrency
The built-in throttle implementations are open to [race conditions][race], so under high concurrency they may allow a few extra requests through.
If your project relies on guaranteeing the number of requests during concurrent requests, you will need to implement your own throttle class.
--- ---
# API Reference # API Reference
@ -124,10 +149,10 @@ For example, multiple user throttle rates could be implemented by using the foll
...and the following settings. ...and the following settings.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': ( 'DEFAULT_THROTTLE_CLASSES': [
'example.throttles.BurstRateThrottle', 'example.throttles.BurstRateThrottle',
'example.throttles.SustainedRateThrottle' 'example.throttles.SustainedRateThrottle'
), ],
'DEFAULT_THROTTLE_RATES': { 'DEFAULT_THROTTLE_RATES': {
'burst': '60/min', 'burst': '60/min',
'sustained': '1000/day' 'sustained': '1000/day'
@ -159,9 +184,9 @@ For example, given the following views...
...and the following settings. ...and the following settings.
REST_FRAMEWORK = { REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': ( 'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.ScopedRateThrottle', 'rest_framework.throttling.ScopedRateThrottle',
), ],
'DEFAULT_THROTTLE_RATES': { 'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day', 'contacts': '1000/day',
'uploads': '20/day' 'uploads': '20/day'
@ -192,6 +217,7 @@ The following is an example of a rate throttle, that will randomly throttle 1 in
[cite]: https://developer.twitter.com/en/docs/basics/rate-limiting [cite]: https://developer.twitter.com/en/docs/basics/rate-limiting
[permissions]: permissions.md [permissions]: permissions.md
[identifing-clients]: http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster [identifying-clients]: http://oxpedia.org/wiki/index.php?title=AppSuite:Grizzly#Multiple_Proxies_in_front_of_the_cluster
[cache-setting]: https://docs.djangoproject.com/en/stable/ref/settings/#caches [cache-setting]: https://docs.djangoproject.com/en/stable/ref/settings/#caches
[cache-docs]: https://docs.djangoproject.com/en/stable/topics/cache/#setting-up-the-cache [cache-docs]: https://docs.djangoproject.com/en/stable/topics/cache/#setting-up-the-cache
[race]: https://en.wikipedia.org/wiki/Race_condition#Data_race

View File

@ -1,4 +1,7 @@
source: validators.py ---
source:
- validators.py
---
# Validators # Validators
@ -17,7 +20,7 @@ Validation in Django REST framework serializers is handled a little differently
With `ModelForm` the validation is performed partially on the form, and partially on the model instance. With REST framework the validation is performed entirely on the serializer class. This is advantageous for the following reasons: With `ModelForm` the validation is performed partially on the form, and partially on the model instance. With REST framework the validation is performed entirely on the serializer class. This is advantageous for the following reasons:
* It introduces a proper separation of concerns, making your code behavior more obvious. * It introduces a proper separation of concerns, making your code behavior more obvious.
* It is easy to switch between using shortcut `ModelSerializer` classes and using explicit `Serializer` classes. Any validation behavior being used for `ModelSerializer` is simple to replicate. * It is easy to switch between using shortcut `ModelSerializer` classes and using explicit `Serializer` classes. Any validation behavior being used for `ModelSerializer` is simple to replicate.
* Printing the `repr` of a serializer instance will show you exactly what validation rules it applies. There's no extra hidden validation behavior being called on the model instance. * Printing the `repr` of a serializer instance will show you exactly what validation rules it applies. There's no extra hidden validation behavior being called on the model instance.
When you're using `ModelSerializer` all of this is handled automatically for you. If you want to drop down to using `Serializer` classes instead, then you need to define the validation rules explicitly. When you're using `ModelSerializer` all of this is handled automatically for you. If you want to drop down to using `Serializer` classes instead, then you need to define the validation rules explicitly.
@ -45,12 +48,12 @@ If we open up the Django shell using `manage.py shell` we can now
CustomerReportSerializer(): CustomerReportSerializer():
id = IntegerField(label='ID', read_only=True) id = IntegerField(label='ID', read_only=True)
time_raised = DateTimeField(read_only=True) time_raised = DateTimeField(read_only=True)
reference = CharField(max_length=20, validators=[<UniqueValidator(queryset=CustomerReportRecord.objects.all())>]) reference = CharField(max_length=20, validators=[UniqueValidator(queryset=CustomerReportRecord.objects.all())])
description = CharField(style={'type': 'textarea'}) description = CharField(style={'type': 'textarea'})
The interesting bit here is the `reference` field. We can see that the uniqueness constraint is being explicitly enforced by a validator on the serializer field. The interesting bit here is the `reference` field. We can see that the uniqueness constraint is being explicitly enforced by a validator on the serializer field.
Because of this more explicit style REST framework includes a few validator classes that are not available in core Django. These classes are detailed below. Because of this more explicit style REST framework includes a few validator classes that are not available in core Django. These classes are detailed below. REST framework validators, like their Django counterparts, implement the `__eq__` method, allowing you to compare instances for equality.
--- ---
@ -94,13 +97,13 @@ The validator should be applied to *serializer classes*, like so:
validators = [ validators = [
UniqueTogetherValidator( UniqueTogetherValidator(
queryset=ToDoItem.objects.all(), queryset=ToDoItem.objects.all(),
fields=('list', 'position') fields=['list', 'position']
) )
] ]
--- ---
**Note**: The `UniqueTogetherValidation` class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input. **Note**: The `UniqueTogetherValidator` class always imposes an implicit constraint that all the fields it applies to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
--- ---
@ -149,8 +152,6 @@ If you want the date field to be visible, but not editable by the user, then set
published = serializers.DateTimeField(read_only=True, default=timezone.now) published = serializers.DateTimeField(read_only=True, default=timezone.now)
The field will not be writable to the user, but the default value will still be passed through to the `validated_data`.
#### Using with a hidden date field. #### Using with a hidden date field.
If you want the date field to be entirely hidden from the user, then use `HiddenField`. This field type does not accept user input, but instead always returns its default value to the `validated_data` in the serializer. If you want the date field to be entirely hidden from the user, then use `HiddenField`. This field type does not accept user input, but instead always returns its default value to the `validated_data` in the serializer.
@ -159,18 +160,22 @@ If you want the date field to be entirely hidden from the user, then use `Hidden
--- ---
**Note**: The `UniqueFor<Range>Validation` classes impose an implicit constraint that the fields they are applied to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input. **Note**: The `UniqueFor<Range>Validator` classes impose an implicit constraint that the fields they are applied to are always treated as required. Fields with `default` values are an exception to this as they always supply a value even when omitted from user input.
---
---
**Note:** `HiddenField()` does not appear in `partial=True` serializer (when making `PATCH` request).
--- ---
# Advanced field defaults # Advanced field defaults
Validators that are applied across multiple fields in the serializer can sometimes require a field input that should not be provided by the API client, but that *is* available as input to the validator. Validators that are applied across multiple fields in the serializer can sometimes require a field input that should not be provided by the API client, but that *is* available as input to the validator.
For this purposes use `HiddenField`. This field will be present in `validated_data` but *will not* be used in the serializer output representation.
Two patterns that you may want to use for this sort of validation include: **Note:** Using a `read_only=True` field is excluded from writable fields so it won't use a `default=…` argument. Look [3.8 announcement](https://www.django-rest-framework.org/community/3.8-announcement/#altered-the-behaviour-of-read_only-plus-default-on-field).
* Using `HiddenField`. This field will be present in `validated_data` but *will not* be used in the serializer output representation.
* Using a standard field with `read_only=True`, but that also includes a `default=…` argument. This field *will* be used in the serializer output representation, but cannot be set directly by the user.
REST framework includes a couple of defaults that may be useful in this context. REST framework includes a couple of defaults that may be useful in this context.
@ -182,7 +187,7 @@ A default class that can be used to represent the current user. In order to use
default=serializers.CurrentUserDefault() default=serializers.CurrentUserDefault()
) )
#### CreateOnlyDefault #### CreateOnlyDefault
A default class that can be used to *only set a default argument during create operations*. During updates the field is omitted. A default class that can be used to *only set a default argument during create operations*. During updates the field is omitted.
@ -207,7 +212,7 @@ by specifying an empty list for the serializer `Meta.validators` attribute.
By default "unique together" validation enforces that all fields be By default "unique together" validation enforces that all fields be
`required=True`. In some cases, you might want to explicit apply `required=True`. In some cases, you might want to explicit apply
`required=False` to one of the fields, in which case the desired behaviour `required=False` to one of the fields, in which case the desired behavior
of the validation is ambiguous. of the validation is ambiguous.
In this case you will typically need to exclude the validator from the In this case you will typically need to exclude the validator from the
@ -217,11 +222,11 @@ in the `.validate()` method, or else in the view.
For example: For example:
class BillingRecordSerializer(serializers.ModelSerializer): class BillingRecordSerializer(serializers.ModelSerializer):
def validate(self, data): def validate(self, attrs):
# Apply custom validation either here, or in the view. # Apply custom validation either here, or in the view.
class Meta: class Meta:
fields = ('client', 'date', 'amount') fields = ['client', 'date', 'amount']
extra_kwargs = {'client': {'required': False}} extra_kwargs = {'client': {'required': False}}
validators = [] # Remove a default "unique together" constraint. validators = [] # Remove a default "unique together" constraint.
@ -237,7 +242,7 @@ In the case of update operations on *nested* serializers there's no way of
applying this exclusion, because the instance is not available. applying this exclusion, because the instance is not available.
Again, you'll probably want to explicitly remove the validator from the Again, you'll probably want to explicitly remove the validator from the
serializer class, and write the code the for the validation constraint serializer class, and write the code for the validation constraint
explicitly, in a `.validate()` method, or in the view. explicitly, in a `.validate()` method, or in the view.
## Debugging complex cases ## Debugging complex cases
@ -275,13 +280,13 @@ A validator may be any callable that raises a `serializers.ValidationError` on f
You can specify custom field-level validation by adding `.validate_<field_name>` methods You can specify custom field-level validation by adding `.validate_<field_name>` methods
to your `Serializer` subclass. This is documented in the to your `Serializer` subclass. This is documented in the
[Serializer docs](http://www.django-rest-framework.org/api-guide/serializers/#field-level-validation) [Serializer docs](https://www.django-rest-framework.org/api-guide/serializers/#field-level-validation)
## Class-based ## Class-based
To write a class-based validator, use the `__call__` method. Class-based validators are useful as they allow you to parameterize and reuse behavior. To write a class-based validator, use the `__call__` method. Class-based validators are useful as they allow you to parameterize and reuse behavior.
class MultipleOf(object): class MultipleOf:
def __init__(self, base): def __init__(self, base):
self.base = base self.base = base
@ -290,13 +295,18 @@ To write a class-based validator, use the `__call__` method. Class-based validat
message = 'This field must be a multiple of %d.' % self.base message = 'This field must be a multiple of %d.' % self.base
raise serializers.ValidationError(message) raise serializers.ValidationError(message)
#### Using `set_context()` #### Accessing the context
In some advanced cases you might want a validator to be passed the serializer field it is being used with as additional context. You can do so by declaring a `set_context` method on a class-based validator. In some advanced cases you might want a validator to be passed the serializer
field it is being used with as additional context. You can do so by setting
a `requires_context = True` attribute on the validator class. The `__call__` method
will then be called with the `serializer_field`
or `serializer` as an additional argument.
def set_context(self, serializer_field): class MultipleOf:
# Determine if this is an update or a create operation. requires_context = True
# In `__call__` we can then use that information to modify the validation behavior.
self.is_update = serializer_field.parent.instance is not None def __call__(self, value, serializer_field):
...
[cite]: https://docs.djangoproject.com/en/stable/ref/validators/ [cite]: https://docs.djangoproject.com/en/stable/ref/validators/

View File

@ -1,4 +1,7 @@
source: versioning.py ---
source:
- versioning.py
---
# Versioning # Versioning
@ -129,12 +132,12 @@ This scheme requires the client to specify the version as part of the URL path.
Your URL conf must include a pattern that matches the version with a `'version'` keyword argument, so that this information is available to the versioning scheme. Your URL conf must include a pattern that matches the version with a `'version'` keyword argument, so that this information is available to the versioning scheme.
urlpatterns = [ urlpatterns = [
url( re_path(
r'^(?P<version>(v1|v2))/bookings/$', r'^(?P<version>(v1|v2))/bookings/$',
bookings_list, bookings_list,
name='bookings-list' name='bookings-list'
), ),
url( re_path(
r'^(?P<version>(v1|v2))/bookings/(?P<pk>[0-9]+)/$', r'^(?P<version>(v1|v2))/bookings/(?P<pk>[0-9]+)/$',
bookings_detail, bookings_detail,
name='bookings-detail' name='bookings-detail'
@ -155,14 +158,14 @@ In the following example we're giving a set of views two different possible URL
# bookings/urls.py # bookings/urls.py
urlpatterns = [ urlpatterns = [
url(r'^$', bookings_list, name='bookings-list'), re_path(r'^$', bookings_list, name='bookings-list'),
url(r'^(?P<pk>[0-9]+)/$', bookings_detail, name='bookings-detail') re_path(r'^(?P<pk>[0-9]+)/$', bookings_detail, name='bookings-detail')
] ]
# urls.py # urls.py
urlpatterns = [ urlpatterns = [
url(r'^v1/bookings/', include('bookings.urls', namespace='v1')), re_path(r'^v1/bookings/', include('bookings.urls', namespace='v1')),
url(r'^v2/bookings/', include('bookings.urls', namespace='v2')) re_path(r'^v2/bookings/', include('bookings.urls', namespace='v2'))
] ]
Both `URLPathVersioning` and `NamespaceVersioning` are reasonable if you just need a simple versioning scheme. The `URLPathVersioning` approach might be better suitable for small ad-hoc projects, and the `NamespaceVersioning` is probably easier to manage for larger projects. Both `URLPathVersioning` and `NamespaceVersioning` are reasonable if you just need a simple versioning scheme. The `URLPathVersioning` approach might be better suitable for small ad-hoc projects, and the `NamespaceVersioning` is probably easier to manage for larger projects.

View File

@ -1,5 +1,8 @@
source: decorators.py ---
views.py source:
- decorators.py
- views.py
---
# Class-based Views # Class-based Views
@ -32,8 +35,8 @@ For example:
* Requires token authentication. * Requires token authentication.
* Only admin users are able to access this view. * Only admin users are able to access this view.
""" """
authentication_classes = (authentication.TokenAuthentication,) authentication_classes = [authentication.TokenAuthentication]
permission_classes = (permissions.IsAdminUser,) permission_classes = [permissions.IsAdminUser]
def get(self, request, format=None): def get(self, request, format=None):
""" """
@ -142,6 +145,7 @@ REST framework also allows you to work with regular function based views. It pr
The core of this functionality is the `api_view` decorator, which takes a list of HTTP methods that your view should respond to. For example, this is how you would write a very simple view that just manually returns some data: The core of this functionality is the `api_view` decorator, which takes a list of HTTP methods that your view should respond to. For example, this is how you would write a very simple view that just manually returns some data:
from rest_framework.decorators import api_view from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view() @api_view()
def hello_world(request): def hello_world(request):
@ -149,7 +153,7 @@ The core of this functionality is the `api_view` decorator, which takes a list o
This view will use the default renderers, parsers, authentication classes etc specified in the [settings]. This view will use the default renderers, parsers, authentication classes etc specified in the [settings].
By default only `GET` methods will be accepted. Other methods will respond with "405 Method Not Allowed". To alter this behaviour, specify which methods the view allows, like so: By default only `GET` methods will be accepted. Other methods will respond with "405 Method Not Allowed". To alter this behavior, specify which methods the view allows, like so:
@api_view(['GET', 'POST']) @api_view(['GET', 'POST'])
def hello_world(request): def hello_world(request):
@ -166,7 +170,7 @@ To override the default settings, REST framework provides a set of additional de
from rest_framework.throttling import UserRateThrottle from rest_framework.throttling import UserRateThrottle
class OncePerDayUserThrottle(UserRateThrottle): class OncePerDayUserThrottle(UserRateThrottle):
rate = '1/day' rate = '1/day'
@api_view(['GET']) @api_view(['GET'])
@throttle_classes([OncePerDayUserThrottle]) @throttle_classes([OncePerDayUserThrottle])

View File

@ -1,4 +1,7 @@
source: viewsets.py ---
source:
- viewsets.py
---
# ViewSets # ViewSets
@ -51,7 +54,7 @@ Typically we wouldn't do this, but would instead register the viewset with a rou
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
router = DefaultRouter() router = DefaultRouter()
router.register(r'users', UserViewSet, base_name='user') router.register(r'users', UserViewSet, basename='user')
urlpatterns = router.urls urlpatterns = router.urls
Rather than writing your own viewsets, you'll often want to use the existing base classes that provide a default set of behavior. For example: Rather than writing your own viewsets, you'll often want to use the existing base classes that provide a default set of behavior. For example:
@ -110,8 +113,10 @@ During dispatch, the following attributes are available on the `ViewSet`.
* `action` - the name of the current action (e.g., `list`, `create`). * `action` - the name of the current action (e.g., `list`, `create`).
* `detail` - boolean indicating if the current action is configured for a list or detail view. * `detail` - boolean indicating if the current action is configured for a list or detail view.
* `suffix` - the display suffix for the viewset type - mirrors the `detail` attribute. * `suffix` - the display suffix for the viewset type - mirrors the `detail` attribute.
* `name` - the display name for the viewset. This argument is mutually exclusive to `suffix`.
* `description` - the display description for the individual view of a viewset.
You may inspect these attributes to adjust behaviour based on the current action. For example, you could restrict permissions to everything except the `list` action similar to this: You may inspect these attributes to adjust behavior based on the current action. For example, you could restrict permissions to everything except the `list` action similar to this:
def get_permissions(self): def get_permissions(self):
""" """
@ -120,12 +125,14 @@ You may inspect these attributes to adjust behaviour based on the current action
if self.action == 'list': if self.action == 'list':
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
else: else:
permission_classes = [IsAdmin] permission_classes = [IsAdminUser]
return [permission() for permission in permission_classes] return [permission() for permission in permission_classes]
**Note**: the `action` attribute is not available in the `get_parsers`, `get_authenticators` and `get_content_negotiator` methods, as it is set _after_ they are called in the framework lifecycle. If you override one of these methods and try to access the `action` attribute in them, you will get an `AttributeError` error.
## Marking extra actions for routing ## Marking extra actions for routing
If you have ad-hoc methods that should be routable, you can mark them as such with the `@action` decorator. Like regular actions, extra actions may be intended for either a list of objects, or a single instance. To indicate this, set the `detail` argument to `True` or `False`. The router will configure its URL patterns accordingly. e.g., the `DefaultRouter` will configure detail actions to contain `pk` in their URL patterns. If you have ad-hoc methods that should be routable, you can mark them as such with the `@action` decorator. Like regular actions, extra actions may be intended for either a single object, or an entire collection. To indicate this, set the `detail` argument to `True` or `False`. The router will configure its URL patterns accordingly. e.g., the `DefaultRouter` will configure detail actions to contain `pk` in their URL patterns.
A more complete example of extra actions: A more complete example of extra actions:
@ -142,12 +149,12 @@ A more complete example of extra actions:
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
@action(methods=['post'], detail=True) @action(detail=True, methods=['post'])
def set_password(self, request, pk=None): def set_password(self, request, pk=None):
user = self.get_object() user = self.get_object()
serializer = PasswordSerializer(data=request.data) serializer = PasswordSerializer(data=request.data)
if serializer.is_valid(): if serializer.is_valid():
user.set_password(serializer.data['password']) user.set_password(serializer.validated_data['password'])
user.save() user.save()
return Response({'status': 'password set'}) return Response({'status': 'password set'})
else: else:
@ -156,7 +163,7 @@ A more complete example of extra actions:
@action(detail=False) @action(detail=False)
def recent_users(self, request): def recent_users(self, request):
recent_users = User.objects.all().order('-last_login') recent_users = User.objects.all().order_by('-last_login')
page = self.paginate_queryset(recent_users) page = self.paginate_queryset(recent_users)
if page is not None: if page is not None:
@ -166,22 +173,48 @@ A more complete example of extra actions:
serializer = self.get_serializer(recent_users, many=True) serializer = self.get_serializer(recent_users, many=True)
return Response(serializer.data) return Response(serializer.data)
The decorator can additionally take extra arguments that will be set for the routed view only. For example:
@action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf]) The `action` decorator will route `GET` requests by default, but may also accept other HTTP methods by setting the `methods` argument. For example:
def set_password(self, request, pk=None):
...
These decorator will route `GET` requests by default, but may also accept other HTTP methods by setting the `methods` argument. For example: @action(detail=True, methods=['post', 'delete'])
@action(methods=['post', 'delete'], detail=True)
def unset_password(self, request, pk=None): def unset_password(self, request, pk=None):
... ...
The two new actions will then be available at the urls `^users/{pk}/set_password/$` and `^users/{pk}/unset_password/$` Argument `methods` also supports HTTP methods defined as [HTTPMethod](https://docs.python.org/3/library/http.html#http.HTTPMethod). Example below is identical to the one above:
from http import HTTPMethod
@action(detail=True, methods=[HTTPMethod.POST, HTTPMethod.DELETE])
def unset_password(self, request, pk=None):
...
The decorator allows you to override any viewset-level configuration such as `permission_classes`, `serializer_class`, `filter_backends`...:
@action(detail=True, methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...
The two new actions will then be available at the urls `^users/{pk}/set_password/$` and `^users/{pk}/unset_password/$`. Use the `url_path` and `url_name` parameters to change the URL segment and the reverse URL name of the action.
To view all extra actions, call the `.get_extra_actions()` method. To view all extra actions, call the `.get_extra_actions()` method.
### Routing additional HTTP methods for extra actions
Extra actions can map additional HTTP methods to separate `ViewSet` methods. For example, the above password set/unset methods could be consolidated into a single route. Note that additional mappings do not accept arguments.
```python
@action(detail=True, methods=["put"], name="Change Password")
def password(self, request, pk=None):
"""Update the user's password."""
...
@password.mapping.delete
def delete_password(self, request, pk=None):
"""Delete the user's password."""
...
```
## Reversing action URLs ## Reversing action URLs
If you need to get the URL of an action, use the `.reverse_action()` method. This is a convenience wrapper for `reverse()`, automatically passing the view's `request` object and prepending the `url_name` with the `.basename` attribute. If you need to get the URL of an action, use the `.reverse_action()` method. This is a convenience wrapper for `reverse()`, automatically passing the view's `request` object and prepending the `url_name` with the `.basename` attribute.
@ -190,14 +223,14 @@ Note that the `basename` is provided by the router during `ViewSet` registration
Using the example from the previous section: Using the example from the previous section:
```python ```pycon
>>> view.reverse_action('set-password', args=['1']) >>> view.reverse_action("set-password", args=["1"])
'http://localhost:8000/api/users/1/set_password' 'http://localhost:8000/api/users/1/set_password'
``` ```
Alternatively, you can use the `url_name` attribute set by the `@action` decorator. Alternatively, you can use the `url_name` attribute set by the `@action` decorator.
```python ```pycon
>>> view.reverse_action(view.set_password.url_name, args=['1']) >>> view.reverse_action(view.set_password.url_name, args=['1'])
'http://localhost:8000/api/users/1/set_password' 'http://localhost:8000/api/users/1/set_password'
``` ```
@ -224,7 +257,7 @@ In order to use a `GenericViewSet` class you'll override the class and either mi
The `ModelViewSet` class inherits from `GenericAPIView` and includes implementations for various actions, by mixing in the behavior of the various mixin classes. The `ModelViewSet` class inherits from `GenericAPIView` and includes implementations for various actions, by mixing in the behavior of the various mixin classes.
The actions provided by the `ModelViewSet` class are `.list()`, `.retrieve()`, `.create()`, `.update()`, `.partial_update()`, and `.destroy()`. The actions provided by the `ModelViewSet` class are `.list()`, `.retrieve()`, `.create()`, `.update()`, `.partial_update()`, and `.destroy()`.
#### Example #### Example
@ -251,7 +284,7 @@ Note that you can use any of the standard attributes or method overrides provide
def get_queryset(self): def get_queryset(self):
return self.request.user.accounts.all() return self.request.user.accounts.all()
Note however that upon removal of the `queryset` property from your `ViewSet`, any associated [router][routers] will be unable to derive the base_name of your Model automatically, and so you will have to specify the `base_name` kwarg as part of your [router registration][routers]. Note however that upon removal of the `queryset` property from your `ViewSet`, any associated [router][routers] will be unable to derive the basename of your Model automatically, and so you will have to specify the `basename` kwarg as part of your [router registration][routers].
Also note that although this class provides the complete set of create/list/retrieve/update/destroy actions by default, you can restrict the available operations by using the standard permission classes. Also note that although this class provides the complete set of create/list/retrieve/update/destroy actions by default, you can restrict the available operations by using the standard permission classes.
@ -280,7 +313,7 @@ You may need to provide custom `ViewSet` classes that do not have the full set o
To create a base viewset class that provides `create`, `list` and `retrieve` operations, inherit from `GenericViewSet`, and mixin the required actions: To create a base viewset class that provides `create`, `list` and `retrieve` operations, inherit from `GenericViewSet`, and mixin the required actions:
from rest_framework import mixins from rest_framework import mixins, viewsets
class CreateListRetrieveViewSet(mixins.CreateModelMixin, class CreateListRetrieveViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin, mixins.ListModelMixin,
@ -296,5 +329,5 @@ To create a base viewset class that provides `create`, `list` and `retrieve` ope
By creating your own base `ViewSet` classes, you can provide common behavior that can be reused in multiple viewsets across your API. By creating your own base `ViewSet` classes, you can provide common behavior that can be reused in multiple viewsets across your API.
[cite]: http://guides.rubyonrails.org/routing.html [cite]: https://guides.rubyonrails.org/action_controller_overview.html
[routers]: routers.md [routers]: routers.md

View File

@ -24,7 +24,7 @@ Notable features of this new release include:
* Support for overriding how validation errors are handled by your API. * 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 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. * 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. * 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 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. 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.
@ -119,7 +119,7 @@ This would now be split out into two separate methods.
instance.save() instance.save()
return instance return instance
def create(self, validated_data): def create(self, validated_data):
return Snippet.objects.create(**validated_data) return Snippet.objects.create(**validated_data)
Note that these methods should return the newly created object instance. Note that these methods should return the newly created object instance.
@ -258,13 +258,13 @@ If you try to use a writable nested serializer without writing a custom `create(
>>> class ProfileSerializer(serializers.ModelSerializer): >>> class ProfileSerializer(serializers.ModelSerializer):
>>> class Meta: >>> class Meta:
>>> model = Profile >>> model = Profile
>>> fields = ('address', 'phone') >>> fields = ['address', 'phone']
>>> >>>
>>> class UserSerializer(serializers.ModelSerializer): >>> class UserSerializer(serializers.ModelSerializer):
>>> profile = ProfileSerializer() >>> profile = ProfileSerializer()
>>> class Meta: >>> class Meta:
>>> model = User >>> model = User
>>> fields = ('username', 'email', 'profile') >>> fields = ['username', 'email', 'profile']
>>> >>>
>>> data = { >>> data = {
>>> 'username': 'lizzy', >>> 'username': 'lizzy',
@ -283,7 +283,7 @@ To use writable nested serialization you'll want to declare a nested field on th
class Meta: class Meta:
model = User model = User
fields = ('username', 'email', 'profile') fields = ['username', 'email', 'profile']
def create(self, validated_data): def create(self, validated_data):
profile_data = validated_data.pop('profile') profile_data = validated_data.pop('profile')
@ -327,9 +327,9 @@ The `write_only_fields` option on `ModelSerializer` has been moved to `PendingDe
class MySerializer(serializer.ModelSerializer): class MySerializer(serializer.ModelSerializer):
class Meta: class Meta:
model = MyModel model = MyModel
fields = ('id', 'email', 'notes', 'is_admin') fields = ['id', 'email', 'notes', 'is_admin']
extra_kwargs = { extra_kwargs = {
'is_admin': {'write_only': True} 'is_admin': {'write_only': True}
} }
Alternatively, specify the field explicitly on the serializer class: Alternatively, specify the field explicitly on the serializer class:
@ -339,7 +339,7 @@ Alternatively, specify the field explicitly on the serializer class:
class Meta: class Meta:
model = MyModel model = MyModel
fields = ('id', 'email', 'notes', 'is_admin') 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.
@ -350,7 +350,7 @@ The `view_name` and `lookup_field` options have been moved to `PendingDeprecatio
class MySerializer(serializer.HyperlinkedModelSerializer): class MySerializer(serializer.HyperlinkedModelSerializer):
class Meta: class Meta:
model = MyModel model = MyModel
fields = ('url', 'email', 'notes', 'is_admin') fields = ['url', 'email', 'notes', 'is_admin']
extra_kwargs = { extra_kwargs = {
'url': {'lookup_field': 'uuid'} 'url': {'lookup_field': 'uuid'}
} }
@ -365,7 +365,7 @@ Alternatively, specify the field explicitly on the serializer class:
class Meta: class Meta:
model = MyModel model = MyModel
fields = ('url', 'email', 'notes', 'is_admin') fields = ['url', 'email', 'notes', 'is_admin']
#### Fields for model methods and properties. #### Fields for model methods and properties.
@ -384,12 +384,12 @@ You can include `expiry_date` as a field option on a `ModelSerializer` class.
class InvitationSerializer(serializers.ModelSerializer): class InvitationSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Invitation model = Invitation
fields = ('to_email', 'message', 'expiry_date') fields = ['to_email', 'message', 'expiry_date']
These fields will be mapped to `serializers.ReadOnlyField()` instances. These fields will be mapped to `serializers.ReadOnlyField()` instances.
>>> serializer = InvitationSerializer() >>> serializer = InvitationSerializer()
>>> print repr(serializer) >>> print(repr(serializer))
InvitationSerializer(): InvitationSerializer():
to_email = EmailField(max_length=75) to_email = EmailField(max_length=75)
message = CharField(max_length=1000) message = CharField(max_length=1000)
@ -454,7 +454,7 @@ We can now use this class to serialize single `HighScore` instances:
def high_score(request, pk): def high_score(request, pk):
instance = HighScore.objects.get(pk=pk) instance = HighScore.objects.get(pk=pk)
serializer = HighScoreSerializer(instance) serializer = HighScoreSerializer(instance)
return Response(serializer.data) return Response(serializer.data)
Or use it to serialize multiple instances: Or use it to serialize multiple instances:
@ -462,7 +462,7 @@ Or use it to serialize multiple instances:
def all_high_scores(request): def all_high_scores(request):
queryset = HighScore.objects.order_by('-score') queryset = HighScore.objects.order_by('-score')
serializer = HighScoreSerializer(queryset, many=True) serializer = HighScoreSerializer(queryset, many=True)
return Response(serializer.data) return Response(serializer.data)
##### Read-write `BaseSerializer` classes. ##### Read-write `BaseSerializer` classes.
@ -493,8 +493,8 @@ Here's a complete example of our previous `HighScoreSerializer`, that's been upd
'player_name': 'May not be more than 10 characters.' 'player_name': 'May not be more than 10 characters.'
}) })
# Return the validated values. This will be available as # Return the validated values. This will be available as
# the `.validated_data` property. # the `.validated_data` property.
return { return {
'score': int(score), 'score': int(score),
'player_name': player_name 'player_name': player_name
@ -523,7 +523,7 @@ The following class is an example of a generic serializer that can handle coerci
def to_representation(self, obj): def to_representation(self, obj):
for attribute_name in dir(obj): for attribute_name in dir(obj):
attribute = getattr(obj, attribute_name) attribute = getattr(obj, attribute_name)
if attribute_name('_'): if attribute_name.startswith('_'):
# Ignore private attributes. # Ignore private attributes.
pass pass
elif hasattr(attribute, '__call__'): elif hasattr(attribute, '__call__'):
@ -632,7 +632,7 @@ The `MultipleChoiceField` class has been added. This field acts like `ChoiceFiel
The `from_native(self, value)` and `to_native(self, data)` method names have been replaced with the more obviously named `to_internal_value(self, data)` and `to_representation(self, value)`. The `from_native(self, value)` and `to_native(self, data)` method names have been replaced with the more obviously named `to_internal_value(self, data)` and `to_representation(self, value)`.
The `field_from_native()` and `field_to_native()` methods are removed. Previously you could use these methods if you wanted to customise the behaviour in a way that did not simply lookup the field value from the object. For example... The `field_from_native()` and `field_to_native()` methods are removed. Previously you could use these methods if you wanted to customise the behavior in a way that did not simply lookup the field value from the object. For example...
def field_to_native(self, obj, field_name): def field_to_native(self, obj, field_name):
"""A custom read-only field that returns the class name.""" """A custom read-only field that returns the class name."""
@ -738,7 +738,7 @@ The `UniqueTogetherValidator` should be applied to a serializer, and takes a `qu
class Meta: class Meta:
validators = [UniqueTogetherValidator( validators = [UniqueTogetherValidator(
queryset=RaceResult.objects.all(), queryset=RaceResult.objects.all(),
fields=('category', 'position') fields=['category', 'position']
)] )]
#### The `UniqueForDateValidator` classes. #### The `UniqueForDateValidator` classes.
@ -960,6 +960,6 @@ 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/encode/django-rest-framework/milestones). You can follow development on the GitHub site, where we use [milestones to indicate planning timescales](https://github.com/encode/django-rest-framework/milestones).
[kickstarter]: https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3 [kickstarter]: https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3
[sponsors]: http://www.django-rest-framework.org/topics/kickstarter-announcement/#sponsors [sponsors]: https://www.django-rest-framework.org/community/kickstarter-announcement/#sponsors
[mixins.py]: https://github.com/encode/django-rest-framework/blob/master/rest_framework/mixins.py [mixins.py]: https://github.com/encode/django-rest-framework/blob/master/rest_framework/mixins.py
[django-localization]: https://docs.djangoproject.com/en/stable/topics/i18n/translation/#localization-how-to-create-language-files [django-localization]: https://docs.djangoproject.com/en/stable/topics/i18n/translation/#localization-how-to-create-language-files

View File

@ -30,7 +30,7 @@ Note that as a result of this work a number of settings keys and generic view at
Until now, there has only been a single built-in pagination style in REST framework. We now have page, limit/offset and cursor based schemes included by default. Until now, there has only been a single built-in pagination style in REST framework. We now have page, limit/offset and cursor based schemes included by default.
The cursor based pagination scheme is particularly smart, and is a better approach for clients iterating through large or frequently changing result sets. The scheme supports paging against non-unique indexes, by using both cursor and limit/offset information. It also allows for both forward and reverse cursor pagination. Much credit goes to David Cramer for [this blog post](http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api) on the subject. The cursor based pagination scheme is particularly smart, and is a better approach for clients iterating through large or frequently changing result sets. The scheme supports paging against non-unique indexes, by using both cursor and limit/offset information. It also allows for both forward and reverse cursor pagination. Much credit goes to David Cramer for [this blog post](https://cra.mr/2011/03/08/building-cursors-for-the-disqus-api) on the subject.
#### Pagination controls in the browsable API. #### Pagination controls in the browsable API.
@ -61,7 +61,7 @@ For example, when using `NamespaceVersioning`, and the following hyperlinked ser
class AccountsSerializer(serializer.HyperlinkedModelSerializer): class AccountsSerializer(serializer.HyperlinkedModelSerializer):
class Meta: class Meta:
model = Accounts model = Accounts
fields = ('account_name', 'users') fields = ['account_name', 'users']
The output representation would match the version used on the incoming request. Like so: The output representation would match the version used on the incoming request. Like so:
@ -114,7 +114,7 @@ Note that the structure of the error responses is still the same. We still have
We include built-in translations both for standard exception cases, and for serializer validation errors. We include built-in translations both for standard exception cases, and for serializer validation errors.
The full list of supported languages can be found on our [Transifex project page](https://www.transifex.com/projects/p/django-rest-framework/). The full list of supported languages can be found on our [Transifex project page](https://www.transifex.com/django-rest-framework-1/django-rest-framework/).
If you only wish to support a subset of the supported languages, use Django's standard `LANGUAGES` setting: If you only wish to support a subset of the supported languages, use Django's standard `LANGUAGES` setting:
@ -123,7 +123,7 @@ If you only wish to support a subset of the supported languages, use Django's st
('en', _('English')), ('en', _('English')),
] ]
For more details, see the [internationalization documentation](internationalization.md). For more details, see the [internationalization documentation][internationalization].
Many thanks to [Craig Blaszczyk](https://github.com/jakul) for helping push this through. Many thanks to [Craig Blaszczyk](https://github.com/jakul) for helping push this through.
@ -155,14 +155,14 @@ We've now moved a number of packages out of the core of REST framework, and into
We're making this change in order to help distribute the maintenance workload, and keep better focus of the core essentials of the framework. We're making this change in order to help distribute the maintenance workload, and keep better focus of the core essentials of the framework.
The change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained [Django OAuth toolkit](https://github.com/evonove/django-oauth-toolkit) has now been promoted as our recommended option for integrating OAuth support. The change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained [Django OAuth toolkit](https://github.com/jazzband/django-oauth-toolkit) has now been promoted as our recommended option for integrating OAuth support.
The following packages are now moved out of core and should be separately installed: The following packages are now moved out of core and should be separately installed:
* OAuth - [djangorestframework-oauth](https://jpadilla.github.io/django-rest-framework-oauth/) * OAuth - [djangorestframework-oauth](https://jpadilla.github.io/django-rest-framework-oauth/)
* XML - [djangorestframework-xml](https://jpadilla.github.io/django-rest-framework-xml) * XML - [djangorestframework-xml](https://jpadilla.github.io/django-rest-framework-xml/)
* YAML - [djangorestframework-yaml](https://jpadilla.github.io/django-rest-framework-yaml) * YAML - [djangorestframework-yaml](https://jpadilla.github.io/django-rest-framework-yaml/)
* JSONP - [djangorestframework-jsonp](https://jpadilla.github.io/django-rest-framework-jsonp) * JSONP - [djangorestframework-jsonp](https://jpadilla.github.io/django-rest-framework-jsonp/)
It's worth reiterating that this change in policy shouldn't mean any work in your codebase other than adding a new requirement and modifying some import paths. For example to install XML rendering, you would now do: It's worth reiterating that this change in policy shouldn't mean any work in your codebase other than adding a new requirement and modifying some import paths. For example to install XML rendering, you would now do:
@ -205,5 +205,5 @@ This will either be made as a single 3.2 release, or split across two separate r
[custom-exception-handler]: ../api-guide/exceptions.md#custom-exception-handling [custom-exception-handler]: ../api-guide/exceptions.md#custom-exception-handling
[pagination]: ../api-guide/pagination.md [pagination]: ../api-guide/pagination.md
[versioning]: ../api-guide/versioning.md [versioning]: ../api-guide/versioning.md
[internationalization]: internationalization.md [internationalization]: ../topics/internationalization.md
[customizing-field-mappings]: ../api-guide/serializers.md#customizing-field-mappings [customizing-field-mappings]: ../api-guide/serializers.md#customizing-field-mappings

View File

@ -0,0 +1,148 @@
<style>
.promo li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
color: black;
}
.promo li {
list-style: none;
}
</style>
# Django REST framework 3.10
The 3.10 release drops support for Python 2.
* Our supported Python versions are now: 3.5, 3.6, and 3.7.
* Our supported Django versions are now: 1.11, 2.0, 2.1, and 2.2.
## OpenAPI Schema Generation
Since we first introduced schema support in Django REST Framework 3.5, OpenAPI has emerged as the widely adopted standard for modeling Web APIs.
This release begins the deprecation process for the CoreAPI based schema generation, and introduces OpenAPI schema generation in its place.
---
## Continuing to use CoreAPI
If you're currently using the CoreAPI schemas, you'll need to make sure to
update your REST framework settings to include `DEFAULT_SCHEMA_CLASS` explicitly.
**settings.py**:
```python
REST_FRAMEWORK = {
...: ...,
"DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.coreapi.AutoSchema",
}
```
You'll still be able to keep using CoreAPI schemas, API docs, and client for the
foreseeable future. We'll aim to ensure that the CoreAPI schema generator remains
available as a third party package, even once it has eventually been removed
from REST framework, scheduled for version 3.12.
We have removed the old documentation for the CoreAPI based schema generation.
You may view the [Legacy CoreAPI documentation here][legacy-core-api-docs].
----
## OpenAPI Quickstart
You can generate a static OpenAPI schema, using the `generateschema` management
command.
Alternately, to have the project serve an API schema, use the `get_schema_view()`
shortcut.
In your `urls.py`:
```python
from rest_framework.schemas import get_schema_view
urlpatterns = [
# ...
# Use the `get_schema_view()` helper to add a `SchemaView` to project URLs.
# * `title` and `description` parameters are passed to `SchemaGenerator`.
# * Provide view name for use with `reverse()`.
path(
"openapi",
get_schema_view(title="Your Project", description="API for all things …"),
name="openapi-schema",
),
# ...
]
```
### Customization
For customizations that you want to apply across the entire API, you can subclass `rest_framework.schemas.openapi.SchemaGenerator` and provide it as an argument
to the `generateschema` command or `get_schema_view()` helper function.
For specific per-view customizations, you can subclass `AutoSchema`,
making sure to set `schema = <YourCustomClass>` on the view.
For more details, see the [API Schema documentation](../api-guide/schemas.md).
### API Documentation
There are some great third party options for documenting your API, based on the
OpenAPI schema.
See the [Documenting you API](../topics/documenting-your-api.md) section for more details.
---
## Feature Roadmap
Given that our OpenAPI schema generation is a new feature, it's likely that there
will still be some iterative improvements for us to make. There will be two
main cases here:
* Expanding the supported range of OpenAPI schemas that are generated by default.
* Improving the ability for developers to customize the output.
We'll aim to bring the first type of change quickly in point releases. For the
second kind we'd like to adopt a slower approach, to make sure we keep the API
simple, and as widely applicable as possible, before we bring in API changes.
It's also possible that we'll end up implementing API documentation and API client
tooling that are driven by the OpenAPI schema. The `apistar` project has a
significant amount of work towards this. However, if we do so, we'll plan
on keeping any tooling outside of the core framework.
---
## Funding
REST framework is a *collaboratively funded project*. If you use
REST framework commercially we strongly encourage you to invest in its
continued development by **[signing up for a paid plan][funding]**.
*Every single sign-up helps us make REST framework long-term financially sustainable.*
<ul class="premium-promo promo">
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
<li><a href="https://getstream.io/try-the-api/?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>
<li><a href="https://software.esg-usa.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/esg-new-logo.png)">ESG</a></li>
<li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar2.png)">Rollbar</a></li>
<li><a href="https://cadre.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/cadre.png)">Cadre</a></li>
<li><a href="https://hubs.ly/H0f30Lf0" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/kloudless-plus-text.png)">Kloudless</a></li>
<li><a href="https://lightsonsoftware.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/lightson-dark.png)">Lights On Software</a></li>
</ul>
<div style="clear: both; padding-bottom: 20px;"></div>
*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), and [Lights On Software](https://lightsonsoftware.com).*
[legacy-core-api-docs]:https://github.com/encode/django-rest-framework/blob/3.14.0/docs/coreapi/index.md
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors
[funding]: funding.md

View File

@ -0,0 +1,118 @@
<style>
.promo li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
color: black;
}
.promo li {
list-style: none;
}
</style>
# Django REST framework 3.11
The 3.11 release adds support for Django 3.0.
* Our supported Python versions are now: 3.5, 3.6, 3.7, and 3.8.
* Our supported Django versions are now: 1.11, 2.0, 2.1, 2.2, and 3.0.
This release will be the last to support Python 3.5 or Django 1.11.
## OpenAPI Schema Generation Improvements
The OpenAPI schema generation continues to mature. Some highlights in 3.11
include:
* Automatic mapping of Django REST Framework renderers and parsers into OpenAPI
request and response media-types.
* Improved mapping JSON schema mapping types, for example in HStoreFields, and
with large integer values.
* Porting of the old CoreAPI parsing of docstrings to form OpenAPI operation
descriptions.
In this example view operation descriptions for the `get` and `post` methods will
be extracted from the class docstring:
```python
class DocStringExampleListView(APIView):
"""
get: A description of my GET operation.
post: A description of my POST operation.
"""
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def get(self, request, *args, **kwargs):
...
def post(self, request, *args, **kwargs):
...
```
## Validator / Default Context
In some circumstances a Validator class or a Default class may need to access the serializer field with which it is called, or the `.context` with which the serializer was instantiated. In particular:
* Uniqueness validators need to be able to determine the name of the field to which they are applied, in order to run an appropriate database query.
* The `CurrentUserDefault` needs to be able to determine the context with which the serializer was instantiated, in order to return the current user instance.
Our previous approach to this was that implementations could include a `set_context` method, which would be called prior to validation. However this approach had issues with potential race conditions. We have now move this approach into a pending deprecation state. It will continue to function, but will be escalated to a deprecated state in 3.12, and removed entirely in 3.13.
Instead, validators or defaults which require the serializer context, should include a `requires_context = True` attribute on the class.
The `__call__` method should then include an additional `serializer_field` argument.
Validator implementations will look like this:
```python
class CustomValidator:
requires_context = True
def __call__(self, value, serializer_field):
...
```
Default implementations will look like this:
```python
class CustomDefault:
requires_context = True
def __call__(self, serializer_field):
...
```
---
## Funding
REST framework is a *collaboratively funded project*. If you use
REST framework commercially we strongly encourage you to invest in its
continued development by **[signing up for a paid plan][funding]**.
*Every single sign-up helps us make REST framework long-term financially sustainable.*
<ul class="premium-promo promo">
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
<li><a href="https://getstream.io/try-the-api/?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>
<li><a href="https://software.esg-usa.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/esg-new-logo.png)">ESG</a></li>
<li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar2.png)">Rollbar</a></li>
<li><a href="https://cadre.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/cadre.png)">Cadre</a></li>
<li><a href="https://hubs.ly/H0f30Lf0" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/kloudless-plus-text.png)">Kloudless</a></li>
<li><a href="https://lightsonsoftware.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/lightson-dark.png)">Lights On Software</a></li>
<li><a href="https://retool.com/?utm_source=djangorest&utm_medium=sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/retool-sidebar.png)">Retool</a></li>
</ul>
<div style="clear: both; padding-bottom: 20px;"></div>
*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), and [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship).*
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors
[funding]: funding.md

View File

@ -0,0 +1,181 @@
<style>
.promo li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
color: black;
}
.promo li {
list-style: none;
}
</style>
# Django REST framework 3.12
REST framework 3.12 brings a handful of refinements to the OpenAPI schema
generation, plus support for Django's new database-agnostic `JSONField`,
and some improvements to the `SearchFilter` class.
## Grouping operations with tags.
Open API schemas will now automatically include tags, based on the first element
in the URL path.
For example...
Method | Path | Tags
--------------------------------|-----------------|-------------
`GET`, `PUT`, `PATCH`, `DELETE` | `/users/{id}/` | `['users']`
`GET`, `POST` | `/users/` | `['users']`
`GET`, `PUT`, `PATCH`, `DELETE` | `/orders/{id}/` | `['orders']`
`GET`, `POST` | `/orders/` | `['orders']`
The tags used for a particular view may also be overridden...
```python
class MyOrders(APIView):
schema = AutoSchema(tags=["users", "orders"])
...
```
See [the schema documentation](https://www.django-rest-framework.org/api-guide/schemas/#grouping-operations-with-tags) for more information.
## Customizing the operation ID.
REST framework automatically determines operation IDs to use in OpenAPI
schemas. The latest version provides more control for overriding the behaviour
used to generate the operation IDs.
See [the schema documentation](https://www.django-rest-framework.org/api-guide/schemas/#operationid) for more information.
## Support for OpenAPI components.
In order to output more graceful OpenAPI schemes, REST framework 3.12 now
defines components in the schema, and then references them inside request
and response objects. This is in contrast with the previous approach, which
fully expanded the request and response bodies for each operation.
The names used for a component default to using the serializer class name, [but
may be overridden if needed](https://www.django-rest-framework.org/api-guide/schemas/#components
)...
```python
class MyOrders(APIView):
schema = AutoSchema(component_name="OrderDetails")
```
## More Public API
Many methods on the `AutoSchema` class have now been promoted to public API,
allowing you to more fully customize the schema generation. The following methods
are now available for overriding...
* `get_path_parameters`
* `get_pagination_parameters`
* `get_filter_parameters`
* `get_request_body`
* `get_responses`
* `get_serializer`
* `get_paginator`
* `map_serializer`
* `map_field`
* `map_choice_field`
* `map_field_validators`
* `allows_filters`.
See [the schema docs](https://www.django-rest-framework.org/api-guide/schemas/#per-view-customization)
for details on using custom `AutoSchema` subclasses.
## Support for JSONField.
Django 3.1 deprecated the existing `django.contrib.postgres.fields.JSONField`
in favour of a new database-agnositic `JSONField`.
REST framework 3.12 now supports this new model field, and `ModelSerializer`
classes will correctly map the model field.
## SearchFilter improvements
There are a couple of significant improvements to the `SearchFilter` class.
### Nested searches against JSONField and HStoreField
The class now supports nested search within `JSONField` and `HStoreField`, using
the double underscore notation for traversing which element of the field the
search should apply to.
```python
class SitesSearchView(generics.ListAPIView):
"""
An API view to return a list of archaeological sites, optionally filtered
by a search against the site name or location. (Location searches are
matched against the region and country names.)
"""
queryset = Sites.objects.all()
serializer_class = SitesSerializer
filter_backends = [filters.SearchFilter]
search_fields = ["site_name", "location__region", "location__country"]
```
### Searches against annotate fields
Django allows querysets to create additional virtual fields, using the `.annotate`
method. We now support searching against annotate fields.
```python
class PublisherSearchView(generics.ListAPIView):
"""
Search for publishers, optionally filtering the search against the average
rating of all their books.
"""
queryset = Publisher.objects.annotate(avg_rating=Avg("book__rating"))
serializer_class = PublisherSerializer
filter_backends = [filters.SearchFilter]
search_fields = ["avg_rating"]
```
---
## Deprecations
### `serializers.NullBooleanField`
`serializers.NullBooleanField` is now pending deprecation, and will be removed in 3.14.
Instead use `serializers.BooleanField` field and set `allow_null=True` which does the same thing.
---
## Funding
REST framework is a *collaboratively funded project*. If you use
REST framework commercially we strongly encourage you to invest in its
continued development by **[signing up for a paid plan][funding]**.
*Every single sign-up helps us make REST framework long-term financially sustainable.*
<ul class="premium-promo promo">
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
<li><a href="https://getstream.io/try-the-api/?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>
<li><a href="https://software.esg-usa.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/esg-new-logo.png)">ESG</a></li>
<li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar2.png)">Rollbar</a></li>
<li><a href="https://cadre.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/cadre.png)">Cadre</a></li>
<li><a href="https://hubs.ly/H0f30Lf0" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/kloudless-plus-text.png)">Kloudless</a></li>
<li><a href="https://lightsonsoftware.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/lightson-dark.png)">Lights On Software</a></li>
<li><a href="https://retool.com/?utm_source=djangorest&utm_medium=sponsorship" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/retool-sidebar.png)">Retool</a></li>
</ul>
<div style="clear: both; padding-bottom: 20px;"></div>
*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [ESG](https://software.esg-usa.com/), [Rollbar](https://rollbar.com/?utm_source=django&utm_medium=sponsorship&utm_campaign=freetrial), [Cadre](https://cadre.com), [Kloudless](https://hubs.ly/H0f30Lf0), [Lights On Software](https://lightsonsoftware.com), and [Retool](https://retool.com/?utm_source=djangorest&utm_medium=sponsorship).*
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors
[funding]: funding.md

View File

@ -0,0 +1,55 @@
<style>
.promo li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
color: black;
}
.promo li {
list-style: none;
}
</style>
# Django REST framework 3.13
## Django 4.0 support
The latest release now fully supports Django 4.0.
Our requirements are now:
* Python 3.6+
* Django 4.0, 3.2, 3.1, 2.2 (LTS)
## Fields arguments are now keyword-only
When instantiating fields on serializers, you should always use keyword arguments,
such as `serializers.CharField(max_length=200)`. This has always been the case,
and all the examples that we have in the documentation use keyword arguments,
rather than positional arguments.
From REST framework 3.13 onwards, this is now *explicitly enforced*.
The most feasible cases where users might be accidentally omitting the keyword arguments
are likely in the composite fields, `ListField` and `DictField`. For instance...
```python
aliases = serializers.ListField(serializers.CharField())
```
They must now use the more explicit keyword argument style...
```python
aliases = serializers.ListField(child=serializers.CharField())
```
This change has been made because using positional arguments here *does not* result in the expected behaviour.
See Pull Request [#7632](https://github.com/encode/django-rest-framework/pull/7632) for more details.

View File

@ -0,0 +1,72 @@
<style>
.promo li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
color: black;
}
.promo li {
list-style: none;
}
</style>
# Django REST framework 3.14
## Django 4.1 support
The latest release now fully supports Django 4.1, and drops support for Django 2.2.
Our requirements are now:
* Python 3.6+
* Django 4.1, 4.0, 3.2, 3.1, 3.0
## `raise_exception` argument for `is_valid` is now keyword-only.
Calling `serializer_instance.is_valid(True)` is no longer acceptable syntax.
If you'd like to use the `raise_exception` argument, you must use it as a
keyword argument.
See Pull Request [#7952](https://github.com/encode/django-rest-framework/pull/7952) for more details.
## `ManyRelatedField` supports returning the default when the source attribute doesn't exist.
Previously, if you used a serializer field with `many=True` with a dot notated source field
that didn't exist, it would raise an `AttributeError`. Now it will return the default or be
skipped depending on the other arguments.
See Pull Request [#7574](https://github.com/encode/django-rest-framework/pull/7574) for more details.
## Make Open API `get_reference` public.
Returns a reference to the serializer component. This may be useful if you override `get_schema()`.
## Change semantic of OR of two permission classes.
When OR-ing two permissions, the request has to pass either class's `has_permission() and has_object_permission()`.
Previously, both class's `has_permission()` was ignored when OR-ing two permissions together.
See Pull Request [#7522](https://github.com/encode/django-rest-framework/pull/7522) for more details.
## Minor fixes and improvements
There are a number of minor fixes and improvements in this release. See the [release notes](release-notes.md) page for a complete listing.
---
## Deprecations
### `serializers.NullBooleanField`
`serializers.NullBooleanField` was moved to pending deprecation in 3.12, and deprecated in 3.13. It has now been removed from the core framework.
Instead use `serializers.BooleanField` field and set `allow_null=True` which does the same thing.

View File

@ -0,0 +1,50 @@
<style>
.promo li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
color: black;
}
.promo li {
list-style: none;
}
</style>
# Django REST framework 3.15
At the Internet, on March 15th, 2024, with 176 commits by 138 authors, we are happy to announce the release of Django REST framework 3.15.
## Django 5.0 and Python 3.12 support
The latest release now fully supports Django 5.0 and Python 3.12.
The current minimum versions of Django still is 3.0 and Python 3.6.
## Primary Support of UniqueConstraint
`ModelSerializer` generates validators for [UniqueConstraint](https://docs.djangoproject.com/en/4.0/ref/models/constraints/#uniqueconstraint) (both UniqueValidator and UniqueTogetherValidator)
## SimpleRouter non-regex matching support
By default the URLs created by `SimpleRouter` use regular expressions. This behavior can be modified by setting the `use_regex_path` argument to `False` when instantiating the router.
## ZoneInfo as the primary source of timezone data
Dependency on pytz has been removed and deprecation warnings have been added, Django will provide ZoneInfo instances as long as USE_DEPRECATED_PYTZ is not enabled. More info on the migration can be found [in this guide](https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html).
## Align `SearchFilter` behaviour to `django.contrib.admin` search
Searches now may contain _quoted phrases_ with spaces, each phrase is considered as a single search term, and it will raise a validation error if any null-character is provided in search. See the [Filtering API guide](../api-guide/filtering.md) for more information.
## Other fixes and improvements
There are a number of fixes and minor improvements in this release, ranging from documentation, internal infrastructure (typing, testing, requirements, deprecation, etc.), security and overall behaviour.
See the [release notes](release-notes.md) page for a complete listing.

View File

@ -0,0 +1,42 @@
<style>
.promo li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
color: black;
}
.promo li {
list-style: none;
}
</style>
# Django REST framework 3.16
At the Internet, on March 28th, 2025, we are happy to announce the release of Django REST framework 3.16.
## Updated Django and Python support
The latest release now fully supports Django 5.1 and the upcoming 5.2 LTS as well as Python 3.13.
The current minimum versions of Django is now 4.2 and Python 3.9.
## Django LoginRequiredMiddleware
The new `LoginRequiredMiddleware` introduced by Django 5.1 can now be used alongside Django REST Framework, however it is not honored for API views as an equivalent behaviour can be configured via `DEFAULT_AUTHENTICATION_CLASSES`. See [our dedicated section](../api-guide/authentication.md#django-51-loginrequiredmiddleware) in the docs for more information.
## Improved support for UniqueConstraint
The generation of validators for [UniqueConstraint](https://docs.djangoproject.com/en/stable/ref/models/constraints/#uniqueconstraint) has been improved to support better nullable fields and constraints with conditions.
## Other fixes and improvements
There are a number of fixes and minor improvements in this release, ranging from documentation, internal infrastructure (typing, testing, requirements, deprecation, etc.), security and overall behaviour.
See the [release notes](release-notes.md) page for a complete listing.

View File

@ -10,7 +10,7 @@ We've also fixed a huge number of issues, and made numerous cleanups and improve
Over the course of the 3.1.x series we've [resolved nearly 600 tickets](https://github.com/encode/django-rest-framework/issues?utf8=%E2%9C%93&q=closed%3A%3E2015-03-05) on our GitHub issue tracker. This means we're currently running at a rate of **closing around 100 issues or pull requests per month**. Over the course of the 3.1.x series we've [resolved nearly 600 tickets](https://github.com/encode/django-rest-framework/issues?utf8=%E2%9C%93&q=closed%3A%3E2015-03-05) on our GitHub issue tracker. This means we're currently running at a rate of **closing around 100 issues or pull requests per month**.
None of this would have been possible without the support of our wonderful Kickstarter backers. If you're looking for a job in Django development we'd strongly recommend taking [a look through our sponsors](http://www.django-rest-framework.org/topics/kickstarter-announcement/#sponsors) and finding out who's hiring. None of this would have been possible without the support of our wonderful Kickstarter backers. If you're looking for a job in Django development we'd strongly recommend taking [a look through our sponsors](https://www.django-rest-framework.org/community/kickstarter-announcement/#sponsors) and finding out who's hiring.
## AdminRenderer ## AdminRenderer
@ -64,7 +64,7 @@ These are a little subtle and probably won't affect most users, but are worth un
### ManyToMany fields and blank=True ### ManyToMany fields and blank=True
We've now added an `allow_empty` argument, which can be used with `ListSerializer`, or with `many=True` relationships. This is `True` by default, but can be set to `False` if you want to disallow empty lists as valid input. We've now added an `allow_empty` argument, which can be used with `ListSerializer`, or with `many=True` relationships. This is `True` by default, but can be set to `False` if you want to disallow empty lists as valid input.
As a follow-up to this we are now able to properly mirror the behavior of Django's `ModelForm` with respect to how many-to-many fields are validated. As a follow-up to this we are now able to properly mirror the behavior of Django's `ModelForm` with respect to how many-to-many fields are validated.

View File

@ -37,8 +37,8 @@ This brings our supported versions into line with Django's [currently supported
The AJAX based support for the browsable API means that there are a number of internal cleanups in the `request` class. For the vast majority of developers this should largely remain transparent: The AJAX based support for the browsable API means that there are a number of internal cleanups in the `request` class. For the vast majority of developers this should largely remain transparent:
* To support form based `PUT` and `DELETE`, or to support form content types such as JSON, you should now use the [AJAX forms][ajax-form] javascript library. This replaces the previous 'method and content type overloading' that required significant internal complexity to the request class. * To support form based `PUT` and `DELETE`, or to support form content types such as JSON, you should now use the [AJAX forms][ajax-form] javascript library. This replaces the previous 'method and content type overloading' that required significant internal complexity to the request class.
* The `accept` query parameter is no longer supported by the default content negotiation class. If you require it then you'll need to [use a custom content negotiation class](browser-enhancements.md#url-based-accept-headers). * The `accept` query parameter is no longer supported by the default content negotiation class. If you require it then you'll need to [use a custom content negotiation class][accept-headers].
* The custom `HTTP_X_HTTP_METHOD_OVERRIDE` header is no longer supported by default. If you require it then you'll need to [use custom middleware](browser-enhancements.md#http-header-based-method-overriding). * The custom `HTTP_X_HTTP_METHOD_OVERRIDE` header is no longer supported by default. If you require it then you'll need to [use custom middleware][method-override].
The following pagination view attributes and settings have been moved into attributes on the pagination class since 3.1. Their usage was formerly deprecated, and has now been removed entirely, in line with the deprecation policy. The following pagination view attributes and settings have been moved into attributes on the pagination class since 3.1. Their usage was formerly deprecated, and has now been removed entirely, in line with the deprecation policy.
@ -52,7 +52,9 @@ The following pagination view attributes and settings have been moved into attri
The `ModelSerializer` and `HyperlinkedModelSerializer` classes should now include either a `fields` or `exclude` option, although the `fields = '__all__'` shortcut may be used. Failing to include either of these two options is currently pending deprecation, and will be removed entirely in the 3.5 release. This behavior brings `ModelSerializer` more closely in line with Django's `ModelForm` behavior. The `ModelSerializer` and `HyperlinkedModelSerializer` classes should now include either a `fields` or `exclude` option, although the `fields = '__all__'` shortcut may be used. Failing to include either of these two options is currently pending deprecation, and will be removed entirely in the 3.5 release. This behavior brings `ModelSerializer` more closely in line with Django's `ModelForm` behavior.
[forms-api]: html-and-forms.md [forms-api]: ../topics/html-and-forms.md
[ajax-form]: https://github.com/encode/ajax-form [ajax-form]: https://github.com/encode/ajax-form
[jsonfield]: ../../api-guide/fields#jsonfield [jsonfield]: ../api-guide/fields#jsonfield
[accept-headers]: ../topics/browser-enhancements.md#url-based-accept-headers
[method-override]: ../topics/browser-enhancements.md#http-header-based-method-overriding
[django-supported-versions]: https://www.djangoproject.com/download/#supported-versions [django-supported-versions]: https://www.djangoproject.com/download/#supported-versions

View File

@ -36,13 +36,13 @@ Right now we're over 60% of the way towards achieving that.
*Every single sign-up makes a significant impact.* *Every single sign-up makes a significant impact.*
<ul class="premium-promo promo"> <ul class="premium-promo promo">
<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> <li><a href="https://www.rover.com/careers/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rover_130x130.png)">Rover.com</a></li>
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li> <li><a href="https://sentry.io/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
<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> <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>
</ul> </ul>
<div style="clear: both; padding-bottom: 20px;"></div> <div style="clear: both; padding-bottom: 20px;"></div>
*Many thanks to all our [awesome sponsors][sponsors], and in particular to our premium backers, [Rover](http://jobs.rover.com/), [Sentry](https://getsentry.com/welcome/), and [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf).* *Many thanks to all our [awesome sponsors][sponsors], and in particular to our premium backers, [Rover](https://www.rover.com/careers/), [Sentry](https://sentry.io/welcome/), and [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf).*
--- ---
@ -89,7 +89,7 @@ Name | Support | PyPI pa
---------------------------------|-------------------------------------|-------------------------------- ---------------------------------|-------------------------------------|--------------------------------
[Core JSON][core-json] | Schema generation & client support. | Built-in support in `coreapi`. [Core JSON][core-json] | Schema generation & client support. | Built-in support in `coreapi`.
[Swagger / OpenAPI][swagger] | Schema generation & client support. | The `openapi-codec` package. [Swagger / OpenAPI][swagger] | Schema generation & client support. | The `openapi-codec` package.
[JSON Hyper-Schema][hyperschema] | Currently client support only. | The `hyperschema-codec` package. [JSON Hyper-Schema][hyperschema] | Currently client support only. | The `hyperschema-codec` package.
[API Blueprint][api-blueprint] | Not yet available. | Not yet available. [API Blueprint][api-blueprint] | Not yet available. | Not yet available.
--- ---
@ -178,17 +178,17 @@ The full set of itemized release notes [are available here][release-notes].
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors [sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors
[moss]: mozilla-grant.md [moss]: mozilla-grant.md
[funding]: funding.md [funding]: funding.md
[core-api]: http://www.coreapi.org/ [core-api]: https://www.coreapi.org/
[command-line-client]: api-clients#command-line-client [command-line-client]: api-clients#command-line-client
[client-library]: api-clients#python-client-library [client-library]: api-clients#python-client-library
[core-json]: http://www.coreapi.org/specification/encoding/#core-json-encoding [core-json]: https://www.coreapi.org/specification/encoding/#core-json-encoding
[swagger]: https://openapis.org/specification [swagger]: https://openapis.org/specification
[hyperschema]: http://json-schema.org/latest/json-schema-hypermedia.html [hyperschema]: https://json-schema.org/latest/json-schema-hypermedia.html
[api-blueprint]: https://apiblueprint.org/ [api-blueprint]: https://apiblueprint.org/
[tut-7]: ../../tutorial/7-schemas-and-client-libraries/ [tut-7]: ../tutorial/7-schemas-and-client-libraries/
[schema-generation]: ../../api-guide/schemas/ [schema-generation]: ../api-guide/schemas/
[api-clients]: api-clients.md [api-clients]: https://github.com/encode/django-rest-framework/blob/3.14.0/docs/topics/api-clients.md
[milestone]: https://github.com/encode/django-rest-framework/milestone/35 [milestone]: https://github.com/encode/django-rest-framework/milestone/35
[release-notes]: release-notes#34 [release-notes]: release-notes#34
[metadata]: ../../api-guide/metadata/#custom-metadata-classes [metadata]: ../api-guide/metadata/#custom-metadata-classes
[gh3751]: https://github.com/encode/django-rest-framework/issues/3751 [gh3751]: https://github.com/encode/django-rest-framework/issues/3751

View File

@ -32,14 +32,14 @@ we strongly encourage you to invest in its continued development by
**[signing up for a paid&nbsp;plan][funding]**. **[signing up for a paid&nbsp;plan][funding]**.
<ul class="premium-promo promo"> <ul class="premium-promo promo">
<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> <li><a href="https://www.rover.com/careers/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rover_130x130.png)">Rover.com</a></li>
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li> <li><a href="https://sentry.io/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
<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> <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>
<li><a href="https://www.machinalis.com/#services" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/Machinalis130.png)">Machinalis</a></li> <li><a href="https://www.machinalis.com/#services" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/Machinalis130.png)">Machinalis</a></li>
</ul> </ul>
<div style="clear: both; padding-bottom: 20px;"></div> <div style="clear: both; padding-bottom: 20px;"></div>
*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](https://www.machinalis.com/#services).* *Many thanks to all our [sponsors][sponsors], and in particular to our premium backers, [Rover](https://www.rover.com/careers/), [Sentry](https://sentry.io/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), and [Machinalis](https://www.machinalis.com/#services).*
--- ---
@ -64,14 +64,10 @@ from rest_framework.schemas import get_schema_view
from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer
schema_view = get_schema_view( schema_view = get_schema_view(
title='Example API', title="Example API", renderer_classes=[OpenAPIRenderer, SwaggerUIRenderer]
renderer_classes=[OpenAPIRenderer, SwaggerUIRenderer]
) )
urlpatterns = [ urlpatterns = [path("swagger/", schema_view), ...]
url(r'^swagger/$', schema_view),
...
]
``` ```
There have been a large number of fixes to the schema generation. These should There have been a large number of fixes to the schema generation. These should
@ -198,8 +194,8 @@ Make sure to include the view before your router urls. For example:
schema_view = get_schema_view(title='Example API') schema_view = get_schema_view(title='Example API')
urlpatterns = [ urlpatterns = [
url('^$', schema_view), path('', schema_view),
url(r'^', include(router.urls)), path('', include(router.urls)),
] ]
### Schema path representations ### Schema path representations

View File

@ -39,16 +39,16 @@ we strongly encourage you to invest in its continued development by
**[signing up for a paid&nbsp;plan][funding]**. **[signing up for a paid&nbsp;plan][funding]**.
<ul class="premium-promo promo"> <ul class="premium-promo promo">
<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> <li><a href="https://www.rover.com/careers/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rover_130x130.png)">Rover.com</a></li>
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li> <li><a href="https://sentry.io/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
<li><a href="https://getstream.io/try-the-api/?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> <li><a href="https://getstream.io/try-the-api/?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>
<li><a href="https://hello.machinalis.co.uk/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/Machinalis130.png)">Machinalis</a></li> <li><a href="https://machinalis.com/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/Machinalis130.png)">Machinalis</a></li>
<li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar.png)">Rollbar</a></li> <li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar.png)">Rollbar</a></li>
<li><a href="https://micropyramid.com/django-rest-framework-development-services/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/mp-text-logo.png)">MicroPyramid</a></li> <li><a href="https://micropyramid.com/django-rest-framework-development-services/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/mp-text-logo.png)">MicroPyramid</a></li>
</ul> </ul>
<div style="clear: both; padding-bottom: 20px;"></div> <div style="clear: both; padding-bottom: 20px;"></div>
*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), [Machinalis](https://hello.machinalis.co.uk/), [Rollbar](https://rollbar.com), and [MicroPyramid](https://micropyramid.com/django-rest-framework-development-services/).* *Many thanks to all our [sponsors][sponsors], and in particular to our premium backers, [Rover](https://www.rover.com/careers/), [Sentry](https://sentry.io/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [Machinalis](https://machinalis.com/), [Rollbar](https://rollbar.com), and [MicroPyramid](https://micropyramid.com/django-rest-framework-development-services/).*
--- ---
@ -60,7 +60,7 @@ REST framework's new API documentation supports a number of features:
* Support for various authentication schemes. * Support for various authentication schemes.
* Code snippets for the Python, JavaScript, and Command Line clients. * Code snippets for the Python, JavaScript, and Command Line clients.
The `coreapi` library is required as a dependancy for the API docs. Make sure The `coreapi` library is required as a dependency for the API docs. Make sure
to install the latest version (2.3.0 or above). The `pygments` and `markdown` to install the latest version (2.3.0 or above). The `pygments` and `markdown`
libraries are optional but recommended. libraries are optional but recommended.
@ -73,7 +73,7 @@ To install the API documentation, you'll need to include it in your projects URL
urlpatterns = [ urlpatterns = [
... ...
url(r'^docs/', include_docs_urls(title=API_TITLE, description=API_DESCRIPTION)) path('docs/', include_docs_urls(title=API_TITLE, description=API_DESCRIPTION))
] ]
Once installed you should see something a little like this: Once installed you should see something a little like this:
@ -194,6 +194,6 @@ on realtime support, for the 3.7 release.
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors [sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors
[funding]: funding.md [funding]: funding.md
[api-docs]: documenting-your-api.md [api-docs]: ../topics/documenting-your-api.md
[js-docs]: api-clients.md#javascript-client-library [js-docs]: https://github.com/encode/django-rest-framework/blob/3.14.0/docs/topics/api-clients.md#javascript-client-library
[py-docs]: api-clients.md#python-client-library [py-docs]: https://github.com/encode/django-rest-framework/blob/3.14.0/docs/topics/api-clients.md#python-client-library

View File

@ -33,15 +33,15 @@ If you use REST framework commercially and would like to see this work continue,
**[signing up for a paid&nbsp;plan][funding]**. **[signing up for a paid&nbsp;plan][funding]**.
<ul class="premium-promo promo"> <ul class="premium-promo promo">
<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> <li><a href="https://www.rover.com/careers/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rover_130x130.png)">Rover.com</a></li>
<li><a href="https://getsentry.com/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li> <li><a href="https://sentry.io/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
<li><a href="https://getstream.io/try-the-api/?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> <li><a href="https://getstream.io/try-the-api/?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>
<li><a href="https://hello.machinalis.co.uk/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/Machinalis130.png)">Machinalis</a></li> <li><a href="https://machinalis.com/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/Machinalis130.png)">Machinalis</a></li>
<li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar.png)">Rollbar</a></li> <li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar.png)">Rollbar</a></li>
</ul> </ul>
<div style="clear: both; padding-bottom: 20px;"></div> <div style="clear: both; padding-bottom: 20px;"></div>
*As well as our release sponsor, we'd like to say thanks in particular 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), [Machinalis](https://hello.machinalis.co.uk/), and [Rollbar](https://rollbar.com).* *As well as our release sponsor, we'd like to say thanks in particular our premium backers, [Rover](https://www.rover.com/careers/), [Sentry](https://sentry.io/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [Machinalis](https://machinalis.com/), and [Rollbar](https://rollbar.com).*
--- ---

View File

@ -30,7 +30,7 @@ If you use REST framework commercially and would like to see this work continue,
**[signing up for a paid&nbsp;plan][funding]**. **[signing up for a paid&nbsp;plan][funding]**.
*We'd like to say thanks in particular 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), [Machinalis](https://hello.machinalis.co.uk/), and [Rollbar](https://rollbar.com).* *We'd like to say thanks in particular our premium backers, [Rover](https://www.rover.com/careers/), [Sentry](https://sentry.io/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [Machinalis](https://machinalis.com/), and [Rollbar](https://rollbar.com).*
--- ---
@ -50,7 +50,7 @@ the view:
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(owner=self.request.user) serializer.save(owner=self.request.user)
Alternatively you may override `save()` or `create()` or `update()` on the serialiser as appropriate. Alternatively you may override `save()` or `create()` or `update()` on the serializer as appropriate.
--- ---
@ -89,7 +89,7 @@ for a complete listing.
We're currently working towards moving to using [OpenAPI][openapi] as our default schema output. We'll also be revisiting our API documentation generation and client libraries. We're currently working towards moving to using [OpenAPI][openapi] as our default schema output. We'll also be revisiting our API documentation generation and client libraries.
We're doing some consolidation in order to make this happen. It's planned that 3.9 will drop the `coreapi` and `coreschema` libraries, and instead use `apistar` for the API documentation generation, schema generation, and API client libraries. We're doing some consolidation in order to make this happen. It's planned that 3.9 will drop the `coreapi` and `coreschema` libraries, and instead use `apistar` for the API documentation generation, schema generation, and API client libraries.
[funding]: funding.md [funding]: funding.md
[gh5886]: https://github.com/encode/django-rest-framework/issues/5886 [gh5886]: https://github.com/encode/django-rest-framework/issues/5886

View File

@ -0,0 +1,210 @@
<style>
.promo li a {
float: left;
width: 130px;
height: 20px;
text-align: center;
margin: 10px 30px;
padding: 150px 0 0 0;
background-position: 0 50%;
background-size: 130px auto;
background-repeat: no-repeat;
font-size: 120%;
color: black;
}
.promo li {
list-style: none;
}
</style>
# Django REST framework 3.9
The 3.9 release gives access to _extra actions_ in the Browsable API, introduces composable permissions and built-in [OpenAPI][openapi] schema support. (Formerly known as Swagger)
---
## Funding
If you use REST framework commercially and would like to see this work continue, we strongly encourage you to invest in its continued development by
**[signing up for a paid&nbsp;plan][funding]**.
<ul class="premium-promo promo">
<li><a href="https://www.rover.com/careers/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rover_130x130.png)">Rover.com</a></li>
<li><a href="https://sentry.io/welcome/" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/sentry130.png)">Sentry</a></li>
<li><a href="https://getstream.io/try-the-api/?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>
<li><a href="https://auklet.io" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/auklet-new.png)">Auklet</a></li>
<li><a href="https://rollbar.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/rollbar2.png)">Rollbar</a></li>
<li><a href="https://cadre.com" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/cadre.png)">Cadre</a></li>
<li><a href="https://loadimpact.com/?utm_campaign=Sponsorship%20links&utm_source=drf&utm_medium=drf" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/load-impact.png)">Load Impact</a></li>
<li><a href="https://hubs.ly/H0f30Lf0" style="background-image: url(https://fund-rest-framework.s3.amazonaws.com/kloudless.png)">Kloudless</a></li>
</ul>
<div style="clear: both; padding-bottom: 20px;"></div>
*Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Rover](https://www.rover.com/careers/), [Sentry](https://sentry.io/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), [Auklet](https://auklet.io/), [Rollbar](https://rollbar.com), [Cadre](https://cadre.com), [Load Impact](https://loadimpact.com/?utm_campaign=Sponsorship%20links&utm_source=drf&utm_medium=drf), and [Kloudless](https://hubs.ly/H0f30Lf0).*
---
## Built-in OpenAPI schema support
REST framework now has a first-pass at directly including OpenAPI schema support. (Formerly known as Swagger)
Specifically:
* There are now `OpenAPIRenderer`, and `JSONOpenAPIRenderer` classes that deal with encoding `coreapi.Document` instances into OpenAPI YAML or OpenAPI JSON.
* The `get_schema_view(...)` method now defaults to OpenAPI YAML, with CoreJSON as a secondary
option if it is selected via HTTP content negotiation.
* There is a new management command `generateschema`, which you can use to dump
the schema into your repository.
Here's an example of adding an OpenAPI schema to the URL conf:
```python
from rest_framework.schemas import get_schema_view
from rest_framework.renderers import JSONOpenAPIRenderer
from django.urls import path
schema_view = get_schema_view(
title="Server Monitoring API",
url="https://www.example.org/api/",
renderer_classes=[JSONOpenAPIRenderer],
)
urlpatterns = [path("schema.json", schema_view), ...]
```
And here's how you can use the `generateschema` management command:
```shell
$ python manage.py generateschema --format openapi > schema.yml
```
There's lots of different tooling that you can use for working with OpenAPI
schemas. One option that we're working on is the [API Star](https://docs.apistar.com/)
command line tool.
You can use `apistar` to validate your API schema:
```shell
$ apistar validate --path schema.json --format openapi
✓ Valid OpenAPI schema.
```
Or to build API documentation:
```shell
$ apistar docs --path schema.json --format openapi
✓ Documentation built at "build/index.html".
```
API Star also includes a [dynamic client library](https://docs.apistar.com/client-library/)
that uses an API schema to automatically provide a client library interface for making requests.
## Composable permission classes
You can now compose permission classes using the and/or operators, `&` and `|`.
For example...
```python
permission_classes = [IsAuthenticated & (ReadOnly | IsAdminUser)]
```
If you're using custom permission classes then make sure that you are subclassing
from `BasePermission` in order to enable this support.
## ViewSet _Extra Actions_ available in the Browsable API
Following the introduction of the `action` decorator in v3.8, _extra actions_ defined on a ViewSet are now available
from the Browsable API.
![Extra Actions displayed in the Browsable API](https://user-images.githubusercontent.com/2370209/32976956-1ca9ab7e-cbf1-11e7-981a-a20cb1e83d63.png)
When defined, a dropdown of "Extra Actions", appropriately filtered to detail/non-detail actions, is displayed.
---
## Supported Versions
REST framework 3.9 supports Django versions 1.11, 2.0, and 2.1.
---
## Deprecations
### `DjangoObjectPermissionsFilter` moved to third-party package.
The `DjangoObjectPermissionsFilter` class is pending deprecation, will be deprecated in 3.10 and removed entirely in 3.11.
It has been moved to the third-party [`djangorestframework-guardian`](https://github.com/rpkilby/django-rest-framework-guardian)
package. Please use this instead.
### Router argument/method renamed to use `basename` for consistency.
* The `Router.register` `base_name` argument has been renamed in favor of `basename`.
* The `Router.get_default_base_name` method has been renamed in favor of `Router.get_default_basename`. [#5990][gh5990]
See [#5990][gh5990].
[gh5990]: https://github.com/encode/django-rest-framework/pull/5990
`base_name` and `get_default_base_name()` are pending deprecation. They will be deprecated in 3.10 and removed entirely in 3.11.
### `action` decorator replaces `list_route` and `detail_route`
Both `list_route` and `detail_route` are now deprecated in favour of the single `action` decorator.
They will be removed entirely in 3.10.
The `action` decorator takes a boolean `detail` argument.
* Replace `detail_route` uses with `@action(detail=True)`.
* Replace `list_route` uses with `@action(detail=False)`.
### `exclude_from_schema`
Both `APIView.exclude_from_schema` and the `exclude_from_schema` argument to the `@api_view` have now been removed.
For `APIView` you should instead set a `schema = None` attribute on the view class.
For function-based views the `@schema` decorator can be used to exclude the view from the schema, by using `@schema(None)`.
---
## Minor fixes and improvements
There are a large number of minor fixes and improvements in this release. See the [release notes](release-notes.md) page for a complete listing.
## What's next
We're planning to iteratively work towards OpenAPI becoming the standard schema
representation. This will mean that the `coreapi` dependency will gradually become
removed, and we'll instead generate the schema directly, rather than building
a CoreAPI `Document` object.
OpenAPI has clearly become the standard for specifying Web APIs, so there's not
much value any more in our schema-agnostic document model. Making this change
will mean that we'll more easily be able to take advantage of the full set of
OpenAPI functionality.
This will also make a wider range of tooling available.
We'll focus on continuing to develop the [API Star](https://docs.apistar.com/)
library and client tool into a recommended option for generating API docs,
validating API schemas, and providing a dynamic client library.
There's also a huge amount of ongoing work on maturing the ASGI landscape,
with the possibility that some of this work will eventually [feed back into
Django](https://www.aeracode.org/2018/06/04/django-async-roadmap/).
There will be further work on the [Uvicorn](https://www.uvicorn.org/)
web server, as well as lots of functionality planned for the [Starlette](https://www.starlette.io/)
web framework, which is building a foundational set of tooling for working with
ASGI.
[funding]: funding.md
[gh5886]: https://github.com/encode/django-rest-framework/issues/5886
[gh5705]: https://github.com/encode/django-rest-framework/issues/5705
[openapi]: https://www.openapis.org/
[sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors

View File

@ -4,7 +4,9 @@
> >
> &mdash; [Tim Berners-Lee][cite] > &mdash; [Tim Berners-Lee][cite]
There are many ways you can contribute to Django REST framework. We'd like it to be a community-led project, so please get involved and help shape the future of the project. !!! note
At this point in its lifespan we consider Django REST framework to be feature-complete. We focus on pull requests that track the continued development of Django versions, and generally do not accept new features or code formatting changes.
## Community ## Community
@ -26,25 +28,8 @@ The [Django code of conduct][code-of-conduct] gives a fuller set of guidelines f
# Issues # Issues
It's really helpful if you can make sure to address issues on the correct channel. Usage questions should be directed to the [discussion group][google-group]. Feature requests, bug reports and other issues should be raised on the GitHub [issue tracker][issues]. * Django REST framework is considered feature-complete. Please do not file requests to change behavior, unless it is required for security reasons or to maintain compatibility with upcoming Django or Python versions.
* Feature requests will typically be closed with a recommendation that they be implemented outside the core REST framework library (e.g. as third-party libraries). This approach allows us to keep down the maintenance overhead of REST framework, so that the focus can be on continued stability and great documentation.
Some tips on good issue reporting:
* When describing issues try to phrase your ticket in terms of the *behavior* you think needs changing rather than the *code* you think need changing.
* Search the issue list first for related items, and make sure you're running the latest version of REST framework before reporting an issue.
* If reporting a bug, then try to include a pull request with a failing test case. This will help us quickly identify if there is a valid issue, and make sure that it gets fixed more quickly if there is one.
* Feature requests will often be closed with a recommendation that they be implemented outside of the core REST framework library. Keeping new feature requests implemented as third party libraries allows us to keep down the maintenance overhead of REST framework, so that the focus can be on continued stability, bugfixes, and great documentation.
* Closing an issue doesn't necessarily mean the end of a discussion. If you believe your issue has been closed incorrectly, explain why and we'll consider if it needs to be reopened.
## Triaging issues
Getting involved in triaging incoming issues is a good way to start contributing. Every single ticket that comes into the ticket tracker needs to be reviewed in order to determine what the next steps should be. Anyone can help out with this, you just need to be willing to
* Read through the ticket - does it make sense, is it missing any context that would help explain it better?
* Is the ticket reported in the correct place, would it be better suited as a discussion on the discussion group?
* If the ticket is a bug report, can you reproduce it? Are you able to write a failing test case that demonstrates the issue and that can be submitted as a pull request?
* If the ticket is a feature request, do you agree with it, and could the feature request instead be implemented as a third party package?
* If a ticket hasn't had much activity and it addresses something you need, then comment on the ticket and try to find out what's needed to get it moving again.
# Development # Development
@ -54,20 +39,28 @@ To start developing on Django REST framework, first create a Fork from the
Then clone your fork. The clone command will look like this, with your GitHub Then clone your fork. The clone command will look like this, with your GitHub
username instead of YOUR-USERNAME: username instead of YOUR-USERNAME:
git clone https://github.com/YOUR-USERNAME/Spoon-Knife git clone https://github.com/YOUR-USERNAME/django-rest-framework
See GitHub's [_Fork a Repo_][how-to-fork] Guide for more help. See GitHub's [_Fork a Repo_][how-to-fork] Guide for more help.
Changes should broadly follow the [PEP 8][pep-8] style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles. Changes should broadly follow the [PEP 8][pep-8] style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles.
You can check your contributions against these conventions each time you commit using the [pre-commit](https://pre-commit.com/) hooks, which we also run on CI.
To set them up, first ensure you have the pre-commit tool installed, for example:
python -m pip install pre-commit
Then run:
pre-commit install
## Testing ## Testing
To run the tests, clone the repository, and then: To run the tests, clone the repository, and then:
# Setup the virtual environment # Setup the virtual environment
virtualenv env python3 -m venv env
source env/bin/activate source env/bin/activate
pip install django pip install -e .
pip install -r requirements.txt pip install -r requirements.txt
# Run the tests # Run the tests
@ -79,18 +72,6 @@ Run using a more concise output style.
./runtests.py -q ./runtests.py -q
Run the tests using a more concise output style, no coverage, no flake8.
./runtests.py --fast
Don't run the flake8 code linting.
./runtests.py --nolint
Only run the flake8 code linting, don't run the tests.
./runtests.py --lintonly
Run the tests for a given test case. Run the tests for a given test case.
./runtests.py MyTestCase ./runtests.py MyTestCase
@ -121,13 +102,13 @@ It's also useful to remember that if you have an outstanding pull request then p
GitHub's documentation for working on pull requests is [available here][pull-requests]. GitHub's documentation for working on pull requests is [available here][pull-requests].
Always run the tests before submitting pull requests, and ideally run `tox` in order to check that your modifications are compatible with both Python 2 and Python 3, and that they run properly on all supported versions of Django. Always run the tests before submitting pull requests, and ideally run `tox` in order to check that your modifications are compatible on all supported versions of Python and Django.
Once you've made a pull request take a look at the Travis build status in the GitHub interface and make sure the tests are running as you'd expect. Once you've made a pull request take a look at the build status in the GitHub interface and make sure the tests are running as you'd expect.
![Travis status][travis-status] ![Build status][build-status]
*Above: Travis build notifications* *Above: build notifications*
## Managing compatibility issues ## Managing compatibility issues
@ -208,9 +189,8 @@ If you want to draw attention to a note or warning, use a pair of enclosing line
[code-of-conduct]: https://www.djangoproject.com/conduct/ [code-of-conduct]: https://www.djangoproject.com/conduct/
[google-group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework [google-group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework
[so-filter]: https://stackexchange.com/filters/66475/rest-framework [so-filter]: https://stackexchange.com/filters/66475/rest-framework
[issues]: https://github.com/encode/django-rest-framework/issues?state=open
[pep-8]: https://www.python.org/dev/peps/pep-0008/ [pep-8]: https://www.python.org/dev/peps/pep-0008/
[travis-status]: ../img/travis-status.png [build-status]: ../img/build-status.png
[pull-requests]: https://help.github.com/articles/using-pull-requests [pull-requests]: https://help.github.com/articles/using-pull-requests
[tox]: https://tox.readthedocs.io/en/latest/ [tox]: https://tox.readthedocs.io/en/latest/
[markdown]: https://daringfireball.net/projects/markdown/basics [markdown]: https://daringfireball.net/projects/markdown/basics

View File

@ -114,7 +114,7 @@ If you use REST framework commercially we strongly encourage you to invest in it
Signing up for a paid plan will: Signing up for a paid plan will:
* Directly contribute to faster releases, more features, and higher quality software. * Directly contribute to faster releases, more features, and higher quality software.
* Allow more time to be invested in documentation, issue triage, and community support. * Allow more time to be invested in keeping the package up to date.
* Safeguard the future development of REST framework. * Safeguard the future development of REST framework.
REST framework continues to be open-source and permissively licensed, but we firmly believe it is in the commercial best-interest for users of the project to invest in its ongoing development. REST framework continues to be open-source and permissively licensed, but we firmly believe it is in the commercial best-interest for users of the project to invest in its ongoing development.
@ -123,9 +123,10 @@ REST framework continues to be open-source and permissively licensed, but we fir
## What funding has enabled so far ## What funding has enabled so far
* The [3.4](http://www.django-rest-framework.org/topics/3.4-announcement/) and [3.5](http://www.django-rest-framework.org/topics/3.5-announcement/) releases, including schema generation for both Swagger and RAML, a Python client library, a Command Line client, and addressing of a large number of outstanding issues. * The [3.4](https://www.django-rest-framework.org/community/3.4-announcement/) and [3.5](https://www.django-rest-framework.org/community/3.5-announcement/) releases, including schema generation for both Swagger and RAML, a Python client library, a Command Line client, and addressing of a large number of outstanding issues.
* The [3.6](http://www.django-rest-framework.org/topics/3.6-announcement/) release, including JavaScript client library, and API documentation, complete with auto-generated code samples. * The [3.6](https://www.django-rest-framework.org/community/3.6-announcement/) release, including JavaScript client library, and API documentation, complete with auto-generated code samples.
* The recent [3.7 release](http://www.django-rest-framework.org/topics/3.7-announcement/), made possible due to our collaborative funding model, focuses on improvements to schema generation and the interactive API documentation. * The [3.7 release](https://www.django-rest-framework.org/community/3.7-announcement/), made possible due to our collaborative funding model, focuses on improvements to schema generation and the interactive API documentation.
* The recent [3.8 release](https://www.django-rest-framework.org/community/3.8-announcement/).
* Tom Christie, the creator of Django REST framework, working on the project full-time. * Tom Christie, the creator of Django REST framework, working on the project full-time.
* Around 80-90 issues and pull requests closed per month since Tom Christie started working on the project full-time. * Around 80-90 issues and pull requests closed per month since Tom Christie started working on the project full-time.
* A community & operations manager position part-time for 4 months, helping mature the business and grow sponsorship. * A community & operations manager position part-time for 4 months, helping mature the business and grow sponsorship.
@ -133,18 +134,6 @@ REST framework continues to be open-source and permissively licensed, but we fir
--- ---
## What future funding will enable
* Realtime API support, using WebSockets. This will consist of documentation and support for using REST framework together with Django Channels, plus integrating WebSocket support into the client libraries.
* Better authentication defaults, possibly bringing JWT & CORs support into the core package.
* Securing the community & operations manager position long-term.
* Opening up and securing a part-time position to focus on ticket triage and resolution.
* Paying for development time on building API client libraries in a range of programming languages. These would be integrated directly into the upcoming API documentation.
Sign up for a paid plan today, and help ensure that REST framework becomes a sustainable, full-time funded project.
---
## What our sponsors and users say ## What our sponsors and users say
> As a developer, Django REST framework feels like an obvious and natural extension to all the great things that make up Django and it's community. Getting started is easy while providing simple abstractions which makes it flexible and customizable. Contributing and supporting Django REST framework helps ensure its future and one way or another it also helps Django, and the Python ecosystem. > As a developer, Django REST framework feels like an obvious and natural extension to all the great things that make up Django and it's community. Getting started is easy while providing simple abstractions which makes it flexible and customizable. Contributing and supporting Django REST framework helps ensure its future and one way or another it also helps Django, and the Python ecosystem.
@ -153,17 +142,19 @@ Sign up for a paid plan today, and help ensure that REST framework becomes a sus
&nbsp; &nbsp;
> The number one feature of the Python programming language is its community. Such a community is only possible because of the Open Source nature of the language and all the culture that comes from it. Building great Open Source projects require great minds. Given that, we at Vinta are not only proud to sponsor the team behind DRF but we also recognize the ROI that comes from it. > The number one feature of the Python programming language is its community. Such a community is only possible because of the Open Source nature of the language and all the culture that comes from it. Building great Open Source projects require great minds. Given that, we at Vinta are not only proud to sponsor the team behind DRF but we also recognize the ROI that comes from it.
> >
> &mdash; Filipe Ximenes, Vinta Software > &mdash; Filipe Ximenes, Vinta Software
&nbsp; &nbsp;
> It's really awesome that this project continues to endure. The code base is top notch and the maintainers are committed to the highest level of quality. > It's really awesome that this project continues to endure. The code base is top notch and the maintainers are committed to the highest level of quality.
DRF is one of the core reasons why Django is top choice among web frameworks today. In my opinion, it sets the standard for rest frameworks for the development community at large. DRF is one of the core reasons why Django is top choice among web frameworks today. In my opinion, it sets the standard for rest frameworks for the development community at large.
> >
> &mdash; Andrew Conti, Django REST framework user > &mdash; Andrew Conti, Django REST framework user
Sign up for a paid plan today, and help ensure that REST framework becomes a sustainable, full-time funded project.
--- ---
## Individual plan ## Individual plan
@ -173,23 +164,23 @@ This subscription is recommended for individuals with an interest in seeing REST
If you are using REST framework as a full-time employee, consider recommending that your company takes out a [corporate&nbsp;plan](#corporate-plans). If you are using REST framework as a full-time employee, consider recommending that your company takes out a [corporate&nbsp;plan](#corporate-plans).
<div class="pricing"> <div class="pricing">
<div class="span4"> <div class="span4">
<div class="chart first"> <div class="chart first">
<div class="quantity"> <div class="quantity">
<span class="dollar">{{ symbol }}</span> <span class="dollar">{{ symbol }}</span>
<span class="price">{{ rates.personal1 }}</span> <span class="price">{{ rates.personal1 }}</span>
<span class="period">/month{% if vat %} +VAT{% endif %}</span> <span class="period">/month{% if vat %} +VAT{% endif %}</span>
</div> </div>
<div class="plan-name">Individual</div> <div class="plan-name">Individual</div>
<div class="specs freelancer"> <div class="specs freelancer">
<div class="spec"> <div class="spec">
Support ongoing development Support ongoing development
</div> </div>
<div class="spec"> <div class="spec">
Credited on the site Credited on the site
</div> </div>
</div> </div>
<form class="signup" action="/signup/{{ currency }}-{{ rates.personal1 }}/" method="POST"> <form class="signup" action="/signup/{{ currency }}-{{ rates.personal1 }}/" method="POST">
<script <script
src="https://checkout.stripe.com/checkout.js" class="stripe-button" src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_public }}" data-key="{{ stripe_public }}"
@ -203,9 +194,9 @@ If you are using REST framework as a full-time employee, consider recommending t
data-panel-label='Sign up - {% verbatim %}{{amount}}{% endverbatim %}/mo'> data-panel-label='Sign up - {% verbatim %}{{amount}}{% endverbatim %}/mo'>
</script> </script>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<div style="clear: both; padding-top: 50px"></div> <div style="clear: both; padding-top: 50px"></div>
*Billing is monthly and you can cancel at any time.* *Billing is monthly and you can cancel at any time.*
@ -221,23 +212,23 @@ In exchange for funding you'll also receive advertising space on our site, allow
Our professional and premium plans also include **priority support**. At any time your engineers can escalate an issue or discussion group thread, and we'll ensure it gets a guaranteed response within the next working day. Our professional and premium plans also include **priority support**. At any time your engineers can escalate an issue or discussion group thread, and we'll ensure it gets a guaranteed response within the next working day.
<div class="pricing"> <div class="pricing">
<div class="span4"> <div class="span4">
<div class="chart first"> <div class="chart first">
<div class="quantity"> <div class="quantity">
<span class="dollar">{{ symbol }}</span> <span class="dollar">{{ symbol }}</span>
<span class="price">{{ rates.corporate1 }}</span> <span class="price">{{ rates.corporate1 }}</span>
<span class="period">/month{% if vat %} +VAT{% endif %}</span> <span class="period">/month{% if vat %} +VAT{% endif %}</span>
</div> </div>
<div class="plan-name">Basic</div> <div class="plan-name">Basic</div>
<div class="specs startup"> <div class="specs startup">
<div class="spec"> <div class="spec">
Support ongoing development Support ongoing development
</div> </div>
<div class="spec"> <div class="spec">
<span class="variable">Funding page</span> ad placement <span class="variable">Funding page</span> ad placement
</div> </div>
</div> </div>
<form class="signup" action="/signup/{{ currency }}-{{ rates.corporate1 }}/" method="POST"> <form class="signup" action="/signup/{{ currency }}-{{ rates.corporate1 }}/" method="POST">
<script <script
src="https://checkout.stripe.com/checkout.js" class="stripe-button" src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_public }}" data-key="{{ stripe_public }}"
@ -251,28 +242,28 @@ Our professional and premium plans also include **priority support**. At any tim
data-panel-label='Sign up - {% verbatim %}{{amount}}{% endverbatim %}/mo'> data-panel-label='Sign up - {% verbatim %}{{amount}}{% endverbatim %}/mo'>
</script> </script>
</form> </form>
</div> </div>
</div> </div>
<div class="span4"> <div class="span4">
<div class="chart"> <div class="chart">
<div class="quantity"> <div class="quantity">
<span class="dollar">{{ symbol }}</span> <span class="dollar">{{ symbol }}</span>
<span class="price">{{ rates.corporate2 }}</span> <span class="price">{{ rates.corporate2 }}</span>
<span class="period">/month{% if vat %} +VAT{% endif %}</span> <span class="period">/month{% if vat %} +VAT{% endif %}</span>
</div> </div>
<div class="plan-name">Professional</div> <div class="plan-name">Professional</div>
<div class="specs"> <div class="specs">
<div class="spec"> <div class="spec">
Support ongoing development Support ongoing development
</div> </div>
<div class="spec"> <div class="spec">
<span class="variable">Sidebar</span> ad placement <span class="variable">Sidebar</span> ad placement
</div> </div>
<div class="spec"> <div class="spec">
<span class="variable">Priority support</span> for your engineers <span class="variable">Priority support</span> for your engineers
</div> </div>
</div> </div>
<form class="signup" action="/signup/{{ currency }}-{{ rates.corporate2 }}/" method="POST"> <form class="signup" action="/signup/{{ currency }}-{{ rates.corporate2 }}/" method="POST">
<script <script
src="https://checkout.stripe.com/checkout.js" class="stripe-button" src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_public }}" data-key="{{ stripe_public }}"
@ -286,31 +277,31 @@ Our professional and premium plans also include **priority support**. At any tim
data-panel-label='Sign up - {% verbatim %}{{amount}}{% endverbatim %}/mo'> data-panel-label='Sign up - {% verbatim %}{{amount}}{% endverbatim %}/mo'>
</script> </script>
</form> </form>
</div> </div>
</div> </div>
<div class="span4"> <div class="span4">
<div class="chart last"> <div class="chart last">
<div class="quantity"> <div class="quantity">
<span class="dollar">{{ symbol }}</span> <span class="dollar">{{ symbol }}</span>
<span class="price">{{ rates.corporate3 }}</span> <span class="price">{{ rates.corporate3 }}</span>
<span class="period">/month{% if vat %} +VAT{% endif %}</span> <span class="period">/month{% if vat %} +VAT{% endif %}</span>
</div> </div>
<div class="plan-name">Premium</div> <div class="plan-name">Premium</div>
<div class="specs"> <div class="specs">
<div class="spec"> <div class="spec">
Support ongoing development Support ongoing development
</div> </div>
<div class="spec"> <div class="spec">
<span class="variable">Homepage</span> ad placement <span class="variable">Homepage</span> ad placement
</div> </div>
<div class="spec"> <div class="spec">
<span class="variable">Sidebar</span> ad placement <span class="variable">Sidebar</span> ad placement
</div> </div>
<div class="spec"> <div class="spec">
<span class="variable">Priority support</span> for your engineers <span class="variable">Priority support</span> for your engineers
</div> </div>
</div> </div>
<form class="signup" action="/signup/{{ currency }}-{{ rates.corporate3 }}/" method="POST"> <form class="signup" action="/signup/{{ currency }}-{{ rates.corporate3 }}/" method="POST">
<script <script
src="https://checkout.stripe.com/checkout.js" class="stripe-button" src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ stripe_public }}" data-key="{{ stripe_public }}"
@ -324,9 +315,9 @@ Our professional and premium plans also include **priority support**. At any tim
data-panel-label='Sign up - {% verbatim %}{{amount}}{% endverbatim %}/mo'> data-panel-label='Sign up - {% verbatim %}{{amount}}{% endverbatim %}/mo'>
</script> </script>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
<div style="clear: both; padding-top: 50px"></div> <div style="clear: both; padding-top: 50px"></div>
@ -340,27 +331,27 @@ For further enquires please contact <a href=mailto:funding@django-rest-framework
## Accountability ## Accountability
In an effort to keep the project as transparent as possible, we are releasing [monthly progress reports](http://www.encode.io/reports/february-2018) and regularly include financial reports and cost breakdowns. In an effort to keep the project as transparent as possible, we are releasing [monthly progress reports](https://www.encode.io/reports/march-2018/) and regularly include financial reports and cost breakdowns.
<!-- Begin MailChimp Signup Form --> <!-- Begin MailChimp Signup Form -->
<link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css"> <link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">
<style type="text/css"> <style type="text/css">
#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; } #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
/* Add your own MailChimp form style overrides in your site stylesheet or in this style block. /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
</style> </style>
<div id="mc_embed_signup"> <div id="mc_embed_signup">
<form action="//encode.us13.list-manage.com/subscribe/post?u=b6b66bb5e4c7cb484a85c8dd7&amp;id=e382ef68ef" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate> <form action="//encode.us13.list-manage.com/subscribe/post?u=b6b66bb5e4c7cb484a85c8dd7&amp;id=e382ef68ef" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
<div id="mc_embed_signup_scroll"> <div id="mc_embed_signup_scroll">
<h2>Stay up to date, with our monthly progress reports...</h2> <h2>Stay up to date, with our monthly progress reports...</h2>
<div class="mc-field-group"> <div class="mc-field-group">
<label for="mce-EMAIL">Email Address </label> <label for="mce-EMAIL">Email Address </label>
<input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL"> <input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
</div> </div>
<div id="mce-responses" class="clear"> <div id="mce-responses" class="clear">
<div class="response" id="mce-error-response" style="display:none"></div> <div class="response" id="mce-error-response" style="display:none"></div>
<div class="response" id="mce-success-response" style="display:none"></div> <div class="response" id="mce-success-response" style="display:none"></div>
</div> <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--> </div> <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
<div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_b6b66bb5e4c7cb484a85c8dd7_e382ef68ef" tabindex="-1" value=""></div> <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_b6b66bb5e4c7cb484a85c8dd7_e382ef68ef" tabindex="-1" value=""></div>
<div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div> <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
</div> </div>

View File

@ -7,16 +7,17 @@ Looking for a new Django REST Framework related role? On this site we provide a
* [https://www.djangoproject.com/community/jobs/][djangoproject-website] * [https://www.djangoproject.com/community/jobs/][djangoproject-website]
* [https://www.python.org/jobs/][python-org-jobs] * [https://www.python.org/jobs/][python-org-jobs]
* [https://django.on-remote.com][django-on-remote]
* [https://djangogigs.com][django-gigs-com] * [https://djangogigs.com][django-gigs-com]
* [https://djangojobs.net/jobs/][django-jobs-net] * [https://djangojobs.net/jobs/][django-jobs-net]
* [http://djangojobbers.com][django-jobbers-com] * [https://findwork.dev/django-rest-framework-jobs][findwork-dev]
* [https://www.indeed.com/q-Django-jobs.html][indeed-com] * [https://www.indeed.com/q-Django-jobs.html][indeed-com]
* [https://stackoverflow.com/jobs/developer-jobs-using-django][stackoverflow-com] * [https://stackoverflow.com/jobs/companies?tl=django][stackoverflow-com]
* [https://www.upwork.com/o/jobs/browse/skill/django-framework/][upwork-com] * [https://www.upwork.com/o/jobs/browse/skill/django-framework/][upwork-com]
* [https://www.technojobs.co.uk/django-jobs][technobjobs-co-uk] * [https://www.technojobs.co.uk/django-jobs][technobjobs-co-uk]
* [https://remoteok.io/remote-django-jobs][remoteok-io] * [https://remoteok.com/remote-django-jobs][remoteok-com]
* [https://www.remotepython.com/jobs/][remotepython-com] * [https://www.remotepython.com/jobs/][remotepython-com]
* [https://weworkcontract.com/python-contract-jobs][weworkcontract-com] * [https://www.pyjobs.com/][pyjobs-com]
Know of any other great resources for Django REST Framework jobs that are missing in our list? Please [submit a pull request][submit-pr] or [email us][anna-email]. Know of any other great resources for Django REST Framework jobs that are missing in our list? Please [submit a pull request][submit-pr] or [email us][anna-email].
@ -26,16 +27,17 @@ Wonder how else you can help? One of the best ways you can help Django REST Fram
[djangoproject-website]: https://www.djangoproject.com/community/jobs/ [djangoproject-website]: https://www.djangoproject.com/community/jobs/
[python-org-jobs]: https://www.python.org/jobs/ [python-org-jobs]: https://www.python.org/jobs/
[django-on-remote]: https://django.on-remote.com/
[django-gigs-com]: https://djangogigs.com [django-gigs-com]: https://djangogigs.com
[django-jobs-net]: https://djangojobs.net/jobs/ [django-jobs-net]: https://djangojobs.net/jobs/
[django-jobbers-com]: http://djangojobbers.com [findwork-dev]: https://findwork.dev/django-rest-framework-jobs
[indeed-com]: https://www.indeed.com/q-Django-jobs.html [indeed-com]: https://www.indeed.com/q-Django-jobs.html
[stackoverflow-com]: https://stackoverflow.com/jobs/developer-jobs-using-django [stackoverflow-com]: https://stackoverflow.com/jobs/companies?tl=django
[upwork-com]: https://www.upwork.com/o/jobs/browse/skill/django-framework/ [upwork-com]: https://www.upwork.com/o/jobs/browse/skill/django-framework/
[technobjobs-co-uk]: https://www.technojobs.co.uk/django-jobs [technobjobs-co-uk]: https://www.technojobs.co.uk/django-jobs
[remoteok-io]: https://remoteok.io/remote-django-jobs [remoteok-com]: https://remoteok.com/remote-django-jobs
[remotepython-com]: https://www.remotepython.com/jobs/ [remotepython-com]: https://www.remotepython.com/jobs/
[weworkcontract-com]: https://weworkcontract.com/python-contract-jobs [pyjobs-com]: https://www.pyjobs.com/
[drf-funding]: https://fund.django-rest-framework.org/topics/funding/ [drf-funding]: https://fund.django-rest-framework.org/topics/funding/
[submit-pr]: https://github.com/encode/django-rest-framework [submit-pr]: https://github.com/encode/django-rest-framework
[anna-email]: mailto:anna@django-rest-framework.org [anna-email]: mailto:anna@django-rest-framework.org

View File

@ -47,8 +47,8 @@ Our platinum sponsors have each made a hugely substantial contribution to the fu
</ul> </ul>
<ul class="sponsor platinum"> <ul class="sponsor platinum">
<li><a href="https://www.divio.ch/" rel="nofollow" style="background-image:url(../../img/sponsors/1-divio.png);">Divio</a></li> <li><a href="https://www.divio.com/" rel="nofollow" style="background-image:url(../../img/sponsors/1-divio.png);">Divio</a></li>
<li><a href="http://company.onlulu.com/en/" rel="nofollow" style="background-image:url(../../img/sponsors/1-lulu.png);">Lulu</a></li> <li><a href="https://onlulu.com" rel="nofollow" style="background-image:url(../../img/sponsors/1-lulu.png);">Lulu</a></li>
<li><a href="https://p.ota.to/" rel="nofollow" style="background-image:url(../../img/sponsors/1-potato.png);">Potato</a></li> <li><a href="https://p.ota.to/" rel="nofollow" style="background-image:url(../../img/sponsors/1-potato.png);">Potato</a></li>
<li><a href="http://www.wiredrive.com/" rel="nofollow" style="background-image:url(../../img/sponsors/1-wiredrive.png);">Wiredrive</a></li> <li><a href="http://www.wiredrive.com/" rel="nofollow" style="background-image:url(../../img/sponsors/1-wiredrive.png);">Wiredrive</a></li>
<li><a href="http://www.cyaninc.com/" rel="nofollow" style="background-image:url(../../img/sponsors/1-cyan.png);">Cyan</a></li> <li><a href="http://www.cyaninc.com/" rel="nofollow" style="background-image:url(../../img/sponsors/1-cyan.png);">Cyan</a></li>
@ -78,11 +78,11 @@ Our gold sponsors include companies large and small. Many thanks for their signi
<li><a href="https://mirusresearch.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-mirus_research.png);">Mirus Research</a></li> <li><a href="https://mirusresearch.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-mirus_research.png);">Mirus Research</a></li>
<li><a href="https://hipolabs.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-hipo.png);">Hipo</a></li> <li><a href="https://hipolabs.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-hipo.png);">Hipo</a></li>
<li><a href="https://www.byte.nl/" rel="nofollow" style="background-image:url(../../img/sponsors/2-byte.png);">Byte</a></li> <li><a href="https://www.byte.nl/" rel="nofollow" style="background-image:url(../../img/sponsors/2-byte.png);">Byte</a></li>
<li><a href="http://lightningkite.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-lightning_kite.png);">Lightning Kite</a></li> <li><a href="https://www.lightningkite.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-lightning_kite.png);">Lightning Kite</a></li>
<li><a href="https://opbeat.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-opbeat.png);">Opbeat</a></li> <li><a href="https://opbeat.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-opbeat.png);">Opbeat</a></li>
<li><a href="https://koordinates.com" rel="nofollow" style="background-image:url(../../img/sponsors/2-koordinates.png);">Koordinates</a></li> <li><a href="https://koordinates.com" rel="nofollow" style="background-image:url(../../img/sponsors/2-koordinates.png);">Koordinates</a></li>
<li><a href="http://pulsecode.ca" rel="nofollow" style="background-image:url(../../img/sponsors/2-pulsecode.png);">Pulsecode Inc.</a></li> <li><a rel="nofollow" style="background-image:url(../../img/sponsors/2-pulsecode.png);">Pulsecode Inc.</a></li>
<li><a href="http://singinghorsestudio.com" rel="nofollow" style="background-image:url(../../img/sponsors/2-singing-horse.png);">Singing Horse Studio Ltd.</a></li> <li><a rel="nofollow" style="background-image:url(../../img/sponsors/2-singing-horse.png);">Singing Horse Studio Ltd.</a></li>
<li><a href="https://www.heroku.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-heroku.png);">Heroku</a></li> <li><a href="https://www.heroku.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-heroku.png);">Heroku</a></li>
<li><a href="https://www.rheinwerk-verlag.de/" rel="nofollow" style="background-image:url(../../img/sponsors/2-rheinwerk_verlag.png);">Rheinwerk Verlag</a></li> <li><a href="https://www.rheinwerk-verlag.de/" rel="nofollow" style="background-image:url(../../img/sponsors/2-rheinwerk_verlag.png);">Rheinwerk Verlag</a></li>
<li><a href="https://www.securitycompass.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-security_compass.png);">Security Compass</a></li> <li><a href="https://www.securitycompass.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-security_compass.png);">Security Compass</a></li>
@ -90,9 +90,9 @@ Our gold sponsors include companies large and small. Many thanks for their signi
<li><a href="http://www.hipflaskapp.com" rel="nofollow" style="background-image:url(../../img/sponsors/2-hipflask.png);">Hipflask</a></li> <li><a href="http://www.hipflaskapp.com" rel="nofollow" style="background-image:url(../../img/sponsors/2-hipflask.png);">Hipflask</a></li>
<li><a href="http://www.crate.io/" rel="nofollow" style="background-image:url(../../img/sponsors/2-crate.png);">Crate</a></li> <li><a href="http://www.crate.io/" rel="nofollow" style="background-image:url(../../img/sponsors/2-crate.png);">Crate</a></li>
<li><a href="http://crypticocorp.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-cryptico.png);">Cryptico Corp</a></li> <li><a href="http://crypticocorp.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-cryptico.png);">Cryptico Corp</a></li>
<li><a href="http://www.nexthub.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-nexthub.png);">NextHub</a></li> <li><a rel="nofollow" style="background-image:url(../../img/sponsors/2-nexthub.png);">NextHub</a></li>
<li><a href="https://www.compile.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-compile.png);">Compile</a></li> <li><a href="https://www.compile.com/" rel="nofollow" style="background-image:url(../../img/sponsors/2-compile.png);">Compile</a></li>
<li><a href="http://wusawork.org" rel="nofollow" style="background-image:url(../../img/sponsors/2-wusawork.png);">WusaWork</a></li> <li><a rel="nofollow" style="background-image:url(../../img/sponsors/2-wusawork.png);">WusaWork</a></li>
<li><a href="http://envisionlinux.org/blog" rel="nofollow">Envision Linux</a></li> <li><a href="http://envisionlinux.org/blog" rel="nofollow">Envision Linux</a></li>
</ul> </ul>
@ -116,7 +116,7 @@ The serious financial contribution that our silver sponsors have made is very mu
<li><a href="https://garfo.io/" rel="nofollow" style="background-image:url(../../img/sponsors/3-garfo.png);">Garfo</a></li> <li><a href="https://garfo.io/" rel="nofollow" style="background-image:url(../../img/sponsors/3-garfo.png);">Garfo</a></li>
<li><a href="https://goshippo.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-shippo.png);">Shippo</a></li> <li><a href="https://goshippo.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-shippo.png);">Shippo</a></li>
<li><a href="http://www.gizmag.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-gizmag.png);">Gizmag</a></li> <li><a href="http://www.gizmag.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-gizmag.png);">Gizmag</a></li>
<li><a href="http://www.tivix.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-tivix.png);">Tivix</a></li> <li><a href="https://www.tivix.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-tivix.png);">Tivix</a></li>
<li><a href="https://www.safaribooksonline.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-safari.png);">Safari</a></li> <li><a href="https://www.safaribooksonline.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-safari.png);">Safari</a></li>
<li><a href="http://brightloop.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-brightloop.png);">Bright Loop</a></li> <li><a href="http://brightloop.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-brightloop.png);">Bright Loop</a></li>
<li><a href="http://www.aba-systems.com.au/" rel="nofollow" style="background-image:url(../../img/sponsors/3-aba.png);">ABA Systems</a></li> <li><a href="http://www.aba-systems.com.au/" rel="nofollow" style="background-image:url(../../img/sponsors/3-aba.png);">ABA Systems</a></li>
@ -131,7 +131,7 @@ The serious financial contribution that our silver sponsors have made is very mu
<li><a href="https://fluxility.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-fluxility.png);">Fluxility</a></li> <li><a href="https://fluxility.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-fluxility.png);">Fluxility</a></li>
<li><a href="https://teonite.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-teonite.png);">Teonite</a></li> <li><a href="https://teonite.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-teonite.png);">Teonite</a></li>
<li><a href="https://trackmaven.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-trackmaven.png);">TrackMaven</a></li> <li><a href="https://trackmaven.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-trackmaven.png);">TrackMaven</a></li>
<li><a href="http://www.phurba.net/" rel="nofollow" style="background-image:url(../../img/sponsors/3-phurba.png);">Phurba</a></li> <li><a href="https://www.phurba.net/" rel="nofollow" style="background-image:url(../../img/sponsors/3-phurba.png);">Phurba</a></li>
<li><a href="https://www.nephila.it/it/" rel="nofollow" style="background-image:url(../../img/sponsors/3-nephila.png);">Nephila</a></li> <li><a href="https://www.nephila.it/it/" rel="nofollow" style="background-image:url(../../img/sponsors/3-nephila.png);">Nephila</a></li>
<li><a href="http://www.aditium.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-aditium.png);">Aditium</a></li> <li><a href="http://www.aditium.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-aditium.png);">Aditium</a></li>
<li><a href="https://www.eyesopen.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-openeye.png);">OpenEye Scientific Software</a></li> <li><a href="https://www.eyesopen.com/" rel="nofollow" style="background-image:url(../../img/sponsors/3-openeye.png);">OpenEye Scientific Software</a></li>

View File

@ -4,7 +4,7 @@ We have recently been [awarded a Mozilla grant](https://blog.mozilla.org/blog/20
Additionally, we will be building on the realtime support that Django Channels provides, supporting and documenting how to build realtime APIs with REST framework. Again, this will include supporting work in the associated client libraries, making it easier to build richly interactive applications. Additionally, we will be building on the realtime support that Django Channels provides, supporting and documenting how to build realtime APIs with REST framework. Again, this will include supporting work in the associated client libraries, making it easier to build richly interactive applications.
The [Core API](http://www.coreapi.org) project will provide the foundations for our client library support, and will allow us to support interaction using a wide range of schemas and hypermedia formats. It's worth noting that these client libraries won't be tightly coupled to solely REST framework APIs either, and will be able to interact with *any* API that exposes a supported schema or hypermedia format. The [Core API](https://www.coreapi.org/) project will provide the foundations for our client library support, and will allow us to support interaction using a wide range of schemas and hypermedia formats. It's worth noting that these client libraries won't be tightly coupled to solely REST framework APIs either, and will be able to interact with *any* API that exposes a supported schema or hypermedia format.
Specifically, the work includes: Specifically, the work includes:
@ -34,7 +34,7 @@ In order to ensure that I can be fully focused on trying to secure a sustainable
& well-funded open source business I will be leaving my current role at [DabApps](https://www.dabapps.com/) & well-funded open source business I will be leaving my current role at [DabApps](https://www.dabapps.com/)
at the end of May 2016. at the end of May 2016.
I have formed a UK limited company, [Encode](http://www.encode.io), which will I have formed a UK limited company, [Encode](https://www.encode.io/), which will
act as the business entity behind REST framework. I will be issuing monthly reports act as the business entity behind REST framework. I will be issuing monthly reports
from Encode on progress both towards the Mozilla grant, and for development time from Encode on progress both towards the Mozilla grant, and for development time
funded via the [REST framework paid plans](funding.md). funded via the [REST framework paid plans](funding.md).
@ -42,22 +42,22 @@ funded via the [REST framework paid plans](funding.md).
<!-- Begin MailChimp Signup Form --> <!-- Begin MailChimp Signup Form -->
<link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css"> <link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">
<style type="text/css"> <style type="text/css">
#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; } #mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
/* Add your own MailChimp form style overrides in your site stylesheet or in this style block. /* Add your own MailChimp form style overrides in your site stylesheet or in this style block.
We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */ We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
</style> </style>
<div id="mc_embed_signup"> <div id="mc_embed_signup">
<form action="//encode.us13.list-manage.com/subscribe/post?u=b6b66bb5e4c7cb484a85c8dd7&amp;id=e382ef68ef" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate> <form action="//encode.us13.list-manage.com/subscribe/post?u=b6b66bb5e4c7cb484a85c8dd7&amp;id=e382ef68ef" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
<div id="mc_embed_signup_scroll"> <div id="mc_embed_signup_scroll">
<h2>Stay up to date, with our monthly progress reports...</h2> <h2>Stay up to date, with our monthly progress reports...</h2>
<div class="mc-field-group"> <div class="mc-field-group">
<label for="mce-EMAIL">Email Address </label> <label for="mce-EMAIL">Email Address </label>
<input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL"> <input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
</div> </div>
<div id="mce-responses" class="clear"> <div id="mce-responses" class="clear">
<div class="response" id="mce-error-response" style="display:none"></div> <div class="response" id="mce-error-response" style="display:none"></div>
<div class="response" id="mce-success-response" style="display:none"></div> <div class="response" id="mce-success-response" style="display:none"></div>
</div> <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups--> </div> <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
<div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_b6b66bb5e4c7cb484a85c8dd7_e382ef68ef" tabindex="-1" value=""></div> <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_b6b66bb5e4c7cb484a85c8dd7_e382ef68ef" tabindex="-1" value=""></div>
<div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div> <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
</div> </div>

View File

@ -13,55 +13,13 @@ The aim is to ensure that the project has a high
## Maintenance team ## Maintenance team
We have a quarterly maintenance cycle where new members may join the maintenance team. We currently cap the size of the team at 5 members, and may encourage folks to step out of the team for a cycle to allow new members to participate. [Participating actively in the REST framework project](contributing.md) **does not require being part of the maintenance team**. Almost every important part of issue triage and project improvement can be actively worked on regardless of your collaborator status on the repository.
#### Current team #### Composition
The [maintenance team for Q4 2015](https://github.com/encode/django-rest-framework/issues/2190): The composition of the maintenance team is handled by [@tomchristie](https://github.com/encode/). Team members will be added as collaborators to the repository.
* [@tomchristie](https://github.com/encode/) #### Responsibilities
* [@xordoquy](https://github.com/xordoquy/) (Release manager.)
* [@carltongibson](https://github.com/carltongibson/)
* [@kevin-brown](https://github.com/kevin-brown/)
* [@jpadilla](https://github.com/jpadilla/)
#### Maintenance cycles
Each maintenance cycle is initiated by an issue being opened with the `Process` label.
* To be considered for a maintainer role simply comment against the issue.
* Existing members must explicitly opt-in to the next cycle by check-marking their name.
* The final decision on the incoming team will be made by `@tomchristie`.
Members of the maintenance team will be added as collaborators to the repository.
The following template should be used for the description of the issue, and serves as the formal process for selecting the team.
This issue is for determining the maintenance team for the *** period.
Please see the [Project management](http://www.django-rest-framework.org/topics/project-management/) section of our documentation for more details.
---
#### Renewing existing members.
The following people are the current maintenance team. Please checkmark your name if you wish to continue to have write permission on the repository for the *** period.
- [ ] @***
- [ ] @***
- [ ] @***
- [ ] @***
- [ ] @***
---
#### New members.
If you wish to be considered for this or a future date, please comment against this or subsequent issues.
To modify this process for future maintenance cycles make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation.
#### Responsibilities of team members
Team members have the following responsibilities. Team members have the following responsibilities.
@ -76,18 +34,13 @@ Further notes for maintainers:
* Code changes should come in the form of a pull request - do not push directly to master. * Code changes should come in the form of a pull request - do not push directly to master.
* Maintainers should typically not merge their own pull requests. * Maintainers should typically not merge their own pull requests.
* Each issue/pull request should have exactly one label once triaged. * Each issue/pull request should have exactly one label once triaged.
* Search for un-triaged issues with [is:open no:label][un-triaged].
It should be noted that participating actively in the REST framework project clearly **does not require being part of the maintenance team**. Almost every import part of issue triage and project improvement can be actively worked on regardless of your collaborator status on the repository.
--- ---
## Release process ## Release process
The release manager is selected on every quarterly maintenance cycle. * The release manager is selected by `@tomchristie`.
* The release manager will then have the maintainer role added to PyPI package.
* The manager should be selected by `@tomchristie`.
* The manager will then have the maintainer role added to PyPI package.
* The previous manager will then have the maintainer role removed from the PyPI package. * The previous manager will then have the maintainer role removed from the PyPI package.
Our PyPI releases will be handled by either the current release manager, or by `@tomchristie`. Every release should have an open issue tagged with the `Release` label and marked against the appropriate milestone. Our PyPI releases will be handled by either the current release manager, or by `@tomchristie`. Every release should have an open issue tagged with the `Release` label and marked against the appropriate milestone.
@ -99,7 +52,7 @@ The following template should be used for the description of the issue, and serv
During development cycle: During development cycle:
- [ ] Upload the new content to be translated to [transifex](http://www.django-rest-framework.org/topics/project-management/#translations). - [ ] Upload the new content to be translated to [transifex](https://www.django-rest-framework.org/topics/project-management/#translations).
Checklist: Checklist:
@ -110,8 +63,11 @@ The following template should be used for the description of the issue, and serv
- [ ] `setup.py` Python & Django version trove classifiers - [ ] `setup.py` Python & Django version trove classifiers
- [ ] `README` Python & Django versions - [ ] `README` Python & Django versions
- [ ] `docs` Python & Django versions - [ ] `docs` Python & Django versions
- [ ] Update the translations from [transifex](http://www.django-rest-framework.org/topics/project-management/#translations). - [ ] Update the translations from [transifex](https://www.django-rest-framework.org/topics/project-management/#translations).
- [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/encode/django-rest-framework/blob/master/rest_framework/__init__.py). - [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/encode/django-rest-framework/blob/master/rest_framework/__init__.py).
- [ ] Ensure documentation validates
- Build and serve docs `mkdocs serve`
- Validate links `pylinkvalidate.py -P http://127.0.0.1:8000`
- [ ] Confirm with @tomchristie that release is finalized and ready to go. - [ ] Confirm with @tomchristie that release is finalized and ready to go.
- [ ] Ensure that release date is included in pull request. - [ ] Ensure that release date is included in pull request.
- [ ] Merge the release pull request. - [ ] Merge the release pull request.
@ -122,7 +78,7 @@ The following template should be used for the description of the issue, and serv
- [ ] Make a release announcement on twitter. - [ ] Make a release announcement on twitter.
- [ ] Close the milestone on GitHub. - [ ] Close the milestone on GitHub.
To modify this process for future releases make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation. To modify this process for future releases make a pull request to the [project management](https://www.django-rest-framework.org/topics/project-management/) documentation.
When pushing the release to PyPI ensure that your environment has been installed from our development `requirement.txt`, so that documentation and PyPI installs are consistently being built against a pinned set of packages. When pushing the release to PyPI ensure that your environment has been installed from our development `requirement.txt`, so that documentation and PyPI installs are consistently being built against a pinned set of packages.
@ -152,7 +108,7 @@ When any user visible strings are changed, they should be uploaded to Transifex
# 1. Update the source django.po file, which is the US English version. # 1. Update the source django.po file, which is the US English version.
cd rest_framework cd rest_framework
django-admin.py makemessages -l en_US django-admin makemessages -l en_US
# 2. Push the source django.po file to Transifex. # 2. Push the source django.po file to Transifex.
cd .. cd ..
tx push -s tx push -s
@ -173,7 +129,7 @@ When a translator has finished translating their work needs to be downloaded fro
tx pull -a --minimum-perc 10 tx pull -a --minimum-perc 10
cd rest_framework cd rest_framework
# 4. Compile the binary .mo files for all supported languages. # 4. Compile the binary .mo files for all supported languages.
django-admin.py compilemessages django-admin compilemessages
--- ---
@ -195,17 +151,12 @@ If `@tomchristie` ceases to participate in the project then `@j4mie` has respons
The following issues still need to be addressed: The following issues still need to be addressed:
* [Consider moving the repo into a proper GitHub organization][github-org]. * Ensure `@j4mie` has back-up access to the `django-rest-framework.org` domain setup and admin.
* Ensure `@jamie` has back-up access to the `django-rest-framework.org` domain setup and admin.
* Document ownership of the [live example][sandbox] API.
* Document ownership of the [mailing list][mailing-list] and IRC channel. * Document ownership of the [mailing list][mailing-list] and IRC channel.
* Document ownership and management of the security mailing list. * Document ownership and management of the security mailing list.
[bus-factor]: https://en.wikipedia.org/wiki/Bus_factor [bus-factor]: https://en.wikipedia.org/wiki/Bus_factor
[un-triaged]: https://github.com/encode/django-rest-framework/issues?q=is%3Aopen+no%3Alabel
[transifex-project]: https://www.transifex.com/projects/p/django-rest-framework/ [transifex-project]: https://www.transifex.com/projects/p/django-rest-framework/
[transifex-client]: https://pypi.python.org/pypi/transifex-client [transifex-client]: https://pypi.org/project/transifex-client/
[translation-memory]: http://docs.transifex.com/guides/tm#let-tm-automatically-populate-translations [translation-memory]: http://docs.transifex.com/guides/tm#let-tm-automatically-populate-translations
[github-org]: https://github.com/encode/django-rest-framework/issues/2162
[sandbox]: https://restframework.herokuapp.com/
[mailing-list]: https://groups.google.com/forum/#!forum/django-rest-framework [mailing-list]: https://groups.google.com/forum/#!forum/django-rest-framework

View File

@ -1,16 +1,14 @@
# Release Notes # Release Notes
> Release Early, Release Often
>
> &mdash; Eric S. Raymond, [The Cathedral and the Bazaar][cite].
## Versioning ## Versioning
Minor version numbers (0.0.x) are used for changes that are API compatible. You should be able to upgrade between minor point releases without any other code changes. - **Minor** version numbers (0.0.x) are used for changes that are API compatible. You should be able to upgrade between minor point releases without any other code changes.
Medium version numbers (0.x.0) may include API changes, in line with the [deprecation policy][deprecation-policy]. You should read the release notes carefully before upgrading between medium point releases. - **Medium** version numbers (0.x.0) may include API changes, in line with the [deprecation policy][deprecation-policy]. You should read the release notes carefully before upgrading between medium point releases.
Major version numbers (x.0.0) are reserved for substantial project milestones. - **Major** version numbers (x.0.0) are reserved for substantial project milestones.
As REST Framework is considered feature-complete, most releases are expected to be minor releases.
## Deprecation policy ## Deprecation policy
@ -18,9 +16,9 @@ REST framework releases follow a formal deprecation policy, which is in line wit
The timeline for deprecation of a feature present in version 1.0 would work as follows: The timeline for deprecation of a feature present in version 1.0 would work as follows:
* Version 1.1 would remain **fully backwards compatible** with 1.0, but would raise `PendingDeprecationWarning` warnings if you use the feature that are due to be deprecated. These warnings are **silent by default**, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make. * Version 1.1 would remain **fully backwards compatible** with 1.0, but would raise `RemovedInDRF13Warning` warnings, subclassing `PendingDeprecationWarning`, if you use the feature that are due to be deprecated. These warnings are **silent by default**, but can be explicitly enabled when you're ready to start migrating any required changes. For example if you start running your tests using `python -Wd manage.py test`, you'll be warned of any API changes you need to make.
* Version 1.2 would escalate these warnings to `DeprecationWarning`, which is loud by default. * Version 1.2 would escalate these warnings to subclass `DeprecationWarning`, which is loud by default.
* Version 1.3 would remove the deprecated bits of API entirely. * Version 1.3 would remove the deprecated bits of API entirely.
@ -38,8 +36,523 @@ You can determine your currently installed version using `pip show`:
--- ---
## 3.16.x series
### 3.16.0
**Date**: 28th March 2025
This release is considered a significant release to improve upstream support with Django and Python. Some of these may change the behaviour of existing features and pre-existing behaviour. Specifically, some fixes were added to around the support of `UniqueConstraint` with nullable fields which will improve built-in serializer validation.
## Features
* Add official support for Django 5.1 and its new `LoginRequiredMiddleware` in [#9514](https://github.com/encode/django-rest-framework/pull/9514) and [#9657](https://github.com/encode/django-rest-framework/pull/9657)
* Add official Django 5.2a1 support in [#9634](https://github.com/encode/django-rest-framework/pull/9634)
* Add support for Python 3.13 in [#9527](https://github.com/encode/django-rest-framework/pull/9527) and [#9556](https://github.com/encode/django-rest-framework/pull/9556)
* Support Django 2.1+ test client JSON data automatically serialized in [#6511](https://github.com/encode/django-rest-framework/pull/6511) and fix a regression in [#9615](https://github.com/encode/django-rest-framework/pull/9615)
## Bug fixes
* Fix unique together validator to respect condition's fields from `UniqueConstraint` in [#9360](https://github.com/encode/django-rest-framework/pull/9360)
* Fix raising on nullable fields part of `UniqueConstraint` in [#9531](https://github.com/encode/django-rest-framework/pull/9531)
* Fix `unique_together` validation with source in [#9482](https://github.com/encode/django-rest-framework/pull/9482)
* Added protections to `AttributeError` raised within properties in [#9455](https://github.com/encode/django-rest-framework/pull/9455)
* Fix `get_template_context` to handle also lists in [#9467](https://github.com/encode/django-rest-framework/pull/9467)
* Fix "Converter is already registered" deprecation warning. in [#9512](https://github.com/encode/django-rest-framework/pull/9512)
* Fix noisy warning and accept integers as min/max values of `DecimalField` in [#9515](https://github.com/encode/django-rest-framework/pull/9515)
* Fix usages of `open()` in `setup.py` in [#9661](https://github.com/encode/django-rest-framework/pull/9661)
## Translations
* Add some missing Chinese translations in [#9505](https://github.com/encode/django-rest-framework/pull/9505)
* Fix spelling mistakes in Farsi language were corrected in [#9521](https://github.com/encode/django-rest-framework/pull/9521)
* Fixing and adding missing Brazilian Portuguese translations in [#9535](https://github.com/encode/django-rest-framework/pull/9535)
## Removals
* Remove support for Python 3.8 in [#9670](https://github.com/encode/django-rest-framework/pull/9670)
* Remove long deprecated code from request wrapper in [#9441](https://github.com/encode/django-rest-framework/pull/9441)
* Remove deprecated `AutoSchema._get_reference` method in [#9525](https://github.com/encode/django-rest-framework/pull/9525)
## Documentation and internal changes
* Provide tests for hashing of `OperandHolder` in [#9437](https://github.com/encode/django-rest-framework/pull/9437)
* Update documentation: Add `adrf` third party package in [#9198](https://github.com/encode/django-rest-framework/pull/9198)
* Update tutorials links in Community contributions docs in [#9476](https://github.com/encode/django-rest-framework/pull/9476)
* Fix usage of deprecated Django function in example from docs in [#9509](https://github.com/encode/django-rest-framework/pull/9509)
* Move path converter docs into a separate section in [#9524](https://github.com/encode/django-rest-framework/pull/9524)
* Add test covering update view without `queryset` attribute in [#9528](https://github.com/encode/django-rest-framework/pull/9528)
* Fix Transifex link in [#9541](https://github.com/encode/django-rest-framework/pull/9541)
* Fix example `httpie` call in docs in [#9543](https://github.com/encode/django-rest-framework/pull/9543)
* Fix example for serializer field with choices in docs in [#9563](https://github.com/encode/django-rest-framework/pull/9563)
* Remove extra `<>` in validators example in [#9590](https://github.com/encode/django-rest-framework/pull/9590)
* Update `strftime` link in the docs in [#9624](https://github.com/encode/django-rest-framework/pull/9624)
* Switch to codecov GHA in [#9618](https://github.com/encode/django-rest-framework/pull/9618)
* Add note regarding availability of the `action` attribute in 'Introspecting ViewSet actions' docs section in [#9633](https://github.com/encode/django-rest-framework/pull/9633)
* Improved description of allowed throttling rates in documentation in [#9640](https://github.com/encode/django-rest-framework/pull/9640)
* Add `rest-framework-gm2m-relations` package to the list of 3rd party libraries in [#9063](https://github.com/encode/django-rest-framework/pull/9063)
* Fix a number of typos in the test suite in the docs in [#9662](https://github.com/encode/django-rest-framework/pull/9662)
* Add `django-pyoidc` as a third party authentication library in [#9667](https://github.com/encode/django-rest-framework/pull/9667)
## New Contributors
* [`@maerteijn`](https://github.com/maerteijn) made their first contribution in [#9198](https://github.com/encode/django-rest-framework/pull/9198)
* [`@FraCata00`](https://github.com/FraCata00) made their first contribution in [#9444](https://github.com/encode/django-rest-framework/pull/9444)
* [`@AlvaroVega`](https://github.com/AlvaroVega) made their first contribution in [#9451](https://github.com/encode/django-rest-framework/pull/9451)
* [`@james`](https://github.com/james)-mchugh made their first contribution in [#9455](https://github.com/encode/django-rest-framework/pull/9455)
* [`@ifeanyidavid`](https://github.com/ifeanyidavid) made their first contribution in [#9479](https://github.com/encode/django-rest-framework/pull/9479)
* [`@p`](https://github.com/p)-schlickmann made their first contribution in [#9480](https://github.com/encode/django-rest-framework/pull/9480)
* [`@akkuman`](https://github.com/akkuman) made their first contribution in [#9505](https://github.com/encode/django-rest-framework/pull/9505)
* [`@rafaelgramoschi`](https://github.com/rafaelgramoschi) made their first contribution in [#9509](https://github.com/encode/django-rest-framework/pull/9509)
* [`@Sinaatkd`](https://github.com/Sinaatkd) made their first contribution in [#9521](https://github.com/encode/django-rest-framework/pull/9521)
* [`@gtkacz`](https://github.com/gtkacz) made their first contribution in [#9535](https://github.com/encode/django-rest-framework/pull/9535)
* [`@sliverc`](https://github.com/sliverc) made their first contribution in [#9556](https://github.com/encode/django-rest-framework/pull/9556)
* [`@gabrielromagnoli1987`](https://github.com/gabrielromagnoli1987) made their first contribution in [#9543](https://github.com/encode/django-rest-framework/pull/9543)
* [`@cheehong1030`](https://github.com/cheehong1030) made their first contribution in [#9563](https://github.com/encode/django-rest-framework/pull/9563)
* [`@amansharma612`](https://github.com/amansharma612) made their first contribution in [#9590](https://github.com/encode/django-rest-framework/pull/9590)
* [`@Gluroda`](https://github.com/Gluroda) made their first contribution in [#9616](https://github.com/encode/django-rest-framework/pull/9616)
* [`@deepakangadi`](https://github.com/deepakangadi) made their first contribution in [#9624](https://github.com/encode/django-rest-framework/pull/9624)
* [`@EXG1O`](https://github.com/EXG1O) made their first contribution in [#9633](https://github.com/encode/django-rest-framework/pull/9633)
* [`@decadenza`](https://github.com/decadenza) made their first contribution in [#9640](https://github.com/encode/django-rest-framework/pull/9640)
* [`@mojtabaakbari221b`](https://github.com/mojtabaakbari221b) made their first contribution in [#9063](https://github.com/encode/django-rest-framework/pull/9063)
* [`@mikemanger`](https://github.com/mikemanger) made their first contribution in [#9661](https://github.com/encode/django-rest-framework/pull/9661)
* [`@gbip`](https://github.com/gbip) made their first contribution in [#9667](https://github.com/encode/django-rest-framework/pull/9667)
**Full Changelog**: https://github.com/encode/django-rest-framework/compare/3.15.2...3.16.0
## 3.15.x series
### 3.15.2
**Date**: 14th June 2024
* Fix potential XSS vulnerability in browsable API. [#9435](https://github.com/encode/django-rest-framework/pull/9435)
* Revert "Ensure CursorPagination respects nulls in the ordering field". [#9381](https://github.com/encode/django-rest-framework/pull/9381)
* Use warnings rather than logging a warning for DecimalField. [#9367](https://github.com/encode/django-rest-framework/pull/9367)
* Remove unused code. [#9393](https://github.com/encode/django-rest-framework/pull/9393)
* Django < 4.2 and Python < 3.8 no longer supported. [#9393](https://github.com/encode/django-rest-framework/pull/9393)
### 3.15.1
Date: 22nd March 2024
* Fix `SearchFilter` handling of quoted and comma separated strings, when `.get_search_terms` is being called into by a custom class. See [[#9338](https://github.com/encode/django-rest-framework/issues/9338)]
* Revert number of 3.15.0 issues which included unintended side-effects. See [[#9331](https://github.com/encode/django-rest-framework/issues/9331)]
### 3.15.0
Date: 15th March 2024
* Django 5.0 and Python 3.12 support [[#9157](https://github.com/encode/django-rest-framework/pull/9157)]
* Use POST method instead of GET to perform logout in browsable API [[9208](https://github.com/encode/django-rest-framework/pull/9208)]
* Added jQuery 3.7.1 support & dropped previous version [[#9094](https://github.com/encode/django-rest-framework/pull/9094)]
* Use str as default path converter [[#9066](https://github.com/encode/django-rest-framework/pull/9066)]
* Document support for http.HTTPMethod in the @action decorator added in Python 3.11 [[#9067](https://github.com/encode/django-rest-framework/pull/9067)]
* Update exceptions.md [[#9071](https://github.com/encode/django-rest-framework/pull/9071)]
* Partial serializer should not have required fields [[#7563](https://github.com/encode/django-rest-framework/pull/7563)]
* Propagate 'default' from model field to serializer field. [[#9030](https://github.com/encode/django-rest-framework/pull/9030)]
* Allow to override child.run_validation call in ListSerializer [[#8035](https://github.com/encode/django-rest-framework/pull/8035)]
* Align SearchFilter behaviour to django.contrib.admin search [[#9017](https://github.com/encode/django-rest-framework/pull/9017)]
* Class name added to unknown field error [[#9019](https://github.com/encode/django-rest-framework/pull/9019)]
* Fix: Pagination response schemas. [[#9049](https://github.com/encode/django-rest-framework/pull/9049)]
* Fix choices in ChoiceField to support IntEnum [[#8955](https://github.com/encode/django-rest-framework/pull/8955)]
* Fix `SearchFilter` rendering search field with invalid value [[#9023](https://github.com/encode/django-rest-framework/pull/9023)]
* Fix OpenAPI Schema yaml rendering for `timedelta` [[#9007](https://github.com/encode/django-rest-framework/pull/9007)]
* Fix `NamespaceVersioning` ignoring `DEFAULT_VERSION` on non-None namespaces [[#7278](https://github.com/encode/django-rest-framework/pull/7278)]
* Added Deprecation Warnings for CoreAPI [[#7519](https://github.com/encode/django-rest-framework/pull/7519)]
* Removed usage of `field.choices` that triggered full table load [[#8950](https://github.com/encode/django-rest-framework/pull/8950)]
* Permit mixed casing of string values for `BooleanField` validation [[#8970](https://github.com/encode/django-rest-framework/pull/8970)]
* Fixes `BrowsableAPIRenderer` for usage with `ListSerializer`. [[#7530](https://github.com/encode/django-rest-framework/pull/7530)]
* Change semantic of `OR` of two permission classes [[#7522](https://github.com/encode/django-rest-framework/pull/7522)]
* Remove dependency on `pytz` [[#8984](https://github.com/encode/django-rest-framework/pull/8984)]
* Make set_value a method within `Serializer` [[#8001](https://github.com/encode/django-rest-framework/pull/8001)]
* Fix URLPathVersioning reverse fallback [[#7247](https://github.com/encode/django-rest-framework/pull/7247)]
* Warn about Decimal type in min_value and max_value arguments of DecimalField [[#8972](https://github.com/encode/django-rest-framework/pull/8972)]
* Fix mapping for choice values [[#8968](https://github.com/encode/django-rest-framework/pull/8968)]
* Refactor read function to use context manager for file handling [[#8967](https://github.com/encode/django-rest-framework/pull/8967)]
* Fix: fallback on CursorPagination ordering if unset on the view [[#8954](https://github.com/encode/django-rest-framework/pull/8954)]
* Replaced `OrderedDict` with `dict` [[#8964](https://github.com/encode/django-rest-framework/pull/8964)]
* Refactor get_field_info method to include max_digits and decimal_places attributes in SimpleMetadata class [[#8943](https://github.com/encode/django-rest-framework/pull/8943)]
* Implement `__eq__` for validators [[#8925](https://github.com/encode/django-rest-framework/pull/8925)]
* Ensure CursorPagination respects nulls in the ordering field [[#8912](https://github.com/encode/django-rest-framework/pull/8912)]
* Use ZoneInfo as primary source of timezone data [[#8924](https://github.com/encode/django-rest-framework/pull/8924)]
* Add username search field for TokenAdmin (#8927) [[#8934](https://github.com/encode/django-rest-framework/pull/8934)]
* Handle Nested Relation in SlugRelatedField when many=False [[#8922](https://github.com/encode/django-rest-framework/pull/8922)]
* Bump version of jQuery to 3.6.4 & updated ref links [[#8909](https://github.com/encode/django-rest-framework/pull/8909)]
* Support UniqueConstraint [[#7438](https://github.com/encode/django-rest-framework/pull/7438)]
* Allow Request, Response, Field, and GenericAPIView to be subscriptable. This allows the classes to be made generic for type checking. [[#8825](https://github.com/encode/django-rest-framework/pull/8825)]
* Feat: Add some changes to ValidationError to support django style validation errors [[#8863](https://github.com/encode/django-rest-framework/pull/8863)]
* Fix Respect `can_read_model` permission in DjangoModelPermissions [[#8009](https://github.com/encode/django-rest-framework/pull/8009)]
* Add SimplePathRouter [[#6789](https://github.com/encode/django-rest-framework/pull/6789)]
* Re-prefetch related objects after updating [[#8043](https://github.com/encode/django-rest-framework/pull/8043)]
* Fix FilePathField required argument [[#8805](https://github.com/encode/django-rest-framework/pull/8805)]
* Raise ImproperlyConfigured exception if `basename` is not unique [[#8438](https://github.com/encode/django-rest-framework/pull/8438)]
* Use PrimaryKeyRelatedField pkfield in openapi [[#8315](https://github.com/encode/django-rest-framework/pull/8315)]
* replace partition with split in BasicAuthentication [[#8790](https://github.com/encode/django-rest-framework/pull/8790)]
* Fix BooleanField's allow_null behavior [[#8614](https://github.com/encode/django-rest-framework/pull/8614)]
* Handle Django's ValidationErrors in ListField [[#6423](https://github.com/encode/django-rest-framework/pull/6423)]
* Remove a bit of inline CSS. Add CSP nonce where it might be required and is available [[#8783](https://github.com/encode/django-rest-framework/pull/8783)]
* Use autocomplete widget for user selection in Token admin [[#8534](https://github.com/encode/django-rest-framework/pull/8534)]
* Make browsable API compatible with strong CSP [[#8784](https://github.com/encode/django-rest-framework/pull/8784)]
* Avoid inline script execution for injecting CSRF token [[#7016](https://github.com/encode/django-rest-framework/pull/7016)]
* Mitigate global dependency on inflection [[#8017](https://github.com/encode/django-rest-framework/pull/8017)] [[#8781](https://github.com/encode/django-rest-framework/pull/8781)]
* Register Django urls [[#8778](https://github.com/encode/django-rest-framework/pull/8778)]
* Implemented Verbose Name Translation for TokenProxy [[#8713](https://github.com/encode/django-rest-framework/pull/8713)]
* Properly handle OverflowError in DurationField deserialization [[#8042](https://github.com/encode/django-rest-framework/pull/8042)]
* Fix OpenAPI operation name plural appropriately [[#8017](https://github.com/encode/django-rest-framework/pull/8017)]
* Represent SafeString as plain string on schema rendering [[#8429](https://github.com/encode/django-rest-framework/pull/8429)]
* Fix #8771 - Checking for authentication even if `_ignore_model_permissions = True` [[#8772](https://github.com/encode/django-rest-framework/pull/8772)]
* Fix 404 when page query parameter is empty string [[#8578](https://github.com/encode/django-rest-framework/pull/8578)]
* Fixes instance check in ListSerializer.to_representation [[#8726](https://github.com/encode/django-rest-framework/pull/8726)] [[#8727](https://github.com/encode/django-rest-framework/pull/8727)]
* FloatField will crash if the input is a number that is too big [[#8725](https://github.com/encode/django-rest-framework/pull/8725)]
* Add missing DurationField to SimpleMetadata label_lookup [[#8702](https://github.com/encode/django-rest-framework/pull/8702)]
* Add support for Python 3.11 [[#8752](https://github.com/encode/django-rest-framework/pull/8752)]
* Make request consistently available in pagination classes [[#8764](https://github.com/encode/django-rest-framework/pull/9764)]
* Possibility to remove trailing zeros on DecimalFields representation [[#6514](https://github.com/encode/django-rest-framework/pull/6514)]
* Add a method for getting serializer field name (OpenAPI) [[#7493](https://github.com/encode/django-rest-framework/pull/7493)]
* Add `__eq__` method for `OperandHolder` class [[#8710](https://github.com/encode/django-rest-framework/pull/8710)]
* Avoid importing `django.test` package when not testing [[#8699](https://github.com/encode/django-rest-framework/pull/8699)]
* Preserve exception messages for wrapped Django exceptions [[#8051](https://github.com/encode/django-rest-framework/pull/8051)]
* Include `examples` and `format` to OpenAPI schema of CursorPagination [[#8687](https://github.com/encode/django-rest-framework/pull/8687)] [[#8686](https://github.com/encode/django-rest-framework/pull/8686)]
* Fix infinite recursion with deepcopy on Request [[#8684](https://github.com/encode/django-rest-framework/pull/8684)]
* Refactor: Replace try/except with contextlib.suppress() [[#8676](https://github.com/encode/django-rest-framework/pull/8676)]
* Minor fix to SerializeMethodField docstring [[#8629](https://github.com/encode/django-rest-framework/pull/8629)]
* Minor refactor: Unnecessary use of list() function [[#8672](https://github.com/encode/django-rest-framework/pull/8672)]
* Unnecessary list comprehension [[#8670](https://github.com/encode/django-rest-framework/pull/8670)]
* Use correct class to indicate present deprecation [[#8665](https://github.com/encode/django-rest-framework/pull/8665)]
## 3.14.x series
### 3.14.0
Date: 22nd September 2022
* Django 2.2 is no longer supported. [[#8662](https://github.com/encode/django-rest-framework/pull/8662)]
* Django 4.1 compatibility. [[#8591](https://github.com/encode/django-rest-framework/pull/8591)]
* Add `--api-version` CLI option to `generateschema` management command. [[#8663](https://github.com/encode/django-rest-framework/pull/8663)]
* Enforce `is_valid(raise_exception=False)` as a keyword-only argument. [[#7952](https://github.com/encode/django-rest-framework/pull/7952)]
* Stop calling `set_context` on Validators. [[#8589](https://github.com/encode/django-rest-framework/pull/8589)]
* Return `NotImplemented` from `ErrorDetails.__ne__`. [[#8538](https://github.com/encode/django-rest-framework/pull/8538)]
* Don't evaluate `DateTimeField.default_timezone` when a custom timezone is set. [[#8531](https://github.com/encode/django-rest-framework/pull/8531)]
* Make relative URLs clickable in Browsable API. [[#8464](https://github.com/encode/django-rest-framework/pull/8464)]
* Support `ManyRelatedField` falling back to the default value when the attribute specified by dot notation doesn't exist. Matches `ManyRelatedField.get_attribute` to `Field.get_attribute`. [[#7574](https://github.com/encode/django-rest-framework/pull/7574)]
* Make `schemas.openapi.get_reference` public. [[#7515](https://github.com/encode/django-rest-framework/pull/7515)]
* Make `ReturnDict` support `dict` union operators on Python 3.9 and later. [[#8302](https://github.com/encode/django-rest-framework/pull/8302)]
* Update throttling to check if `request.user` is set before checking if the user is authenticated. [[#8370](https://github.com/encode/django-rest-framework/pull/8370)]
## 3.13.x series
### 3.13.1
Date: 15th December 2021
* Revert schema naming changes with function based `@api_view`. [#8297]
### 3.13.0
Date: 13th December 2021
* Django 4.0 compatibility. [#8178]
* Add `max_length` and `min_length` options to `ListSerializer`. [#8165]
* Add `get_request_serializer` and `get_response_serializer` hooks to `AutoSchema`. [#7424]
* Fix OpenAPI representation of null-able read only fields. [#8116]
* Respect `UNICODE_JSON` setting in API schema outputs. [#7991]
* Fix for `RemoteUserAuthentication`. [#7158]
* Make Field constructors keyword-only. [#7632]
---
## 3.12.x series
### 3.12.4
Date: 26th March 2021
* Revert use of `deque` instead of `list` for tracking throttling `.history`. (Due to incompatibility with DjangoRedis cache backend. See #7870) [#7872]
### 3.12.3
Date: 25th March 2021
* Properly handle ATOMIC_REQUESTS when multiple database configurations are used. [#7739]
* Bypass `COUNT` query when `LimitOffsetPagination` is configured but pagination params are not included on the request. [#6098]
* Respect `allow_null=True` on `DecimalField`. [#7718]
* Allow title cased `"Yes"`/`"No"` values with `BooleanField`. [#7739]
* Add `PageNumberPagination.get_page_number()` method for overriding behavior. [#7652]
* Fixed rendering of timedelta values in OpenAPI schemas, when present as default, min, or max fields. [#7641]
* Render JSONFields with indentation in browsable API forms. [#6243]
* Remove unnecessary database query in admin Token views. [#7852]
* Raise validation errors when bools are passed to `PrimaryKeyRelatedField` fields, instead of casting to ints. [#7597]
* Don't include model properties as automatically generated ordering fields with `OrderingFilter`. [#7609]
* Use `deque` instead of `list` for tracking throttling `.history`. [#7849]
### 3.12.2
Date: 13th October 2020
* Fix issue if `rest_framework.authtoken.models` is imported, but `rest_framework.authtoken` is not in INSTALLED_APPS. [#7571]
* Ignore subclasses of BrowsableAPIRenderer in OpenAPI schema. [#7497]
* Narrower exception catching in serilizer fields, to ensure that any errors in broken `get_queryset()` methods are not masked. [#7480]
### 3.12.1
Date: 28th September 2020
* Add `TokenProxy` migration. [#7557]
### 3.12.0
Date: 28th September 2020
* Add `--file` option to `generateschema` command. [#7130]
* Support `tags` for OpenAPI schema generation. See [the schema docs](https://www.django-rest-framework.org/api-guide/schemas/#grouping-operations-with-tags). [#7184]
* Support customising the operation ID for schema generation. See [the schema docs](https://www.django-rest-framework.org/api-guide/schemas/#operationid). [#7190]
* Support OpenAPI components for schema generation. See [the schema docs](https://www.django-rest-framework.org/api-guide/schemas/#components). [#7124]
* The following methods on `AutoSchema` become public API: `get_path_parameters`, `get_pagination_parameters`, `get_filter_parameters`, `get_request_body`, `get_responses`, `get_serializer`, `get_paginator`, `map_serializer`, `map_field`, `map_choice_field`, `map_field_validators`, `allows_filters`. See [the schema docs](https://www.django-rest-framework.org/api-guide/schemas/#autoschema)
* Add support for Django 3.1's database-agnositic `JSONField`. [#7467]
* `SearchFilter` now supports nested search on `JSONField` and `HStoreField` model fields. [#7121]
* `SearchFilter` now supports searching on `annotate()` fields. [#6240]
* The authtoken model no longer exposes the `pk` in the admin URL. [#7341]
* Add `__repr__` for Request instances. [#7239]
* UTF-8 decoding with Latin-1 fallback for basic auth credentials. [#7193]
* CharField treats surrogate characters as a validation failure. [#7026]
* Don't include callables as default values in schemas. [#7105]
* Improve `ListField` schema output to include all available child information. [#7137]
* Allow `default=False` to be included for `BooleanField` schema outputs. [#7165]
* Include `"type"` information in `ChoiceField` schema outputs. [#7161]
* Include `"type": "object"` on schema objects. [#7169]
* Don't include component in schema output for DELETE requests. [#7229]
* Fix schema types for `DecimalField`. [#7254]
* Fix schema generation for `ObtainAuthToken` view. [#7211]
* Support passing `context=...` to view `.get_serializer()` methods. [#7298]
* Pass custom code to `PermissionDenied` if permission class has one set. [#7306]
* Include "example" in schema pagination output. [#7275]
* Default status code of 201 on schema output for POST requests. [#7206]
* Use camelCase for operation IDs in schema output. [#7208]
* Warn if duplicate operation IDs exist in schema output. [#7207]
* Improve handling of decimal type when mapping `ChoiceField` to a schema output. [#7264]
* Disable YAML aliases for OpenAPI schema outputs. [#7131]
* Fix action URL names for APIs included under a namespaced URL. [#7287]
* Update jQuery version from 3.4 to 3.5. [#7313]
* Fix `UniqueTogether` handling when serializer fields use `source=...`. [#7143]
* HTTP `HEAD` requests now set `self.action` correctly on a ViewSet instance. [#7223]
* Return a valid OpenAPI schema for the case where no API schema paths exist. [#7125]
* Include tests in package distribution. [#7145]
* Allow type checkers to support annotations like `ModelSerializer[Author]`. [#7385]
* Don't include invalid `charset=None` portion in the request `Content-Type` header when using APIClient. [#7400]
* Fix `\Z`/`\z` tokens in OpenAPI regexs. [#7389]
* Fix `PrimaryKeyRelatedField` and `HyperlinkedRelatedField` when source field is actually a property. [#7142]
* `Token.generate_key` is now a class method. [#7502]
* `@action` warns if method is wrapped in a decorator that does not preserve information using `@functools.wraps`. [#7098]
* Deprecate `serializers.NullBooleanField` in favour of `serializers.BooleanField` with `allow_null=True` [#7122]
---
## 3.11.x series
### 3.11.2
**Date**: 30th September 2020
* **Security**: Drop `urlize_quoted_links` template tag in favour of Django's built-in `urlize`. Removes a XSS vulnerability for some kinds of content in the browsable API.
### 3.11.1
**Date**: 5th August 2020
* Fix compat with Django 3.1
### 3.11.0
**Date**: 12th December 2019
* Drop `.set_context` API [in favour of a `requires_context` marker](3.11-announcement.md#validator-default-context).
* Changed default widget for TextField with choices to select box. [#6892][gh6892]
* Supported nested writes on non-relational fields, such as JSONField. [#6916][gh6916]
* Include request/response media types in OpenAPI schemas, based on configured parsers/renderers. [#6865][gh6865]
* Include operation descriptions in OpenAPI schemas, based on the docstring on the view. [#6898][gh6898]
* Fix representation of serializers with all optional fields in OpenAPI schemas. [#6941][gh6941], [#6944][gh6944]
* Fix representation of `serializers.HStoreField` in OpenAPI schemas. [#6914][gh6914]
* Fix OpenAPI generation when title or version is not provided. [#6912][gh6912]
* Use `int64` representation for large integers in OpenAPI schemas. [#7018][gh7018]
* Improved error messages if no `.to_representation` implementation is provided on a field subclass. [#6996][gh6996]
* Fix for serializer classes that use multiple inheritance. [#6980][gh6980]
* Fix for reversing Hyperlinked URL fields with percent encoded components in the path. [#7059][gh7059]
* Update bootstrap to 3.4.1. [#6923][gh6923]
## 3.10.x series
### 3.10.3
**Date**: 4th September 2019
* Include API version in OpenAPI schema generation, defaulting to empty string.
* Add pagination properties to OpenAPI response schemas.
* Add missing "description" property to OpenAPI response schemas.
* Only include "required" for non-empty cases in OpenAPI schemas.
* Fix response schemas for "DELETE" case in OpenAPI schemas.
* Use an array type for list view response schemas.
* Use consistent `lowerInitialCamelCase` style in OpenAPI operation IDs.
* Fix `minLength`/`maxLength`/`minItems`/`maxItems` properties in OpenAPI schemas.
* Only call `FileField.url` once in serialization, for improved performance.
* Fix an edge case where throttling calculations could error after a configuration change.
### 3.10.2
**Date**: 29th July 2019
* Various `OpenAPI` schema fixes.
* Ability to specify urlconf in include_docs_urls.
### 3.10.1
**Date**: 17th July 2019
* Don't include autocomplete fields on TokenAuth admin, since it forces constraints on custom user models & admin.
* Require `uritemplate` for OpenAPI schema generation, but not `coreapi`.
### 3.10.0
**Date**: [15th July 2019][3.10.0-milestone]
* Switch to OpenAPI schema generation.
* Drop Python 2 support.
* Add `generateschema --generator_class` CLI option
* Updated PyYaml dependency for OpenAPI schema generation to `pyyaml>=5.1` [#6680][gh6680]
* Resolve DeprecationWarning with markdown. [#6317][gh6317]
* Use `user.get_username` in templates, in preference to `user.username`.
* Fix for cursor pagination issue that could occur after object deletions.
* Fix for nullable fields with `source="*"`
* Always apply all throttle classes during throttling checks.
* Updates to jQuery and Markdown dependencies.
* Don't strict disallow redundant `SerializerMethodField` field name arguments.
* Don't render extra actions in browable API if not authenticated.
* Strip null characters from search parameters.
* Deprecate the `detail_route` decorator in favor of `action`, which accepts a `detail` bool. Use `@action(detail=True)` instead. [gh6687]
* Deprecate the `list_route` decorator in favor of `action`, which accepts a `detail` bool. Use `@action(detail=False)` instead. [gh6687]
## 3.9.x series
### 3.9.4
**Date**: 10th May 2019
This is a maintenance release that fixes an error handling bug under Python 2.
### 3.9.3
**Date**: 29th April 2019
This is the last Django REST Framework release that will support Python 2.
Be sure to upgrade to Python 3 before upgrading to Django REST Framework 3.10.
* Adjusted the compat check for django-guardian to allow the last guardian
version (v1.4.9) compatible with Python 2. [#6613][gh6613]
### 3.9.2
**Date**: [3rd March 2019][3.9.2-milestone]
* Routers: invalidate `_urls` cache on `register()` [#6407][gh6407]
* Deferred schema renderer creation to avoid requiring pyyaml. [#6416][gh6416]
* Added 'request_forms' block to base.html [#6340][gh6340]
* Fixed SchemaView to reset renderer on exception. [#6429][gh6429]
* Update Django Guardian dependency. [#6430][gh6430]
* Ensured support for Django 2.2 [#6422][gh6422] & [#6455][gh6455]
* Made templates compatible with session-based CSRF. [#6207][gh6207]
* Adjusted field `validators` to accept non-list iterables. [#6282][gh6282]
* Added SearchFilter.get_search_fields() hook. [#6279][gh6279]
* Fix DeprecationWarning when accessing collections.abc classes via collections [#6268][gh6268]
* Allowed Q objects in limit_choices_to introspection. [#6472][gh6472]
* Added lazy evaluation to composed permissions. [#6463][gh6463]
* Add negation ~ operator to permissions composition [#6361][gh6361]
* Avoided calling distinct on annotated fields in SearchFilter. [#6240][gh6240]
* Introduced `RemovedInDRF…Warning` classes to simplify deprecations. [#6480][gh6480]
### 3.9.1
**Date**: [16th January 2019][3.9.1-milestone]
* Resolve XSS issue in browsable API. [#6330][gh6330]
* Upgrade Bootstrap to 3.4.0 to resolve XSS issue.
* Resolve issues with composable permissions. [#6299][gh6299]
* Respect `limit_choices_to` on foreign keys. [#6371][gh6371]
### 3.9.0
**Date**: [18th October 2018][3.9.0-milestone]
* Improvements to ViewSet extra actions [#5605][gh5605]
* Fix `action` support for ViewSet suffixes [#6081][gh6081]
* Allow `action` docs sections [#6060][gh6060]
* Deprecate the `Router.register` `base_name` argument in favor of `basename`. [#5990][gh5990]
* Deprecate the `Router.get_default_base_name` method in favor of `Router.get_default_basename`. [#5990][gh5990]
* Change `CharField` to disallow null bytes. [#6073][gh6073]
To revert to the old behavior, subclass `CharField` and remove `ProhibitNullCharactersValidator` from the validators.
```python
class NullableCharField(serializers.CharField):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.validators = [
v
for v in self.validators
if not isinstance(v, ProhibitNullCharactersValidator)
]
```
* Add `OpenAPIRenderer` and `generate_schema` management command. [#6229][gh6229]
* Add OpenAPIRenderer by default, and add schema docs. [#6233][gh6233]
* Allow permissions to be composed [#5753][gh5753]
* Allow nullable BooleanField in Django 2.1 [#6183][gh6183]
* Add testing of Python 3.7 support [#6141][gh6141]
* Test using Django 2.1 final release. [#6109][gh6109]
* Added djangorestframework-datatables to third-party packages [#5931][gh5931]
* Change ISO 8601 date format to exclude year/month-only options [#5936][gh5936]
* Update all pypi.python.org URLs to pypi.org [#5942][gh5942]
* Ensure that html forms (multipart form data) respect optional fields [#5927][gh5927]
* Allow hashing of ErrorDetail. [#5932][gh5932]
* Correct schema parsing for JSONField [#5878][gh5878]
* Render descriptions (from help_text) using safe [#5869][gh5869]
* Removed input value from default_error_message [#5881][gh5881]
* Added min_value/max_value support in DurationField [#5643][gh5643]
* Fixed instance being overwritten in pk-only optimization try/except block [#5747][gh5747]
* Fixed AttributeError from items filter when value is None [#5981][gh5981]
* Fixed Javascript `e.indexOf` is not a function error [#5982][gh5982]
* Fix schemas for extra actions [#5992][gh5992]
* Improved get_error_detail to use error_dict/error_list [#5785][gh5785]
* Improved URLs in Admin renderer [#5988][gh5988]
* Add "Community" section to docs, minor cleanup [#5993][gh5993]
* Moved guardian imports out of compat [#6054][gh6054]
* Deprecate the `DjangoObjectPermissionsFilter` class, moved to the `djangorestframework-guardian` package. [#6075][gh6075]
* Drop Django 1.10 support [#5657][gh5657]
* Only catch TypeError/ValueError for object lookups [#6028][gh6028]
* Handle models without .objects manager in ModelSerializer. [#6111][gh6111]
* Improve ModelSerializer.create() error message. [#6112][gh6112]
* Fix CSRF cookie check failure when using session auth with django 1.11.6+ [#6113][gh6113]
* Updated JWT docs. [#6138][gh6138]
* Fix autoescape not getting passed to urlize_quoted_links filter [#6191][gh6191]
## 3.8.x series ## 3.8.x series
### 3.8.2
**Date**: [6th April 2018][3.8.2-milestone]
* Fix `read_only` + `default` `unique_together` validation. [#5922][gh5922]
* authtoken.views import coreapi from rest_framework.compat, not directly. [#5921][gh5921]
* Docs: Add missing argument 'detail' to Route [#5920][gh5920]
### 3.8.1
**Date**: [4th April 2018][3.8.1-milestone]
* Use old `url_name` behavior in route decorators [#5915][gh5915]
For `list_route` and `detail_route` maintain the old behavior of `url_name`,
basing it on the `url_path` instead of the function name.
### 3.8.0 ### 3.8.0
**Date**: [3rd April 2018][3.8.0-milestone] **Date**: [3rd April 2018][3.8.0-milestone]
@ -57,10 +570,11 @@ You can determine your currently installed version using `pip show`:
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(owner=self.request.user) serializer.save(owner=self.request.user)
Alternatively you may override `save()` or `create()` or `update()` on the serialiser as appropriate. Alternatively you may override `save()` or `create()` or `update()` on the serializer as appropriate.
* Correct allow_null behaviour when required=False [#5888][gh5888] * Correct allow_null behaviour when required=False [#5888][gh5888]
Without an explicit `default`, `allow_null` implies a default of `null` for outgoing serialisation. Previously such Without an explicit `default`, `allow_null` implies a default of `null` for outgoing serialization. Previously such
fields were being skipped when read-only or otherwise not required. fields were being skipped when read-only or otherwise not required.
**Possible backwards compatibility break** if you were relying on such fields being excluded from the outgoing **Possible backwards compatibility break** if you were relying on such fields being excluded from the outgoing
@ -73,7 +587,7 @@ You can determine your currently installed version using `pip show`:
""" """
Drop `maybe_none` field if None. Drop `maybe_none` field if None.
""" """
data = super().data() data = super().data
if 'maybe_none' in data and data['maybe_none'] is None: if 'maybe_none' in data and data['maybe_none'] is None:
del data['maybe_none'] del data['maybe_none']
return data return data
@ -86,6 +600,8 @@ You can determine your currently installed version using `pip show`:
* Merged `list_route` and `detail_route` into a single `action` decorator. * Merged `list_route` and `detail_route` into a single `action` decorator.
* Get all extra actions on a `ViewSet` with `.get_extra_actions()`. * Get all extra actions on a `ViewSet` with `.get_extra_actions()`.
* Extra actions now set the `url_name` and `url_path` on the decorated method. * Extra actions now set the `url_name` and `url_path` on the decorated method.
* `url_name` is now based on the function name, instead of the `url_path`,
as the path is not always suitable (e.g., capturing arguments in the path).
* Enable action url reversing through `.reverse_action()` method (added in 3.7.4) * Enable action url reversing through `.reverse_action()` method (added in 3.7.4)
* Example reverse call: `self.reverse_action(self.custom_action.url_name)` * Example reverse call: `self.reverse_action(self.custom_action.url_name)`
* Add `detail` initkwarg to indicate if the current action is operating on a * Add `detail` initkwarg to indicate if the current action is operating on a
@ -96,6 +612,9 @@ You can determine your currently installed version using `pip show`:
* Deprecated `list_route` & `detail_route` in favor of `action` decorator with `detail` boolean. * Deprecated `list_route` & `detail_route` in favor of `action` decorator with `detail` boolean.
* Deprecated dynamic list/detail route variants in favor of `DynamicRoute` with `detail` boolean. * Deprecated dynamic list/detail route variants in favor of `DynamicRoute` with `detail` boolean.
* Refactored the router's dynamic route generation. * Refactored the router's dynamic route generation.
* `list_route` and `detail_route` maintain the old behavior of `url_name`,
basing it on the `url_path` instead of the function name.
* Fix formatting of the 3.7.4 release note [#5704][gh5704] * Fix formatting of the 3.7.4 release note [#5704][gh5704]
* Docs: Update DRF Writable Nested Serializers references [#5711][gh5711] * Docs: Update DRF Writable Nested Serializers references [#5711][gh5711]
* Docs: Fixed typo in auth URLs example. [#5713][gh5713] * Docs: Fixed typo in auth URLs example. [#5713][gh5713]
@ -188,7 +707,7 @@ You can determine your currently installed version using `pip show`:
Note: `AutoSchema.__init__` now ensures `manual_fields` is a list. Note: `AutoSchema.__init__` now ensures `manual_fields` is a list.
Previously may have been stored internally as `None`. Previously may have been stored internally as `None`.
* Remove ulrparse compatability shim; use six instead [#5579][gh5579] * Remove ulrparse compatibility shim; use six instead [#5579][gh5579]
* Drop compat wrapper for `TimeDelta.total_seconds()` [#5577][gh5577] * Drop compat wrapper for `TimeDelta.total_seconds()` [#5577][gh5577]
* Clean up all whitespace throughout project [#5578][gh5578] * Clean up all whitespace throughout project [#5578][gh5578]
* Compat cleanup [#5581][gh5581] * Compat cleanup [#5581][gh5581]
@ -293,7 +812,7 @@ You can determine your currently installed version using `pip show`:
* Deprecated `exclude_from_schema` on `APIView` and `api_view` decorator. Set `schema = None` or `@schema(None)` as appropriate. [#5422][gh5422] * Deprecated `exclude_from_schema` on `APIView` and `api_view` decorator. Set `schema = None` or `@schema(None)` as appropriate. [#5422][gh5422]
* Timezone-aware `DateTimeField`s now respect active or default `timezone` during serialization, instead of always using UTC. [#5435][gh5435] * Timezone-aware `DateTimeField`s now respect active or default `timezone` during serialization, instead of always using UTC. [#5435][gh5435]
Resolves inconsistency whereby instances were serialised with supplied datetime for `create` but UTC for `retrieve`. [#3732][gh3732] Resolves inconsistency whereby instances were serialized with supplied datetime for `create` but UTC for `retrieve`. [#3732][gh3732]
**Possible backwards compatibility break** if you were relying on datetime strings being UTC. Have client interpret datetimes or [set default or active timezone (docs)][djangodocs-set-timezone] to UTC if needed. **Possible backwards compatibility break** if you were relying on datetime strings being UTC. Have client interpret datetimes or [set default or active timezone (docs)][djangodocs-set-timezone] to UTC if needed.
@ -614,7 +1133,7 @@ See the [release announcement][3.6-release].
* description.py codes and tests removal. ([#4153][gh4153]) * description.py codes and tests removal. ([#4153][gh4153])
* Wrap guardian.VERSION in tuple. ([#4149][gh4149]) * Wrap guardian.VERSION in tuple. ([#4149][gh4149])
* Refine validator for fields with <source=> kwargs. ([#4146][gh4146]) * Refine validator for fields with <source=> kwargs. ([#4146][gh4146])
* Fix None values representation in childs of ListField, DictField. ([#4118][gh4118]) * Fix None values representation in children of ListField, DictField. ([#4118][gh4118])
* Resolve TimeField representation for midnight value. ([#4107][gh4107]) * Resolve TimeField representation for midnight value. ([#4107][gh4107])
* Set proper status code in AdminRenderer for the redirection after POST/DELETE requests. ([#4106][gh4106]) * Set proper status code in AdminRenderer for the redirection after POST/DELETE requests. ([#4106][gh4106])
* TimeField render returns None instead of 00:00:00. ([#4105][gh4105]) * TimeField render returns None instead of 00:00:00. ([#4105][gh4105])
@ -622,7 +1141,7 @@ See the [release announcement][3.6-release].
* Prevent raising exception when limit is 0. ([#4098][gh4098]) * Prevent raising exception when limit is 0. ([#4098][gh4098])
* TokenAuthentication: Allow custom keyword in the header. ([#4097][gh4097]) * TokenAuthentication: Allow custom keyword in the header. ([#4097][gh4097])
* Handle incorrectly padded HTTP basic auth header. ([#4090][gh4090]) * Handle incorrectly padded HTTP basic auth header. ([#4090][gh4090])
* LimitOffset pagination crashes Browseable API when limit=0. ([#4079][gh4079]) * LimitOffset pagination crashes Browsable API when limit=0. ([#4079][gh4079])
* Fixed DecimalField arbitrary precision support. ([#4075][gh4075]) * Fixed DecimalField arbitrary precision support. ([#4075][gh4075])
* Added support for custom CSRF cookie names. ([#4049][gh4049]) * Added support for custom CSRF cookie names. ([#4049][gh4049])
* Fix regression introduced by #4035. ([#4041][gh4041]) * Fix regression introduced by #4035. ([#4041][gh4041])
@ -1055,6 +1574,12 @@ For older release notes, [please see the version 2.x documentation][old-release-
[3.7.6-milestone]: https://github.com/encode/django-rest-framework/milestone/64?closed=1 [3.7.6-milestone]: https://github.com/encode/django-rest-framework/milestone/64?closed=1
[3.7.7-milestone]: https://github.com/encode/django-rest-framework/milestone/65?closed=1 [3.7.7-milestone]: https://github.com/encode/django-rest-framework/milestone/65?closed=1
[3.8.0-milestone]: https://github.com/encode/django-rest-framework/milestone/61?closed=1 [3.8.0-milestone]: https://github.com/encode/django-rest-framework/milestone/61?closed=1
[3.8.1-milestone]: https://github.com/encode/django-rest-framework/milestone/67?closed=1
[3.8.2-milestone]: https://github.com/encode/django-rest-framework/milestone/68?closed=1
[3.9.0-milestone]: https://github.com/encode/django-rest-framework/milestone/66?closed=1
[3.9.1-milestone]: https://github.com/encode/django-rest-framework/milestone/70?closed=1
[3.9.2-milestone]: https://github.com/encode/django-rest-framework/milestone/71?closed=1
[3.10.0-milestone]: https://github.com/encode/django-rest-framework/milestone/69?closed=1
<!-- 3.0.1 --> <!-- 3.0.1 -->
[gh2013]: https://github.com/encode/django-rest-framework/issues/2013 [gh2013]: https://github.com/encode/django-rest-framework/issues/2013
@ -1926,3 +2451,95 @@ For older release notes, [please see the version 2.x documentation][old-release-
[gh5764]: https://github.com/encode/django-rest-framework/issues/5764 [gh5764]: https://github.com/encode/django-rest-framework/issues/5764
[gh5904]: https://github.com/encode/django-rest-framework/issues/5904 [gh5904]: https://github.com/encode/django-rest-framework/issues/5904
[gh5899]: https://github.com/encode/django-rest-framework/issues/5899 [gh5899]: https://github.com/encode/django-rest-framework/issues/5899
<!-- 3.8.1 -->
[gh5915]: https://github.com/encode/django-rest-framework/issues/5915
<!-- 3.8.2 -->
[gh5922]: https://github.com/encode/django-rest-framework/issues/5922
[gh5921]: https://github.com/encode/django-rest-framework/issues/5921
[gh5920]: https://github.com/encode/django-rest-framework/issues/5920
<!-- 3.9.0 -->
[gh6109]: https://github.com/encode/django-rest-framework/issues/6109
[gh6141]: https://github.com/encode/django-rest-framework/issues/6141
[gh6113]: https://github.com/encode/django-rest-framework/issues/6113
[gh6112]: https://github.com/encode/django-rest-framework/issues/6112
[gh6111]: https://github.com/encode/django-rest-framework/issues/6111
[gh6028]: https://github.com/encode/django-rest-framework/issues/6028
[gh5657]: https://github.com/encode/django-rest-framework/issues/5657
[gh6054]: https://github.com/encode/django-rest-framework/issues/6054
[gh5993]: https://github.com/encode/django-rest-framework/issues/5993
[gh5990]: https://github.com/encode/django-rest-framework/issues/5990
[gh5988]: https://github.com/encode/django-rest-framework/issues/5988
[gh5785]: https://github.com/encode/django-rest-framework/issues/5785
[gh5992]: https://github.com/encode/django-rest-framework/issues/5992
[gh5605]: https://github.com/encode/django-rest-framework/issues/5605
[gh5982]: https://github.com/encode/django-rest-framework/issues/5982
[gh5981]: https://github.com/encode/django-rest-framework/issues/5981
[gh5747]: https://github.com/encode/django-rest-framework/issues/5747
[gh5643]: https://github.com/encode/django-rest-framework/issues/5643
[gh5881]: https://github.com/encode/django-rest-framework/issues/5881
[gh5869]: https://github.com/encode/django-rest-framework/issues/5869
[gh5878]: https://github.com/encode/django-rest-framework/issues/5878
[gh5932]: https://github.com/encode/django-rest-framework/issues/5932
[gh5927]: https://github.com/encode/django-rest-framework/issues/5927
[gh5942]: https://github.com/encode/django-rest-framework/issues/5942
[gh5936]: https://github.com/encode/django-rest-framework/issues/5936
[gh5931]: https://github.com/encode/django-rest-framework/issues/5931
[gh6183]: https://github.com/encode/django-rest-framework/issues/6183
[gh6075]: https://github.com/encode/django-rest-framework/issues/6075
[gh6138]: https://github.com/encode/django-rest-framework/issues/6138
[gh6081]: https://github.com/encode/django-rest-framework/issues/6081
[gh6073]: https://github.com/encode/django-rest-framework/issues/6073
[gh6191]: https://github.com/encode/django-rest-framework/issues/6191
[gh6060]: https://github.com/encode/django-rest-framework/issues/6060
[gh6233]: https://github.com/encode/django-rest-framework/issues/6233
[gh5753]: https://github.com/encode/django-rest-framework/issues/5753
[gh6229]: https://github.com/encode/django-rest-framework/issues/6229
<!-- 3.9.1 -->
[gh6330]: https://github.com/encode/django-rest-framework/issues/6330
[gh6299]: https://github.com/encode/django-rest-framework/issues/6299
[gh6371]: https://github.com/encode/django-rest-framework/issues/6371
<!-- 3.9.2 -->
[gh6480]: https://github.com/encode/django-rest-framework/issues/6480
[gh6240]: https://github.com/encode/django-rest-framework/issues/6240
[gh6361]: https://github.com/encode/django-rest-framework/issues/6361
[gh6463]: https://github.com/encode/django-rest-framework/issues/6463
[gh6472]: https://github.com/encode/django-rest-framework/issues/6472
[gh6268]: https://github.com/encode/django-rest-framework/issues/6268
[gh6279]: https://github.com/encode/django-rest-framework/issues/6279
[gh6282]: https://github.com/encode/django-rest-framework/issues/6282
[gh6207]: https://github.com/encode/django-rest-framework/issues/6207
[gh6455]: https://github.com/encode/django-rest-framework/issues/6455
[gh6422]: https://github.com/encode/django-rest-framework/issues/6422
[gh6430]: https://github.com/encode/django-rest-framework/issues/6430
[gh6429]: https://github.com/encode/django-rest-framework/issues/6429
[gh6340]: https://github.com/encode/django-rest-framework/issues/6340
[gh6416]: https://github.com/encode/django-rest-framework/issues/6416
[gh6407]: https://github.com/encode/django-rest-framework/issues/6407
<!-- 3.9.3 -->
[gh6613]: https://github.com/encode/django-rest-framework/issues/6613
<!-- 3.10.0 -->
[gh6680]: https://github.com/encode/django-rest-framework/issues/6680
[gh6317]: https://github.com/encode/django-rest-framework/issues/6317
[gh6687]: https://github.com/encode/django-rest-framework/issues/6687
<!-- 3.11.0 -->
[gh6892]: https://github.com/encode/django-rest-framework/issues/6892
[gh6916]: https://github.com/encode/django-rest-framework/issues/6916
[gh6865]: https://github.com/encode/django-rest-framework/issues/6865
[gh6898]: https://github.com/encode/django-rest-framework/issues/6898
[gh6941]: https://github.com/encode/django-rest-framework/issues/6941
[gh6944]: https://github.com/encode/django-rest-framework/issues/6944
[gh6914]: https://github.com/encode/django-rest-framework/issues/6914
[gh6912]: https://github.com/encode/django-rest-framework/issues/6912
[gh7018]: https://github.com/encode/django-rest-framework/issues/7018
[gh6996]: https://github.com/encode/django-rest-framework/issues/6996
[gh6980]: https://github.com/encode/django-rest-framework/issues/6980
[gh7059]: https://github.com/encode/django-rest-framework/issues/7059
[gh6923]: https://github.com/encode/django-rest-framework/issues/6923

View File

@ -14,142 +14,9 @@ We aim to make creating third party packages as easy as possible, whilst keeping
If you have an idea for a new feature please consider how it may be packaged as a Third Party Package. We're always happy to discuss ideas on the [Mailing List][discussion-group]. If you have an idea for a new feature please consider how it may be packaged as a Third Party Package. We're always happy to discuss ideas on the [Mailing List][discussion-group].
## How to create a Third Party Package ## Creating a Third Party Package
### Creating your package ### Version compatibility
You can use [this cookiecutter template][cookiecutter] for creating reusable Django REST Framework packages quickly. Cookiecutter creates projects from project templates. While optional, this cookiecutter template includes best practices from Django REST framework and other packages, as well as a Travis CI configuration, Tox configuration, and a sane setup.py for easy PyPI registration/distribution.
Note: Let us know if you have an alternate cookiecuter package so we can also link to it.
#### Running the initial cookiecutter command
To run the initial cookiecutter command, you'll first need to install the Python `cookiecutter` package.
$ pip install cookiecutter
Once `cookiecutter` is installed just run the following to create a new project.
$ cookiecutter gh:jpadilla/cookiecutter-django-rest-framework
You'll be prompted for some questions, answer them, then it'll create your Python package in the current working directory based on those values.
full_name (default is "Your full name here")? Johnny Appleseed
email (default is "you@example.com")? jappleseed@example.com
github_username (default is "yourname")? jappleseed
pypi_project_name (default is "dj-package")? djangorestframework-custom-auth
repo_name (default is "dj-package")? django-rest-framework-custom-auth
app_name (default is "djpackage")? custom_auth
project_short_description (default is "Your project description goes here")?
year (default is "2014")?
version (default is "0.1.0")?
#### Getting it onto GitHub
To put your project up on GitHub, you'll need a repository for it to live in. You can create a new repository [here][new-repo]. If you need help, check out the [Create A Repo][create-a-repo] article on GitHub.
#### Adding to Travis CI
We recommend using [Travis CI][travis-ci], a hosted continuous integration service which integrates well with GitHub and is free for public repositories.
To get started with Travis CI, [sign in][travis-ci] with your GitHub account. Once you're signed in, go to your [profile page][travis-profile] and enable the service hook for the repository you want.
If you use the cookiecutter template, your project will already contain a `.travis.yml` file which Travis CI will use to build your project and run tests. By default, builds are triggered everytime you push to your repository or create Pull Request.
#### Uploading to PyPI
Once you've got at least a prototype working and tests running, you should publish it on PyPI to allow others to install it via `pip`.
You must [register][pypi-register] an account before publishing to PyPI.
To register your package on PyPI run the following command.
$ python setup.py register
If this is the first time publishing to PyPI, you'll be prompted to login.
Note: Before publishing you'll need to make sure you have the latest pip that supports `wheel` as well as install the `wheel` package.
$ pip install --upgrade pip
$ pip install wheel
After this, every time you want to release a new version on PyPI just run the following command.
$ python setup.py publish
You probably want to also tag the version now:
git tag -a {0} -m 'version 0.1.0'
git push --tags
After releasing a new version to PyPI, it's always a good idea to tag the version and make available as a GitHub Release.
We recommend to follow [Semantic Versioning][semver] for your package's versions.
### Development
#### Version requirements
The cookiecutter template assumes a set of supported versions will be provided for Python and Django. Make sure you correctly update your requirements, docs, `tox.ini`, `.travis.yml`, and `setup.py` to match the set of versions you wish to support.
#### Tests
The cookiecutter template includes a `runtests.py` which uses the `pytest` package as a test runner.
Before running, you'll need to install a couple test requirements.
$ pip install -r requirements.txt
Once requirements installed, you can run `runtests.py`.
$ ./runtests.py
Run using a more concise output style.
$ ./runtests.py -q
Run the tests using a more concise output style, no coverage, no flake8.
$ ./runtests.py --fast
Don't run the flake8 code linting.
$ ./runtests.py --nolint
Only run the flake8 code linting, don't run the tests.
$ ./runtests.py --lintonly
Run the tests for a given test case.
$ ./runtests.py MyTestCase
Run the tests for a given test method.
$ ./runtests.py MyTestCase.test_this_method
Shorter form to run the tests for a given test method.
$ ./runtests.py test_this_method
To run your tests against multiple versions of Python as different versions of requirements such as Django we recommend using `tox`. [Tox][tox-docs] is a generic virtualenv management and test command line tool.
First, install `tox` globally.
$ pip install tox
To run `tox`, just simply run:
$ tox
To run a particular `tox` environment:
$ tox -e envlist
`envlist` is a comma-separated value to that specifies the environments to run tests against. To view a list of all possible test environments, run:
$ tox -l
#### Version compatibility
Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into a `compat.py` module, and should provide a single common interface that the rest of the codebase can use. Sometimes, in order to ensure your code works on various different versions of Django, Python or third party libraries, you'll need to run slightly different code depending on the environment. Any code that branches in this way should be isolated into a `compat.py` module, and should provide a single common interface that the rest of the codebase can use.
@ -165,7 +32,7 @@ We suggest adding your package to the [REST Framework][rest-framework-grid] grid
#### Adding to the Django REST framework docs #### Adding to the Django REST framework docs
Create a [Pull Request][drf-create-pr] or [Issue][drf-create-issue] on GitHub, and we'll add a link to it from the main REST framework documentation. You can add your package under **Third party packages** of the API Guide section that best applies, like [Authentication][authentication] or [Permissions][permissions]. You can also link your package under the [Third Party Packages][third-party-packages] section. Create a [Pull Request][drf-create-pr] on GitHub, and we'll add a link to it from the main REST framework documentation. You can add your package under **Third party packages** of the API Guide section that best applies, like [Authentication][authentication] or [Permissions][permissions]. You can also link your package under the [Third Party Packages][third-party-packages] section.
#### Announce on the discussion group. #### Announce on the discussion group.
@ -177,21 +44,25 @@ Django REST Framework has a growing community of developers, packages, and resou
Check out a grid detailing all the packages and ecosystem around Django REST Framework at [Django Packages][rest-framework-grid]. Check out a grid detailing all the packages and ecosystem around Django REST Framework at [Django Packages][rest-framework-grid].
To submit new content, [open an issue][drf-create-issue] or [create a pull request][drf-create-pr]. To submit new content, [create a pull request][drf-create-pr].
## Async Support
* [adrf](https://github.com/em1208/adrf) - Async support, provides async Views, ViewSets, and Serializers.
### Authentication ### Authentication
* [djangorestframework-digestauth][djangorestframework-digestauth] - Provides Digest Access Authentication support. * [djangorestframework-digestauth][djangorestframework-digestauth] - Provides Digest Access Authentication support.
* [django-oauth-toolkit][django-oauth-toolkit] - Provides OAuth 2.0 support. * [django-oauth-toolkit][django-oauth-toolkit] - Provides OAuth 2.0 support.
* [doac][doac] - Provides OAuth 2.0 support. * [djangorestframework-simplejwt][djangorestframework-simplejwt] - Provides JSON Web Token Authentication support.
* [djangorestframework-jwt][djangorestframework-jwt] - Provides JSON Web Token Authentication support.
* [djangorestframework-simplejwt][djangorestframework-simplejwt] - An alternative package that provides JSON Web Token Authentication support.
* [hawkrest][hawkrest] - Provides Hawk HTTP Authorization. * [hawkrest][hawkrest] - Provides Hawk HTTP Authorization.
* [djangorestframework-httpsignature][djangorestframework-httpsignature] - Provides an easy to use HTTP Signature Authentication mechanism. * [djangorestframework-httpsignature][djangorestframework-httpsignature] - Provides an easy to use HTTP Signature Authentication mechanism.
* [djoser][djoser] - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation. * [djoser][djoser] - Provides a set of views to handle basic actions such as registration, login, logout, password reset and account activation.
* [django-rest-auth][django-rest-auth] - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. * [dj-rest-auth][dj-rest-auth] - Provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc.
* [drf-oidc-auth][drf-oidc-auth] - Implements OpenID Connect token authentication for DRF. * [drf-oidc-auth][drf-oidc-auth] - Implements OpenID Connect token authentication for DRF.
* [drfpasswordless][drfpasswordless] - Adds (Medium, Square Cash inspired) passwordless logins and signups via email and mobile numbers. * [drfpasswordless][drfpasswordless] - Adds (Medium, Square Cash inspired) passwordless logins and signups via email and mobile numbers.
* [django-rest-authemail][django-rest-authemail] - Provides a RESTful API for user signup and authentication using email addresses.
* [dango-pyoidc][django-pyoidc] adds support for OpenID Connect (OIDC) authentication.
### Permissions ### Permissions
@ -199,6 +70,8 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
* [djangorestframework-composed-permissions][djangorestframework-composed-permissions] - Provides a simple way to define complex permissions. * [djangorestframework-composed-permissions][djangorestframework-composed-permissions] - Provides a simple way to define complex permissions.
* [rest_condition][rest-condition] - Another extension for building complex permissions in a simple and convenient way. * [rest_condition][rest-condition] - Another extension for building complex permissions in a simple and convenient way.
* [dry-rest-permissions][dry-rest-permissions] - Provides a simple way to define permissions for individual api actions. * [dry-rest-permissions][dry-rest-permissions] - Provides a simple way to define permissions for individual api actions.
* [drf-access-policy][drf-access-policy] - Declarative and flexible permissions inspired by AWS' IAM policies.
* [drf-psq][drf-psq] - An extension that gives support for having action-based **permission_classes**, **serializer_class**, and **queryset** dependent on permission-based rules.
### Serializers ### Serializers
@ -210,17 +83,23 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
* [django-rest-framework-serializer-extensions][drf-serializer-extensions] - * [django-rest-framework-serializer-extensions][drf-serializer-extensions] -
Enables black/whitelisting fields, and conditionally expanding child serializers on a per-view/request basis. Enables black/whitelisting fields, and conditionally expanding child serializers on a per-view/request basis.
* [djangorestframework-queryfields][djangorestframework-queryfields] - Serializer mixin allowing clients to control which fields will be sent in the API response. * [djangorestframework-queryfields][djangorestframework-queryfields] - Serializer mixin allowing clients to control which fields will be sent in the API response.
* [drf-flex-fields][drf-flex-fields] - Serializer providing dynamic field expansion and sparse field sets via URL parameters.
* [drf-action-serializer][drf-action-serializer] - Serializer providing per-action fields config for use with ViewSets to prevent having to write multiple serializers.
* [djangorestframework-dataclasses][djangorestframework-dataclasses] - Serializer providing automatic field generation for Python dataclasses, like the built-in ModelSerializer does for models.
* [django-restql][django-restql] - Turn your REST API into a GraphQL like API(It allows clients to control which fields will be sent in a response, uses GraphQL like syntax, supports read and write on both flat and nested fields).
* [graphwrap][graphwrap] - Transform your REST API into a fully compliant GraphQL API with just two lines of code. Leverages [Graphene-Django](https://docs.graphene-python.org/projects/django/en/latest/) to dynamically build, at runtime, a GraphQL ObjectType for each view in your API.
### Serializer fields ### Serializer fields
* [drf-compound-fields][drf-compound-fields] - Provides "compound" serializer fields, such as lists of simple values. * [drf-compound-fields][drf-compound-fields] - Provides "compound" serializer fields, such as lists of simple values.
* [django-extra-fields][django-extra-fields] - Provides extra serializer fields. * [drf-extra-fields][drf-extra-fields] - Provides extra serializer fields.
* [django-versatileimagefield][django-versatileimagefield] - Provides a drop-in replacement for Django's stock `ImageField` that makes it easy to serve images in multiple sizes/renditions from a single field. For DRF-specific implementation docs, [click here][django-versatileimagefield-drf-docs]. * [django-versatileimagefield][django-versatileimagefield] - Provides a drop-in replacement for Django's stock `ImageField` that makes it easy to serve images in multiple sizes/renditions from a single field. For DRF-specific implementation docs, [click here][django-versatileimagefield-drf-docs].
### Views ### Views
* [djangorestframework-bulk][djangorestframework-bulk] - Implements generic view mixins as well as some common concrete generic views to allow to apply bulk operations via API requests.
* [django-rest-multiple-models][django-rest-multiple-models] - Provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request. * [django-rest-multiple-models][django-rest-multiple-models] - Provides a generic view (and mixin) for sending multiple serialized models and/or querysets via a single API request.
* [drf-typed-views][drf-typed-views] - Use Python type annotations to validate/deserialize request parameters. Inspired by API Star, Hug and FastAPI.
* [rest-framework-actions][rest-framework-actions] - Provides control over each action in ViewSets. Serializers per action, method.
### Routers ### Routers
@ -232,12 +111,13 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
* [djangorestframework-msgpack][djangorestframework-msgpack] - Provides MessagePack renderer and parser support. * [djangorestframework-msgpack][djangorestframework-msgpack] - Provides MessagePack renderer and parser support.
* [djangorestframework-jsonapi][djangorestframework-jsonapi] - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec. * [djangorestframework-jsonapi][djangorestframework-jsonapi] - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec.
* [djangorestframework-camel-case][djangorestframework-camel-case] - Provides camel case JSON renderers and parsers. * [djangorestframework-camel-case][djangorestframework-camel-case] - Provides camel case JSON renderers and parsers.
* [nested-multipart-parser][nested-multipart-parser] - Provides nested parser for http multipart request
### Renderers ### Renderers
* [djangorestframework-csv][djangorestframework-csv] - Provides CSV renderer support. * [djangorestframework-csv][djangorestframework-csv] - Provides CSV renderer support.
* [djangorestframework-jsonapi][djangorestframework-jsonapi] - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec. * [djangorestframework-jsonapi][djangorestframework-jsonapi] - Provides a parser, renderer, serializers, and other tools to help build an API that is compliant with the jsonapi.org spec.
* [drf_ujson][drf_ujson] - Implements JSON rendering using the UJSON package. * [drf_ujson2][drf_ujson2] - Implements JSON rendering using the UJSON package.
* [rest-pandas][rest-pandas] - Pandas DataFrame-powered renderers including Excel, CSV, and SVG formats. * [rest-pandas][rest-pandas] - Pandas DataFrame-powered renderers including Excel, CSV, and SVG formats.
* [djangorestframework-rapidjson][djangorestframework-rapidjson] - Provides rapidjson support with parser and renderer. * [djangorestframework-rapidjson][djangorestframework-rapidjson] - Provides rapidjson support with parser and renderer.
@ -246,12 +126,13 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
* [djangorestframework-chain][djangorestframework-chain] - Allows arbitrary chaining of both relations and lookup filters. * [djangorestframework-chain][djangorestframework-chain] - Allows arbitrary chaining of both relations and lookup filters.
* [django-url-filter][django-url-filter] - Allows a safe way to filter data via human-friendly URLs. It is a generic library which is not tied to DRF but it provides easy integration with DRF. * [django-url-filter][django-url-filter] - Allows a safe way to filter data via human-friendly URLs. It is a generic library which is not tied to DRF but it provides easy integration with DRF.
* [drf-url-filter][drf-url-filter] is a simple Django app to apply filters on drf `ModelViewSet`'s `Queryset` in a clean, simple and configurable way. It also supports validations on incoming query params and their values. * [drf-url-filter][drf-url-filter] is a simple Django app to apply filters on drf `ModelViewSet`'s `Queryset` in a clean, simple and configurable way. It also supports validations on incoming query params and their values.
* [django-rest-framework-guardian][django-rest-framework-guardian] - Provides integration with django-guardian, including the `DjangoObjectPermissionsFilter` previously found in DRF.
### Misc ### Misc
* [drf-sendables][drf-sendables] - User messages for Django REST Framework
* [cookiecutter-django-rest][cookiecutter-django-rest] - A cookiecutter template that takes care of the setup and configuration so you can focus on making your REST apis awesome. * [cookiecutter-django-rest][cookiecutter-django-rest] - A cookiecutter template that takes care of the setup and configuration so you can focus on making your REST apis awesome.
* [djangorestrelationalhyperlink][djangorestrelationalhyperlink] - A hyperlinked serialiser that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer. * [djangorestrelationalhyperlink][djangorestrelationalhyperlink] - A hyperlinked serializer that can can be used to alter relationships via hyperlinks, but otherwise like a hyperlink model serializer.
* [django-rest-swagger][django-rest-swagger] - An API documentation generator for Swagger UI.
* [django-rest-framework-proxy][django-rest-framework-proxy] - Proxy to redirect incoming request to another API server. * [django-rest-framework-proxy][django-rest-framework-proxy] - Proxy to redirect incoming request to another API server.
* [gaiarestframework][gaiarestframework] - Utils for django-rest-framework * [gaiarestframework][gaiarestframework] - Utils for django-rest-framework
* [drf-extensions][drf-extensions] - A collection of custom extensions * [drf-extensions][drf-extensions] - A collection of custom extensions
@ -264,27 +145,42 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
* [django-rest-framework-version-transforms][django-rest-framework-version-transforms] - Enables the use of delta transformations for versioning of DRF resource representations. * [django-rest-framework-version-transforms][django-rest-framework-version-transforms] - Enables the use of delta transformations for versioning of DRF resource representations.
* [django-rest-messaging][django-rest-messaging], [django-rest-messaging-centrifugo][django-rest-messaging-centrifugo] and [django-rest-messaging-js][django-rest-messaging-js] - A real-time pluggable messaging service using DRM. * [django-rest-messaging][django-rest-messaging], [django-rest-messaging-centrifugo][django-rest-messaging-centrifugo] and [django-rest-messaging-js][django-rest-messaging-js] - A real-time pluggable messaging service using DRM.
* [djangorest-alchemy][djangorest-alchemy] - SQLAlchemy support for REST framework. * [djangorest-alchemy][djangorest-alchemy] - SQLAlchemy support for REST framework.
* [djangorestframework-datatables][djangorestframework-datatables] - Seamless integration between Django REST framework and [Datatables](https://datatables.net).
* [django-rest-framework-condition][django-rest-framework-condition] - Decorators for managing HTTP cache headers for Django REST framework (ETag and Last-modified).
* [django-rest-witchcraft][django-rest-witchcraft] - Provides DRF integration with SQLAlchemy with SQLAlchemy model serializers/viewsets and a bunch of other goodies
* [djangorestframework-mvt][djangorestframework-mvt] - An extension for creating views that serve Postgres data as Map Box Vector Tiles.
* [drf-viewset-profiler][drf-viewset-profiler] - Lib to profile all methods from a viewset line by line.
* [djangorestframework-features][djangorestframework-features] - Advanced schema generation and more based on named features.
* [django-elasticsearch-dsl-drf][django-elasticsearch-dsl-drf] - Integrate Elasticsearch DSL with Django REST framework. Package provides views, serializers, filter backends, pagination and other handy add-ons.
* [django-api-client][django-api-client] - DRF client that groups the Endpoint response, for use in CBVs and FBV as if you were working with Django's Native Models..
* [fast-drf] - A model based library for making API development faster and easier.
* [django-requestlogs] - Providing middleware and other helpers for audit logging for REST framework.
* [drf-standardized-errors][drf-standardized-errors] - DRF exception handler to standardize error responses for all API endpoints.
* [drf-api-action][drf-api-action] - uses the power of DRF also as a library functions
### Customization
* [drf-restwind][drf-restwind] - a modern re-imagining of the Django REST Framework utilizes TailwindCSS and DaisyUI to provide flexible and customizable UI solutions with minimal coding effort.
* [drf-redesign][drf-redesign] - A project that gives a fresh look to the browse-able API using Bootstrap 5.
* [drf-material][drf-material] - A project that gives a sleek and elegant look to the browsable API using Material Design.
[drf-sendables]: https://github.com/amikrop/drf-sendables
[cite]: http://www.software-ecosystems.com/Software_Ecosystems/Ecosystems.html [cite]: http://www.software-ecosystems.com/Software_Ecosystems/Ecosystems.html
[cookiecutter]: https://github.com/jpadilla/cookiecutter-django-rest-framework [cookiecutter]: https://github.com/jpadilla/cookiecutter-django-rest-framework
[new-repo]: https://github.com/new [new-repo]: https://github.com/new
[create-a-repo]: https://help.github.com/articles/create-a-repo/ [create-a-repo]: https://help.github.com/articles/create-a-repo/
[travis-ci]: https://travis-ci.org [pypi-register]: https://pypi.org/account/register/
[travis-profile]: https://travis-ci.org/profile
[pypi-register]: https://pypi.python.org/pypi?%3Aaction=register_form
[semver]: https://semver.org/ [semver]: https://semver.org/
[tox-docs]: https://tox.readthedocs.io/en/latest/ [tox-docs]: https://tox.readthedocs.io/en/latest/
[drf-compat]: https://github.com/encode/django-rest-framework/blob/master/rest_framework/compat.py [drf-compat]: https://github.com/encode/django-rest-framework/blob/master/rest_framework/compat.py
[rest-framework-grid]: https://www.djangopackages.com/grids/g/django-rest-framework/ [rest-framework-grid]: https://www.djangopackages.com/grids/g/django-rest-framework/
[drf-create-pr]: https://github.com/encode/django-rest-framework/compare [drf-create-pr]: https://github.com/encode/django-rest-framework/compare
[drf-create-issue]: https://github.com/encode/django-rest-framework/issues/new
[authentication]: ../api-guide/authentication.md [authentication]: ../api-guide/authentication.md
[permissions]: ../api-guide/permissions.md [permissions]: ../api-guide/permissions.md
[third-party-packages]: ../topics/third-party-packages/#existing-third-party-packages [third-party-packages]: ../topics/third-party-packages/#existing-third-party-packages
[discussion-group]: https://groups.google.com/forum/#!forum/django-rest-framework [discussion-group]: https://groups.google.com/forum/#!forum/django-rest-framework
[djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth
[django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit [django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit
[doac]: https://github.com/Rediker-Software/doac
[djangorestframework-jwt]: https://github.com/GetBlimp/django-rest-framework-jwt [djangorestframework-jwt]: https://github.com/GetBlimp/django-rest-framework-jwt
[djangorestframework-simplejwt]: https://github.com/davesque/django-rest-framework-simplejwt [djangorestframework-simplejwt]: https://github.com/davesque/django-rest-framework-simplejwt
[hawkrest]: https://github.com/kumar303/hawkrest [hawkrest]: https://github.com/kumar303/hawkrest
@ -297,33 +193,32 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
[djangorestframework-gis]: https://github.com/djangonauts/django-rest-framework-gis [djangorestframework-gis]: https://github.com/djangonauts/django-rest-framework-gis
[djangorestframework-hstore]: https://github.com/djangonauts/django-rest-framework-hstore [djangorestframework-hstore]: https://github.com/djangonauts/django-rest-framework-hstore
[drf-compound-fields]: https://github.com/estebistec/drf-compound-fields [drf-compound-fields]: https://github.com/estebistec/drf-compound-fields
[django-extra-fields]: https://github.com/Hipo/drf-extra-fields [drf-extra-fields]: https://github.com/Hipo/drf-extra-fields
[djangorestframework-bulk]: https://github.com/miki725/django-rest-framework-bulk
[django-rest-multiple-models]: https://github.com/MattBroach/DjangoRestMultipleModels [django-rest-multiple-models]: https://github.com/MattBroach/DjangoRestMultipleModels
[drf-nested-routers]: https://github.com/alanjds/drf-nested-routers [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers
[wq.db.rest]: https://wq.io/docs/about-rest [wq.db.rest]: https://wq.io/docs/about-rest
[djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack [djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack
[djangorestframework-camel-case]: https://github.com/vbabiy/djangorestframework-camel-case [djangorestframework-camel-case]: https://github.com/vbabiy/djangorestframework-camel-case
[nested-multipart-parser]: https://github.com/remigermain/nested-multipart-parser
[djangorestframework-csv]: https://github.com/mjumbewu/django-rest-framework-csv [djangorestframework-csv]: https://github.com/mjumbewu/django-rest-framework-csv
[drf_ujson]: https://github.com/gizmag/drf-ujson-renderer [drf_ujson2]: https://github.com/Amertz08/drf_ujson2
[rest-pandas]: https://github.com/wq/django-rest-pandas [rest-pandas]: https://github.com/wq/django-rest-pandas
[djangorestframework-rapidjson]: https://github.com/allisson/django-rest-framework-rapidjson [djangorestframework-rapidjson]: https://github.com/allisson/django-rest-framework-rapidjson
[djangorestframework-chain]: https://github.com/philipn/django-rest-framework-chain [djangorestframework-chain]: https://github.com/philipn/django-rest-framework-chain
[djangorestrelationalhyperlink]: https://github.com/fredkingham/django_rest_model_hyperlink_serializers_project [djangorestrelationalhyperlink]: https://github.com/fredkingham/django_rest_model_hyperlink_serializers_project
[django-rest-swagger]: https://github.com/marcgibbons/django-rest-swagger
[django-rest-framework-proxy]: https://github.com/eofs/django-rest-framework-proxy [django-rest-framework-proxy]: https://github.com/eofs/django-rest-framework-proxy
[gaiarestframework]: https://github.com/AppsFuel/gaiarestframework [gaiarestframework]: https://github.com/AppsFuel/gaiarestframework
[drf-extensions]: https://github.com/chibisov/drf-extensions [drf-extensions]: https://github.com/chibisov/drf-extensions
[ember-django-adapter]: https://github.com/dustinfarris/ember-django-adapter [ember-django-adapter]: https://github.com/dustinfarris/ember-django-adapter
[django-rest-auth]: https://github.com/Tivix/django-rest-auth/ [dj-rest-auth]: https://github.com/iMerica/dj-rest-auth
[django-versatileimagefield]: https://github.com/WGBH/django-versatileimagefield [django-versatileimagefield]: https://github.com/WGBH/django-versatileimagefield
[django-versatileimagefield-drf-docs]:https://django-versatileimagefield.readthedocs.io/en/latest/drf_integration.html [django-versatileimagefield-drf-docs]:https://django-versatileimagefield.readthedocs.io/en/latest/drf_integration.html
[drf-tracking]: https://github.com/aschn/drf-tracking [drf-tracking]: https://github.com/aschn/drf-tracking
[django-rest-framework-braces]: https://github.com/dealertrack/django-rest-framework-braces [django-rest-framework-braces]: https://github.com/dealertrack/django-rest-framework-braces
[dry-rest-permissions]: https://github.com/Helioscene/dry-rest-permissions [dry-rest-permissions]: https://github.com/FJNR-inc/dry-rest-permissions
[django-url-filter]: https://github.com/miki725/django-url-filter [django-url-filter]: https://github.com/miki725/django-url-filter
[drf-url-filter]: https://github.com/manjitkumar/drf-url-filters [drf-url-filter]: https://github.com/manjitkumar/drf-url-filters
[cookiecutter-django-rest]: https://github.com/agconti/cookiecutter-django-rest [cookiecutter-django-rest]: https://github.com/agconti/cookiecutter-django-rest
[drf-haystack]: https://drf-haystack.readthedocs.io/en/latest/ [drf-haystack]: https://drf-haystack.readthedocs.io/en/latest/
[django-rest-framework-version-transforms]: https://github.com/mrhwick/django-rest-framework-version-transforms [django-rest-framework-version-transforms]: https://github.com/mrhwick/django-rest-framework-version-transforms
[djangorestframework-jsonapi]: https://github.com/django-json-api/django-rest-framework-json-api [djangorestframework-jsonapi]: https://github.com/django-json-api/django-rest-framework-json-api
@ -337,3 +232,30 @@ To submit new content, [open an issue][drf-create-issue] or [create a pull reque
[djangorestframework-queryfields]: https://github.com/wimglenn/djangorestframework-queryfields [djangorestframework-queryfields]: https://github.com/wimglenn/djangorestframework-queryfields
[drfpasswordless]: https://github.com/aaronn/django-rest-framework-passwordless [drfpasswordless]: https://github.com/aaronn/django-rest-framework-passwordless
[djangorest-alchemy]: https://github.com/dealertrack/djangorest-alchemy [djangorest-alchemy]: https://github.com/dealertrack/djangorest-alchemy
[djangorestframework-datatables]: https://github.com/izimobil/django-rest-framework-datatables
[django-rest-framework-condition]: https://github.com/jozo/django-rest-framework-condition
[django-rest-witchcraft]: https://github.com/shosca/django-rest-witchcraft
[drf-access-policy]: https://github.com/rsinger86/drf-access-policy
[drf-flex-fields]: https://github.com/rsinger86/drf-flex-fields
[drf-typed-views]: https://github.com/rsinger86/drf-typed-views
[drf-action-serializer]: https://github.com/gregschmit/drf-action-serializer
[djangorestframework-dataclasses]: https://github.com/oxan/djangorestframework-dataclasses
[django-restql]: https://github.com/yezyilomo/django-restql
[djangorestframework-mvt]: https://github.com/corteva/djangorestframework-mvt
[django-rest-framework-guardian]: https://github.com/rpkilby/django-rest-framework-guardian
[drf-viewset-profiler]: https://github.com/fvlima/drf-viewset-profiler
[djangorestframework-features]: https://github.com/cloudcode-hungary/django-rest-framework-features/
[django-elasticsearch-dsl-drf]: https://github.com/barseghyanartur/django-elasticsearch-dsl-drf
[django-api-client]: https://github.com/rhenter/django-api-client
[drf-psq]: https://github.com/drf-psq/drf-psq
[django-rest-authemail]: https://github.com/celiao/django-rest-authemail
[graphwrap]: https://github.com/PaulGilmartin/graph_wrap
[rest-framework-actions]: https://github.com/AlexisMunera98/rest-framework-actions
[fast-drf]: https://github.com/iashraful/fast-drf
[django-requestlogs]: https://github.com/Raekkeri/django-requestlogs
[drf-standardized-errors]: https://github.com/ghazi-git/drf-standardized-errors
[drf-api-action]: https://github.com/Ori-Roza/drf-api-action
[drf-restwind]: https://github.com/youzarsiph/drf-restwind
[drf-redesign]: https://github.com/youzarsiph/drf-redesign
[drf-material]: https://github.com/youzarsiph/drf-material
[django-pyoidc]: https://github.com/makinacorpus/django_pyoidc

View File

@ -11,14 +11,23 @@ There are a wide range of resources available for learning and using Django REST
<a class="book-cover" href="https://www.twoscoopspress.com/products/two-scoops-of-django-1-11"> <a class="book-cover" href="https://www.twoscoopspress.com/products/two-scoops-of-django-1-11">
<img src="../../img/books/tsd-cover.png"/> <img src="../../img/books/tsd-cover.png"/>
</a> </a>
<a class="book-cover" href="https://djangoforapis.com">
<img src="../../img/books/dfa-40-cover.jpg"/>
</a>
<a class="book-cover" href="https://books.agiliq.com/projects/django-api-polls-tutorial/en/latest/">
<img src="../../img/books/bda-cover.png"/>
</a>
</div> </div>
## Courses
* [Developing RESTful APIs with Django REST Framework][developing-restful-apis-with-django-rest-framework]
## Tutorials ## Tutorials
* [Beginner's Guide to the Django REST Framework][beginners-guide-to-the-django-rest-framework] * [Beginner's Guide to the Django REST Framework][beginners-guide-to-the-django-rest-framework]
* [Django REST Framework - An Introduction][drf-an-intro] * [Django REST Framework - An Introduction][drf-an-intro]
* [Django REST Framework Tutorial][drf-tutorial] * [Django REST Framework Tutorial][drf-tutorial]
* [Django REST Framework Course][django-rest-framework-course]
* [Building a RESTful API with Django REST Framework][building-a-restful-api-with-drf] * [Building a RESTful API with Django REST Framework][building-a-restful-api-with-drf]
* [Getting Started with Django REST Framework and AngularJS][getting-started-with-django-rest-framework-and-angularjs] * [Getting Started with Django REST Framework and AngularJS][getting-started-with-django-rest-framework-and-angularjs]
* [End to End Web App with Django REST Framework & AngularJS][end-to-end-web-app-with-django-rest-framework-angularjs] * [End to End Web App with Django REST Framework & AngularJS][end-to-end-web-app-with-django-rest-framework-angularjs]
@ -29,8 +38,10 @@ There are a wide range of resources available for learning and using Django REST
* [Check Credentials Using Django REST Framework][check-credentials-using-django-rest-framework] * [Check Credentials Using Django REST Framework][check-credentials-using-django-rest-framework]
* [Creating a Production Ready API with Python and Django REST Framework Part 1][creating-a-production-ready-api-with-python-and-drf-part1] * [Creating a Production Ready API with Python and Django REST Framework Part 1][creating-a-production-ready-api-with-python-and-drf-part1]
* [Creating a Production Ready API with Python and Django REST Framework Part 2][creating-a-production-ready-api-with-python-and-drf-part2] * [Creating a Production Ready API with Python and Django REST Framework Part 2][creating-a-production-ready-api-with-python-and-drf-part2]
* [Django REST Framework Tutorial - Build a Blog API][django-rest-framework-tutorial-build-a-blog] * [Creating a Production Ready API with Python and Django REST Framework Part 3][creating-a-production-ready-api-with-python-and-drf-part3]
* [Django REST Framework & React Tutorial - Build a Todo List API][django-rest-framework-react-tutorial-build-a-todo-list] * [Creating a Production Ready API with Python and Django REST Framework Part 4][creating-a-production-ready-api-with-python-and-drf-part4]
* [Django Polls Tutorial API][django-polls-api]
* [Django REST Framework Tutorial: Todo API][django-rest-framework-todo-api]
* [Tutorial: Django REST with React (Django 2.0)][django-rest-react-valentinog] * [Tutorial: Django REST with React (Django 2.0)][django-rest-react-valentinog]
@ -39,11 +50,11 @@ There are a wide range of resources available for learning and using Django REST
### Talks ### Talks
* [Level Up! Rethinking the Web API Framework][pycon-us-2017] * [Level Up! Rethinking the Web API Framework][pycon-us-2017]
* [How to Make a Full Fledged REST API with Django OAuth Toolkit][full-fledged-rest-api-with-django-oauth-tookit] * [How to Make a Full Fledged REST API with Django OAuth Toolkit][full-fledged-rest-api-with-django-oauth-toolkit]
* [Django REST API - So Easy You Can Learn It in 25 Minutes][django-rest-api-so-easy] * [Django REST API - So Easy You Can Learn It in 25 Minutes][django-rest-api-so-easy]
* [Tom Christie about Django Rest Framework at Django: Under The Hood][django-under-hood-2014] * [Tom Christie about Django Rest Framework at Django: Under The Hood][django-under-hood-2014]
* [Django REST Framework: Schemas, Hypermedia & Client Libraries][pycon-uk-2016] * [Django REST Framework: Schemas, Hypermedia & Client Libraries][pycon-uk-2016]
* [Finally Understand Authentication in Django REST Framework][django-con-2018]
### Tutorials ### Tutorials
@ -70,6 +81,7 @@ There are a wide range of resources available for learning and using Django REST
* [Chatbot Using Django REST Framework + api.ai + SlackPart 1/3][chatbot-using-drf-part1] * [Chatbot Using Django REST Framework + api.ai + SlackPart 1/3][chatbot-using-drf-part1]
* [New Django Admin with DRF and EmberJS... What are the News?][new-django-admin-with-drf-and-emberjs] * [New Django Admin with DRF and EmberJS... What are the News?][new-django-admin-with-drf-and-emberjs]
* [Blog posts about Django REST Framework][medium-django-rest-framework] * [Blog posts about Django REST Framework][medium-django-rest-framework]
* [Implementing Rest APIs With Embedded Privacy][doordash-implementing-rest-apis]
### Documentations ### Documentations
* [Classy Django REST Framework][cdrf.co] * [Classy Django REST Framework][cdrf.co]
@ -79,37 +91,38 @@ Want your Django REST Framework talk/tutorial/article to be added to our website
[beginners-guide-to-the-django-rest-framework]: https://code.tutsplus.com/tutorials/beginners-guide-to-the-django-rest-framework--cms-19786 [beginners-guide-to-the-django-rest-framework]: https://code.tutsplus.com/tutorials/beginners-guide-to-the-django-rest-framework--cms-19786
[getting-started-with-django-rest-framework-and-angularjs]: http://blog.kevinastone.com/getting-started-with-django-rest-framework-and-angularjs.html [getting-started-with-django-rest-framework-and-angularjs]: https://blog.kevinastone.com/django-rest-framework-and-angular-js
[end-to-end-web-app-with-django-rest-framework-angularjs]: http://mourafiq.com/2013/07/01/end-to-end-web-app-with-django-angular-1.html [end-to-end-web-app-with-django-rest-framework-angularjs]: https://mourafiq.com/2013/07/01/end-to-end-web-app-with-django-angular-1.html
[start-your-api-django-rest-framework-part-1]: https://godjango.com/41-start-your-api-django-rest-framework-part-1/ [start-your-api-django-rest-framework-part-1]: https://www.youtube.com/watch?v=hqo2kk91WpE
[permissions-authentication-django-rest-framework-part-2]: https://godjango.com/43-permissions-authentication-django-rest-framework-part-2/ [permissions-authentication-django-rest-framework-part-2]: https://www.youtube.com/watch?v=R3xvUDUZxGU
[viewsets-and-routers-django-rest-framework-part-3]: https://godjango.com/45-viewsets-and-routers-django-rest-framework-part-3/ [viewsets-and-routers-django-rest-framework-part-3]: https://www.youtube.com/watch?v=2d6w4DGQ4OU
[django-rest-framework-user-endpoint]: https://richardtier.com/2014/02/25/django-rest-framework-user-endpoint/ [django-rest-framework-user-endpoint]: https://richardtier.com/2014/02/25/django-rest-framework-user-endpoint/
[check-credentials-using-django-rest-framework]: https://richardtier.com/2014/03/06/110/ [check-credentials-using-django-rest-framework]: https://richardtier.com/2014/03/06/110/
[ember-and-django-part 1-video]: http://www.neckbeardrepublic.com/screencasts/ember-and-django-part-1 [ember-and-django-part 1-video]: http://www.neckbeardrepublic.com/screencasts/ember-and-django-part-1
[django-rest-framework-part-1-video]: http://www.neckbeardrepublic.com/screencasts/django-rest-framework-part-1 [django-rest-framework-part-1-video]: http://www.neckbeardrepublic.com/screencasts/django-rest-framework-part-1
[web-api-performance-profiling-django-rest-framework]: https://www.dabapps.com/blog/api-performance-profiling-django-rest-framework/ [web-api-performance-profiling-django-rest-framework]: https://www.dabapps.com/blog/api-performance-profiling-django-rest-framework/
[api-development-with-django-and-django-rest-framework]: https://bnotions.com/api-development-with-django-and-django-rest-framework/ [api-development-with-django-and-django-rest-framework]: https://bnotions.com/news-and-insights/api-development-with-django-and-django-rest-framework/
[cdrf.co]:http://www.cdrf.co [cdrf.co]:http://www.cdrf.co
[medium-django-rest-framework]: https://medium.com/django-rest-framework [medium-django-rest-framework]: https://medium.com/django-rest-framework
[django-rest-framework-course]: https://teamtreehouse.com/library/django-rest-framework
[pycon-uk-2016]: https://www.youtube.com/watch?v=FjmiGh7OqVg [pycon-uk-2016]: https://www.youtube.com/watch?v=FjmiGh7OqVg
[django-under-hood-2014]: https://www.youtube.com/watch?v=3cSsbe-tA0E [django-under-hood-2014]: https://www.youtube.com/watch?v=3cSsbe-tA0E
[integrating-pandas-drf-and-bokeh]: https://machinalis.com/blog/pandas-django-rest-framework-bokeh/ [integrating-pandas-drf-and-bokeh]: https://web.archive.org/web/20180104205117/http://machinalis.com/blog/pandas-django-rest-framework-bokeh/
[controlling-uncertainty-on-web-apps-and-apis]: https://machinalis.com/blog/controlling-uncertainty-on-web-applications-and-apis/ [controlling-uncertainty-on-web-apps-and-apis]: https://web.archive.org/web/20180104205043/https://machinalis.com/blog/controlling-uncertainty-on-web-applications-and-apis/
[full-text-search-in-drf]: https://machinalis.com/blog/full-text-search-on-django-rest-framework/ [full-text-search-in-drf]: https://web.archive.org/web/20180104205059/http://machinalis.com/blog/full-text-search-on-django-rest-framework/
[oauth2-authentication-with-drf]: https://machinalis.com/blog/oauth2-authentication/ [oauth2-authentication-with-drf]: https://web.archive.org/web/20180104205054/http://machinalis.com/blog/oauth2-authentication/
[nested-resources-with-drf]: https://machinalis.com/blog/nested-resources-with-django/ [nested-resources-with-drf]: https://web.archive.org/web/20180104205109/http://machinalis.com/blog/nested-resources-with-django/
[image-fields-with-drf]: https://machinalis.com/blog/image-fields-with-django-rest-framework/ [image-fields-with-drf]: https://web.archive.org/web/20180104205048/http://machinalis.com/blog/image-fields-with-django-rest-framework/
[chatbot-using-drf-part1]: https://chatbotslife.com/chatbot-using-django-rest-framework-api-ai-slack-part-1-3-69c7e38b7b1e#.g2aceuncf [chatbot-using-drf-part1]: https://chatbotslife.com/chatbot-using-django-rest-framework-api-ai-slack-part-1-3-69c7e38b7b1e#.g2aceuncf
[new-django-admin-with-drf-and-emberjs]: https://blog.levit.be/new-django-admin-with-emberjs-what-are-the-news/ [new-django-admin-with-drf-and-emberjs]: https://blog.levit.be/new-django-admin-with-emberjs-what-are-the-news/
[drf-schema]: https://drf-schema-adapter.readthedocs.io/en/latest/ [drf-schema]: https://drf-schema-adapter.readthedocs.io/en/latest/
[creating-a-production-ready-api-with-python-and-drf-part1]: https://www.andreagrandi.it/2016/09/28/creating-production-ready-api-python-django-rest-framework-part-1/ [creating-a-production-ready-api-with-python-and-drf-part1]: https://www.andreagrandi.it/posts/creating-production-ready-api-python-django-rest-framework-part-1/
[creating-a-production-ready-api-with-python-and-drf-part2]: https://www.andreagrandi.it/2016/10/01/creating-a-production-ready-api-with-python-and-django-rest-framework-part-2/ [creating-a-production-ready-api-with-python-and-drf-part2]: https://www.andreagrandi.it/posts/creating-a-production-ready-api-with-python-and-django-rest-framework-part-2/
[django-rest-framework-tutorial-build-a-blog]: https://wsvincent.com/django-rest-framework-tutorial/ [creating-a-production-ready-api-with-python-and-drf-part3]: https://www.andreagrandi.it/posts/creating-a-production-ready-api-with-python-and-django-rest-framework-part-3/
[django-rest-framework-react-tutorial-build-a-todo-list]: https://wsvincent.com/django-rest-framework-react-tutorial/ [creating-a-production-ready-api-with-python-and-drf-part4]: https://www.andreagrandi.it/posts/creating-a-production-ready-api-with-python-and-django-rest-framework-part-4/
[django-polls-api]: https://learndjango.com/tutorials/django-polls-tutorial-api
[django-rest-framework-todo-api]: https://learndjango.com/tutorials/django-rest-framework-tutorial-todo-api
[django-rest-api-so-easy]: https://www.youtube.com/watch?v=cqP758k1BaQ [django-rest-api-so-easy]: https://www.youtube.com/watch?v=cqP758k1BaQ
[full-fledged-rest-api-with-django-oauth-tookit]: https://www.youtube.com/watch?v=M6Ud3qC2tTk [full-fledged-rest-api-with-django-oauth-toolkit]: https://www.youtube.com/watch?v=M6Ud3qC2tTk
[drf-in-your-pjs]: https://www.youtube.com/watch?v=xMtHsWa72Ww [drf-in-your-pjs]: https://www.youtube.com/watch?v=xMtHsWa72Ww
[building-a-rest-api-using-django-and-drf]: https://www.youtube.com/watch?v=PwssEec3IRw [building-a-rest-api-using-django-and-drf]: https://www.youtube.com/watch?v=PwssEec3IRw
[drf-tutorials]: https://www.youtube.com/watch?v=axRCBgbOJp8&list=PLJtp8Jm8EDzjgVg9vVyIUMoGyqtegj7FH [drf-tutorials]: https://www.youtube.com/watch?v=axRCBgbOJp8&list=PLJtp8Jm8EDzjgVg9vVyIUMoGyqtegj7FH
@ -122,3 +135,6 @@ Want your Django REST Framework talk/tutorial/article to be added to our website
[anna-email]: mailto:anna@django-rest-framework.org [anna-email]: mailto:anna@django-rest-framework.org
[pycon-us-2017]: https://www.youtube.com/watch?v=Rk6MHZdust4 [pycon-us-2017]: https://www.youtube.com/watch?v=Rk6MHZdust4
[django-rest-react-valentinog]: https://www.valentinog.com/blog/tutorial-api-django-rest-react/ [django-rest-react-valentinog]: https://www.valentinog.com/blog/tutorial-api-django-rest-react/
[doordash-implementing-rest-apis]: https://doordash.engineering/2013/10/07/implementing-rest-apis-with-embedded-privacy/
[developing-restful-apis-with-django-rest-framework]: https://testdriven.io/courses/django-rest-framework/
[django-con-2018]: https://youtu.be/pY-oje5b5Qk?si=AOU6tLi0IL1_pVzq

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
docs/img/build-status.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

BIN
docs/img/drf-m-api-root.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

BIN
docs/img/drf-r-api-root.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 567 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Some files were not shown because too many files have changed in this diff Show More