├── tests
├── __init__.py
├── schemas
│ ├── __init__.py
│ └── test_get_schema_view.py
├── authentication
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ │ └── 0001_initial.py
│ └── models.py
├── browsable_api
│ ├── __init__.py
│ ├── no_auth_urls.py
│ ├── auth_urls.py
│ ├── views.py
│ └── test_browsable_nested_api.py
├── generic_relations
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ │ └── 0001_initial.py
│ ├── models.py
│ └── test_generic_relations.py
├── urls.py
├── test_templates.py
├── importable
│ ├── test_installed.py
│ └── __init__.py
├── test_write_only_fields.py
├── test_status.py
├── test_one_to_one_with_inheritance.py
├── test_lazy_hyperlinks.py
├── test_reverse.py
├── utils.py
├── test_settings.py
├── test_prefetch_related.py
├── test_multitable_inheritance.py
└── test_middleware.py
├── rest_framework
├── utils
│ ├── __init__.py
│ ├── urls.py
│ ├── json.py
│ ├── humanize_datetime.py
│ ├── breadcrumbs.py
│ ├── html.py
│ └── encoders.py
├── management
│ ├── __init__.py
│ └── commands
│ │ └── __init__.py
├── templatetags
│ └── __init__.py
├── authtoken
│ ├── management
│ │ ├── __init__.py
│ │ └── commands
│ │ │ ├── __init__.py
│ │ │ └── drf_create_token.py
│ ├── migrations
│ │ ├── __init__.py
│ │ ├── 0001_initial.py
│ │ └── 0002_auto_20160226_1747.py
│ ├── __init__.py
│ ├── apps.py
│ ├── admin.py
│ ├── models.py
│ ├── serializers.py
│ └── views.py
├── templates
│ └── rest_framework
│ │ ├── inline
│ │ ├── list_fieldset.html
│ │ ├── form.html
│ │ ├── fieldset.html
│ │ ├── list_field.html
│ │ ├── dict_field.html
│ │ ├── checkbox.html
│ │ ├── textarea.html
│ │ ├── input.html
│ │ ├── checkbox_multiple.html
│ │ ├── radio.html
│ │ ├── select.html
│ │ └── select_multiple.html
│ │ ├── api.html
│ │ ├── login.html
│ │ ├── admin
│ │ ├── simple_list_value.html
│ │ ├── list_value.html
│ │ ├── dict_value.html
│ │ ├── detail.html
│ │ └── list.html
│ │ ├── schema.js
│ │ ├── horizontal
│ │ ├── form.html
│ │ ├── list_field.html
│ │ ├── dict_field.html
│ │ ├── list_fieldset.html
│ │ ├── fieldset.html
│ │ ├── checkbox.html
│ │ ├── textarea.html
│ │ ├── input.html
│ │ ├── checkbox_multiple.html
│ │ ├── select.html
│ │ ├── select_multiple.html
│ │ └── radio.html
│ │ ├── vertical
│ │ ├── form.html
│ │ ├── list_field.html
│ │ ├── list_fieldset.html
│ │ ├── dict_field.html
│ │ ├── fieldset.html
│ │ ├── checkbox.html
│ │ ├── textarea.html
│ │ ├── input.html
│ │ ├── select.html
│ │ ├── checkbox_multiple.html
│ │ ├── select_multiple.html
│ │ └── radio.html
│ │ ├── docs
│ │ ├── langs
│ │ │ ├── shell-intro.html
│ │ │ ├── python-intro.html
│ │ │ ├── javascript-intro.html
│ │ │ ├── shell.html
│ │ │ ├── python.html
│ │ │ └── javascript.html
│ │ ├── document.html
│ │ ├── auth
│ │ │ ├── session.html
│ │ │ ├── basic.html
│ │ │ └── token.html
│ │ ├── interact.html
│ │ ├── error.html
│ │ ├── index.html
│ │ └── sidebar.html
│ │ ├── raw_data_form.html
│ │ ├── filters
│ │ ├── search.html
│ │ ├── ordering.html
│ │ └── base.html
│ │ └── pagination
│ │ ├── previous_and_next.html
│ │ └── numbers.html
├── locale
│ ├── ach
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── ar
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── be
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── ca
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── cs
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── da
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── de
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── el
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── en
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── es
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── et
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── fa
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── fi
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── fr
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── gl
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── hu
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── id
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── it
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── ja
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── lv
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── mk
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── nb
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── nl
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── nn
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── no
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── pl
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── pt
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── ro
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── ru
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── sk
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── sl
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── sv
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── tr
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── uk
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── vi
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── ca_ES
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── el_GR
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── en_AU
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── en_CA
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── en_US
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── fa_IR
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── fr_CA
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── gl_ES
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── he_IL
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── ko_KR
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── pt_BR
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── pt_PT
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── tr_TR
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── zh_CN
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── zh_TW
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ ├── zh_Hans
│ │ └── LC_MESSAGES
│ │ │ └── django.mo
│ └── zh_Hant
│ │ └── LC_MESSAGES
│ │ └── django.mo
├── static
│ └── rest_framework
│ │ ├── img
│ │ ├── grid.png
│ │ ├── glyphicons-halflings.png
│ │ └── glyphicons-halflings-white.png
│ │ ├── docs
│ │ ├── img
│ │ │ ├── grid.png
│ │ │ └── favicon.ico
│ │ ├── css
│ │ │ ├── jquery.json-view.min.css
│ │ │ └── highlight.css
│ │ └── js
│ │ │ └── jquery.json-view.min.js
│ │ ├── fonts
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ ├── glyphicons-halflings-regular.eot
│ │ ├── glyphicons-halflings-regular.ttf
│ │ ├── glyphicons-halflings-regular.woff
│ │ └── glyphicons-halflings-regular.woff2
│ │ ├── css
│ │ ├── prettify.css
│ │ └── default.css
│ │ └── js
│ │ ├── default.js
│ │ └── csrf.js
├── apps.py
├── urls.py
├── checks.py
├── __init__.py
├── schemas
│ ├── utils.py
│ ├── __init__.py
│ └── views.py
├── reverse.py
└── status.py
├── docs
├── CNAME
├── img
│ ├── logo.png
│ ├── raml.png
│ ├── admin.png
│ ├── bayer.png
│ ├── inline.png
│ ├── rover.png
│ ├── slate.png
│ ├── api-docs.gif
│ ├── api-docs.png
│ ├── cerulean.png
│ ├── drf-yasg.png
│ ├── vertical.png
│ ├── horizontal.png
│ ├── quickstart.png
│ ├── search-filter.png
│ ├── sponsors
│ │ ├── 2-sga.png
│ │ ├── 3-aba.png
│ │ ├── 3-isl.png
│ │ ├── 1-cyan.png
│ │ ├── 1-divio.png
│ │ ├── 1-lulu.png
│ │ ├── 1-potato.png
│ │ ├── 2-byte.png
│ │ ├── 2-crate.png
│ │ ├── 2-django.png
│ │ ├── 2-heroku.png
│ │ ├── 2-hipo.png
│ │ ├── 2-opbeat.png
│ │ ├── 2-sirono.png
│ │ ├── 2-vinta.png
│ │ ├── 3-blimp.png
│ │ ├── 3-garfo.png
│ │ ├── 3-gizmag.png
│ │ ├── 3-holvi.png
│ │ ├── 3-phurba.png
│ │ ├── 3-safari.png
│ │ ├── 3-shippo.png
│ │ ├── 3-tivix.png
│ │ ├── 3-vzzual.png
│ │ ├── 1-runscope.png
│ │ ├── 2-compile.png
│ │ ├── 2-cryptico.png
│ │ ├── 2-hipflask.png
│ │ ├── 2-laterpay.png
│ │ ├── 2-nexthub.png
│ │ ├── 2-rapasso.png
│ │ ├── 2-wusawork.png
│ │ ├── 3-aditium.png
│ │ ├── 3-beefarm.png
│ │ ├── 3-cantemo.gif
│ │ ├── 3-nephila.png
│ │ ├── 3-openeye.png
│ │ ├── 3-pkgfarm.png
│ │ ├── 3-teonite.png
│ │ ├── 3-wildfish.png
│ │ ├── 0-eventbrite.png
│ │ ├── 1-kuwaitnet.png
│ │ ├── 1-purplebit.png
│ │ ├── 1-wiredrive.png
│ │ ├── 2-koordinates.png
│ │ ├── 2-prorenata.png
│ │ ├── 2-pulsecode.png
│ │ ├── 3-alwaysdata.png
│ │ ├── 3-brightloop.png
│ │ ├── 3-fluxility.png
│ │ ├── 3-ipushpull.png
│ │ ├── 3-makespace.png
│ │ ├── 3-pathwright.png
│ │ ├── 3-providenz.png
│ │ ├── 3-trackmaven.png
│ │ ├── 3-transcode.png
│ │ ├── 1-simple-energy.png
│ │ ├── 2-singing-horse.png
│ │ ├── 3-ax_semantics.png
│ │ ├── 3-infinite_code.png
│ │ ├── 3-life_the_game.png
│ │ ├── 2-lightning_kite.png
│ │ ├── 2-mirus_research.png
│ │ ├── 2-rheinwerk_verlag.png
│ │ ├── 2-schuberg_philis.png
│ │ ├── 2-security_compass.png
│ │ ├── 3-crosswordtracker.png
│ │ ├── 3-thermondo-gmbh.png
│ │ ├── 1-vokal_interactive.png
│ │ ├── 3-imt_computer_services.png
│ │ └── 3-triggered_messaging.png
│ ├── travis-status.png
│ ├── books
│ │ ├── bda-cover.png
│ │ ├── dfa-cover.jpg
│ │ ├── hwa-cover.png
│ │ └── tsd-cover.png
│ ├── corejson-format.png
│ ├── cursor-pagination.png
│ ├── filter-controls.png
│ ├── ordering-filter.png
│ ├── pages-pagination.png
│ ├── self-describing.png
│ ├── premium
│ │ ├── esg-readme.png
│ │ ├── cadre-readme.png
│ │ ├── retool-readme.png
│ │ ├── rollbar-readme.png
│ │ ├── sentry-readme.png
│ │ ├── stream-readme.png
│ │ ├── kloudless-readme.png
│ │ ├── lightson-readme.png
│ │ └── release-history.png
│ ├── labels-and-milestones.png
│ └── link-header-pagination.png
├── coreapi
│ └── index.md
├── topics
│ └── writable-nested-serializers.md
├── api-guide
│ ├── caching.md
│ └── reverse.md
└── community
│ └── jobs.md
├── .github
└── FUNDING.yml
├── requirements
├── requirements-documentation.txt
├── requirements-testing.txt
├── requirements-codestyle.txt
├── requirements-packaging.txt
└── requirements-optionals.txt
├── docs_theme
├── img
│ ├── grid.png
│ ├── favicon.ico
│ ├── glyphicons-halflings.png
│ └── glyphicons-halflings-white.png
├── 404.html
├── js
│ └── theme.js
├── css
│ └── prettify.css
└── nav.html
├── codecov.yml
├── .gitignore
├── MANIFEST.in
├── PULL_REQUEST_TEMPLATE.md
├── SECURITY.md
├── requirements.txt
├── setup.cfg
├── ISSUE_TEMPLATE.md
├── licenses
├── bootstrap.md
└── jquery.json-view.md
├── .travis.yml
├── tox.ini
└── LICENSE.md
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/schemas/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rest_framework/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/authentication/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/browsable_api/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rest_framework/management/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/generic_relations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rest_framework/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/authentication/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | www.django-rest-framework.org
2 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/management/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rest_framework/management/commands/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/generic_relations/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/management/commands/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | custom: https://fund.django-rest-framework.org/topics/funding/
2 |
--------------------------------------------------------------------------------
/docs/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/logo.png
--------------------------------------------------------------------------------
/docs/img/raml.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/raml.png
--------------------------------------------------------------------------------
/requirements/requirements-documentation.txt:
--------------------------------------------------------------------------------
1 | # MkDocs to build our documentation.
2 | mkdocs==1.0.4
3 |
--------------------------------------------------------------------------------
/docs/img/admin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/admin.png
--------------------------------------------------------------------------------
/docs/img/bayer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/bayer.png
--------------------------------------------------------------------------------
/docs/img/inline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/inline.png
--------------------------------------------------------------------------------
/docs/img/rover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/rover.png
--------------------------------------------------------------------------------
/docs/img/slate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/slate.png
--------------------------------------------------------------------------------
/docs/img/api-docs.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/api-docs.gif
--------------------------------------------------------------------------------
/docs/img/api-docs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/api-docs.png
--------------------------------------------------------------------------------
/docs/img/cerulean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/cerulean.png
--------------------------------------------------------------------------------
/docs/img/drf-yasg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/drf-yasg.png
--------------------------------------------------------------------------------
/docs/img/vertical.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/vertical.png
--------------------------------------------------------------------------------
/rest_framework/authtoken/__init__.py:
--------------------------------------------------------------------------------
1 | default_app_config = 'rest_framework.authtoken.apps.AuthTokenConfig'
2 |
--------------------------------------------------------------------------------
/docs/img/horizontal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/horizontal.png
--------------------------------------------------------------------------------
/docs/img/quickstart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/quickstart.png
--------------------------------------------------------------------------------
/docs_theme/img/grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs_theme/img/grid.png
--------------------------------------------------------------------------------
/docs/img/search-filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/search-filter.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-sga.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-sga.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-aba.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-aba.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-isl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-isl.png
--------------------------------------------------------------------------------
/docs/img/travis-status.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/travis-status.png
--------------------------------------------------------------------------------
/docs_theme/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs_theme/img/favicon.ico
--------------------------------------------------------------------------------
/docs/img/books/bda-cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/books/bda-cover.png
--------------------------------------------------------------------------------
/docs/img/books/dfa-cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/books/dfa-cover.jpg
--------------------------------------------------------------------------------
/docs/img/books/hwa-cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/books/hwa-cover.png
--------------------------------------------------------------------------------
/docs/img/books/tsd-cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/books/tsd-cover.png
--------------------------------------------------------------------------------
/docs/img/corejson-format.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/corejson-format.png
--------------------------------------------------------------------------------
/docs/img/cursor-pagination.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/cursor-pagination.png
--------------------------------------------------------------------------------
/docs/img/filter-controls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/filter-controls.png
--------------------------------------------------------------------------------
/docs/img/ordering-filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/ordering-filter.png
--------------------------------------------------------------------------------
/docs/img/pages-pagination.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/pages-pagination.png
--------------------------------------------------------------------------------
/docs/img/self-describing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/self-describing.png
--------------------------------------------------------------------------------
/docs/img/sponsors/1-cyan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-cyan.png
--------------------------------------------------------------------------------
/docs/img/sponsors/1-divio.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-divio.png
--------------------------------------------------------------------------------
/docs/img/sponsors/1-lulu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-lulu.png
--------------------------------------------------------------------------------
/docs/img/sponsors/1-potato.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-potato.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-byte.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-byte.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-crate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-crate.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-django.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-django.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-heroku.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-heroku.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-hipo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-hipo.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-opbeat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-opbeat.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-sirono.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-sirono.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-vinta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-vinta.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-blimp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-blimp.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-garfo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-garfo.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-gizmag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-gizmag.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-holvi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-holvi.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-phurba.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-phurba.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-safari.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-safari.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-shippo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-shippo.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-tivix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-tivix.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-vzzual.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-vzzual.png
--------------------------------------------------------------------------------
/docs/img/premium/esg-readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/premium/esg-readme.png
--------------------------------------------------------------------------------
/docs/img/sponsors/1-runscope.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-runscope.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-compile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-compile.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-cryptico.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-cryptico.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-hipflask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-hipflask.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-laterpay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-laterpay.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-nexthub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-nexthub.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-rapasso.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-rapasso.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-wusawork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-wusawork.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-aditium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-aditium.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-beefarm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-beefarm.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-cantemo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-cantemo.gif
--------------------------------------------------------------------------------
/docs/img/sponsors/3-nephila.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-nephila.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-openeye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-openeye.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-pkgfarm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-pkgfarm.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-teonite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-teonite.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-wildfish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-wildfish.png
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/list_fieldset.html:
--------------------------------------------------------------------------------
1 | Lists are not currently supported in HTML input.
2 |
--------------------------------------------------------------------------------
/docs/img/labels-and-milestones.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/labels-and-milestones.png
--------------------------------------------------------------------------------
/docs/img/link-header-pagination.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/link-header-pagination.png
--------------------------------------------------------------------------------
/docs/img/premium/cadre-readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/premium/cadre-readme.png
--------------------------------------------------------------------------------
/docs/img/premium/retool-readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/premium/retool-readme.png
--------------------------------------------------------------------------------
/docs/img/premium/rollbar-readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/premium/rollbar-readme.png
--------------------------------------------------------------------------------
/docs/img/premium/sentry-readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/premium/sentry-readme.png
--------------------------------------------------------------------------------
/docs/img/premium/stream-readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/premium/stream-readme.png
--------------------------------------------------------------------------------
/docs/img/sponsors/0-eventbrite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/0-eventbrite.png
--------------------------------------------------------------------------------
/docs/img/sponsors/1-kuwaitnet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-kuwaitnet.png
--------------------------------------------------------------------------------
/docs/img/sponsors/1-purplebit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-purplebit.png
--------------------------------------------------------------------------------
/docs/img/sponsors/1-wiredrive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-wiredrive.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-koordinates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-koordinates.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-prorenata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-prorenata.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-pulsecode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-pulsecode.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-alwaysdata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-alwaysdata.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-brightloop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-brightloop.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-fluxility.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-fluxility.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-ipushpull.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-ipushpull.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-makespace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-makespace.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-pathwright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-pathwright.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-providenz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-providenz.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-trackmaven.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-trackmaven.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-transcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-transcode.png
--------------------------------------------------------------------------------
/docs/img/premium/kloudless-readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/premium/kloudless-readme.png
--------------------------------------------------------------------------------
/docs/img/premium/lightson-readme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/premium/lightson-readme.png
--------------------------------------------------------------------------------
/docs/img/premium/release-history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/premium/release-history.png
--------------------------------------------------------------------------------
/docs/img/sponsors/1-simple-energy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-simple-energy.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-singing-horse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-singing-horse.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-ax_semantics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-ax_semantics.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-infinite_code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-infinite_code.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-life_the_game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-life_the_game.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-lightning_kite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-lightning_kite.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-mirus_research.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-mirus_research.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-rheinwerk_verlag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-rheinwerk_verlag.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-schuberg_philis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-schuberg_philis.png
--------------------------------------------------------------------------------
/docs/img/sponsors/2-security_compass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/2-security_compass.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-crosswordtracker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-crosswordtracker.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-thermondo-gmbh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-thermondo-gmbh.png
--------------------------------------------------------------------------------
/docs_theme/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs_theme/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/requirements/requirements-testing.txt:
--------------------------------------------------------------------------------
1 | # Pytest for running the tests.
2 | pytest>=5.0,<5.1
3 | pytest-django>=3.5.1,<3.6
4 | pytest-cov>=2.7.1
5 |
--------------------------------------------------------------------------------
/docs/img/sponsors/1-vokal_interactive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/1-vokal_interactive.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-imt_computer_services.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-imt_computer_services.png
--------------------------------------------------------------------------------
/docs/img/sponsors/3-triggered_messaging.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs/img/sponsors/3-triggered_messaging.png
--------------------------------------------------------------------------------
/docs_theme/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/docs_theme/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/rest_framework/locale/ach/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/ach/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/ar/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/ar/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/be/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/be/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/ca/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/ca/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/cs/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/cs/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/da/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/da/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/de/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/de/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/el/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/el/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/en/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/en/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/es/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/es/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/et/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/et/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/fa/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/fa/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/fi/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/fi/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/fr/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/fr/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/gl/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/gl/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/hu/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/hu/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/id/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/id/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/it/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/it/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/ja/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/ja/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/lv/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/lv/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/mk/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/mk/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/nb/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/nb/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/nl/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/nl/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/nn/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/nn/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/no/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/no/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/pl/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/pl/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/pt/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/pt/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/ro/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/ro/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/ru/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/ru/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/sk/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/sk/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/sl/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/sl/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/sv/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/sv/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/tr/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/tr/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/uk/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/uk/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/vi/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/vi/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/ca_ES/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/ca_ES/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/el_GR/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/el_GR/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/en_AU/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/en_AU/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/en_CA/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/en_CA/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/en_US/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/en_US/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/fa_IR/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/fa_IR/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/fr_CA/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/fr_CA/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/gl_ES/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/gl_ES/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/he_IL/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/he_IL/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/ko_KR/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/ko_KR/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/pt_BR/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/pt_BR/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/pt_PT/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/pt_PT/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/tr_TR/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/tr_TR/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/zh_CN/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/zh_CN/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/zh_TW/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/zh_TW/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/img/grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/img/grid.png
--------------------------------------------------------------------------------
/rest_framework/locale/zh_Hans/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/zh_Hans/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/locale/zh_Hant/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/locale/zh_Hant/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/docs/img/grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/docs/img/grid.png
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/api.html:
--------------------------------------------------------------------------------
1 | {% extends "rest_framework/base.html" %}
2 |
3 | {# Override this template in your own templates directory to customize #}
4 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/docs/img/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/docs/img/favicon.ico
--------------------------------------------------------------------------------
/tests/browsable_api/no_auth_urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 |
3 | from .views import MockView
4 |
5 | urlpatterns = [
6 | url(r'^$', MockView.as_view()),
7 | ]
8 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/login.html:
--------------------------------------------------------------------------------
1 | {% extends "rest_framework/login_base.html" %}
2 |
3 | {# Override this template in your own templates directory to customize #}
4 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | precision: 2
3 | round: down
4 | range: "80...100"
5 |
6 | status:
7 | project: yes
8 | patch: no
9 | changes: no
10 |
11 | comment: off
12 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/admin/simple_list_value.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% for item in value %}{% if not forloop.first%},{% endif %} {{item|format_value}}{% endfor %}
3 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/schema.js:
--------------------------------------------------------------------------------
1 | var codec = new window.coreapi.codecs.CoreJSONCodec()
2 | var coreJSON = window.atob('{{ schema }}')
3 | window.schema = codec.decode(coreJSON)
4 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/fonts/fontawesome-webfont.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/fonts/fontawesome-webfont.eot
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/fonts/fontawesome-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/fonts/fontawesome-webfont.ttf
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/fonts/fontawesome-webfont.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/fonts/fontawesome-webfont.woff
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/requirements/requirements-codestyle.txt:
--------------------------------------------------------------------------------
1 | # PEP8 code linting, which we run on all commits.
2 | flake8==3.7.8
3 | flake8-tidy-imports==3.0.0
4 | pycodestyle==2.5.0
5 |
6 | # Sort and lint imports
7 | isort==4.3.21
8 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/grangier/django-rest-framework/master/rest_framework/static/rest_framework/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/form.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% for field in form %}
3 | {% if not field.read_only %}
4 | {% render_field field style=style %}
5 | {% endif %}
6 | {% endfor %}
7 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/form.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% for field in form %}
3 | {% if not field.read_only %}
4 | {% render_field field style=style %}
5 | {% endif %}
6 | {% endfor %}
7 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/form.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% for field in form %}
3 | {% if not field.read_only %}
4 | {% render_field field style=style %}
5 | {% endif %}
6 | {% endfor %}
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | *.db
3 | *~
4 | .*
5 |
6 | /site/
7 | /htmlcov/
8 | /coverage/
9 | /build/
10 | /dist/
11 | /*.egg-info/
12 | /env/
13 | MANIFEST
14 | coverage.*
15 |
16 | !.gitignore
17 | !.travis.yml
18 | !.isort.cfg
19 |
--------------------------------------------------------------------------------
/requirements/requirements-packaging.txt:
--------------------------------------------------------------------------------
1 | # Wheel for PyPI installs.
2 | wheel==0.30.0
3 |
4 | # Twine for secured PyPI uploads.
5 | twine==1.11.0
6 |
7 | # Transifex client for managing translation resources.
8 | transifex-client==0.11
9 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 | from django.utils.translation import gettext_lazy as _
3 |
4 |
5 | class AuthTokenConfig(AppConfig):
6 | name = 'rest_framework.authtoken'
7 | verbose_name = _("Auth Token")
8 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/fieldset.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% for nested_field in field %}
3 | {% if not nested_field.read_only %}
4 | {% render_field nested_field style=style %}
5 | {% endif %}
6 | {% endfor %}
7 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/langs/shell-intro.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
{% code bash %}# Install the command line client
3 | $ pip install coreapi-cli{% endcode %}
4 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/langs/python-intro.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% code bash %}# Install the Python client library
3 | $ pip install coreapi{% endcode %}
4 |
--------------------------------------------------------------------------------
/tests/browsable_api/auth_urls.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import include, url
2 |
3 | from .views import MockView
4 |
5 | urlpatterns = [
6 | url(r'^$', MockView.as_view()),
7 | url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
8 | ]
9 |
--------------------------------------------------------------------------------
/requirements/requirements-optionals.txt:
--------------------------------------------------------------------------------
1 | # Optional packages which may be used with REST framework.
2 | psycopg2-binary>=2.8.2, <2.9
3 | markdown==3.1.1
4 | pygments==2.4.2
5 | django-guardian==2.1.0
6 | django-filter>=2.2.0, <2.3
7 | coreapi==2.3.1
8 | coreschema==0.0.4
9 | pyyaml>=5.1
10 |
--------------------------------------------------------------------------------
/tests/authentication/models.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.db import models
3 |
4 |
5 | class CustomToken(models.Model):
6 | key = models.CharField(max_length=40, primary_key=True)
7 | user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
8 |
--------------------------------------------------------------------------------
/rest_framework/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class RestFrameworkConfig(AppConfig):
5 | name = 'rest_framework'
6 | verbose_name = "Django REST framework"
7 |
8 | def ready(self):
9 | # Add System checks
10 | from .checks import pagination_system_check # NOQA
11 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/list_field.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/dict_field.html:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/list_field.html:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/list_fieldset.html:
--------------------------------------------------------------------------------
1 |
2 | {% if field.label %}
3 |
4 | {{ field.label }}
5 |
6 | {% endif %}
7 |
8 | Lists are not currently supported in HTML input.
9 |
10 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/dict_field.html:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | from rest_framework.authtoken.models import Token
4 |
5 |
6 | class TokenAdmin(admin.ModelAdmin):
7 | list_display = ('key', 'user', 'created')
8 | fields = ('user',)
9 | ordering = ('-created',)
10 |
11 |
12 | admin.site.register(Token, TokenAdmin)
13 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/admin/list_value.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 | {% for item in value %}
5 |
6 | {{ forloop.counter0 }}
7 | {{ item|format_value }}
8 |
9 | {% endfor %}
10 |
11 |
12 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include README.md
2 | include LICENSE.md
3 | recursive-include tests/* *
4 | recursive-include rest_framework/static *.js *.css *.png *.ico *.eot *.svg *.ttf *.woff *.woff2
5 | recursive-include rest_framework/templates *.html schema.js
6 | recursive-include rest_framework/locale *.mo
7 | global-exclude __pycache__
8 | global-exclude *.py[co]
9 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/admin/dict_value.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 | {% for k, v in value|items %}
5 |
6 | {{ k|format_value }}
7 | {{ v|format_value }}
8 |
9 | {% endfor %}
10 |
11 |
12 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/checkbox.html:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/admin/detail.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 | {% for key, value in results|items %}
5 | {% if key in details %}
6 | {{ key|capfirst }} {{ value|format_value }}
7 | {% endif %}
8 | {% endfor %}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/langs/javascript-intro.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% load static %}
3 | {% code html %}
4 |
5 | {% endcode %}
6 |
--------------------------------------------------------------------------------
/docs_theme/404.html:
--------------------------------------------------------------------------------
1 | {% extends "main.html" %}
2 |
3 | {% block content %}
4 |
5 | 404
6 | Page not found
7 | Try the homepage , or search the documentation .
8 |
9 | {% endblock %}
10 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/list_field.html:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | *Note*: Before submitting this pull request, please review our [contributing guidelines](https://github.com/encode/django-rest-framework/blob/master/CONTRIBUTING.md#pull-requests).
2 |
3 | ## Description
4 |
5 | Please describe your pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue. When linking to an issue, please use `refs #...` in the description of the pull request.
6 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/dict_field.html:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/raw_data_form.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {{ form.non_field_errors }}
3 | {% for field in form %}
4 |
11 | {% endfor %}
12 |
--------------------------------------------------------------------------------
/tests/urls.py:
--------------------------------------------------------------------------------
1 | """
2 | URLConf for test suite.
3 |
4 | We need only the docs urls for DocumentationRenderer tests.
5 | """
6 | from django.conf.urls import url
7 |
8 | from rest_framework.compat import coreapi
9 | from rest_framework.documentation import include_docs_urls
10 |
11 | if coreapi:
12 | urlpatterns = [
13 | url(r'^docs/', include_docs_urls(title='Test Suite API')),
14 | ]
15 | else:
16 | urlpatterns = []
17 |
--------------------------------------------------------------------------------
/tests/browsable_api/views.py:
--------------------------------------------------------------------------------
1 | from rest_framework import authentication, renderers
2 | from rest_framework.response import Response
3 | from rest_framework.views import APIView
4 |
5 |
6 | class MockView(APIView):
7 | authentication_classes = (authentication.SessionAuthentication,)
8 | renderer_classes = (renderers.BrowsableAPIRenderer, renderers.JSONRenderer)
9 |
10 | def get(self, request):
11 | return Response({'a': 1, 'b': 2, 'c': 3})
12 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/textarea.html:
--------------------------------------------------------------------------------
1 |
2 | {% if field.label %}
3 |
4 | {{ field.label }}
5 |
6 | {% endif %}
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/fieldset.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 | {% if field.label %}
5 |
6 | {{ field.label }}
7 |
8 | {% endif %}
9 |
10 | {% for nested_field in field %}
11 | {% if not nested_field.read_only %}
12 | {% render_field nested_field style=style %}
13 | {% endif %}
14 | {% endfor %}
15 |
16 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/list_fieldset.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 | {% if field.label %}
5 |
6 |
7 | {{ field.label }}
8 |
9 |
10 | {% endif %}
11 |
12 | Lists are not currently supported in HTML input.
13 |
14 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/langs/shell.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% code bash %}# Load the schema document
3 | $ coreapi get {{ document.url }}{% if schema_format %} --format {{ schema_format }}{% endif %}
4 |
5 | # Interact with the API endpoint
6 | $ coreapi action {% if section_key %}{{ section_key }} {% endif %}{{ link_key|cut:"> " }}{% for field in link.fields %} -p {{ field.name }}=...{% endfor %}{% endcode %}
7 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Reporting a Vulnerability
4 |
5 | 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**.
6 |
7 | 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.
8 |
9 | [security-mail]: mailto:rest-framework-security@googlegroups.com
10 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/filters/search.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% trans "Search" %}
3 |
13 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/fieldset.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 | {% if field.label %}
4 |
5 |
6 | {{ field.label }}
7 |
8 |
9 | {% endif %}
10 |
11 | {% for nested_field in field %}
12 | {% if not nested_field.read_only %}
13 | {% render_field nested_field style=style %}
14 | {% endif %}
15 | {% endfor %}
16 |
17 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/input.html:
--------------------------------------------------------------------------------
1 |
2 | {% if field.label %}
3 |
4 | {{ field.label }}
5 |
6 | {% endif %}
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/checkbox_multiple.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
17 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/pagination/previous_and_next.html:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # The base set of requirements for REST framework is actually
2 | # just Django, but for the purposes of development and testing
3 | # there are a number of packages that are useful to install.
4 |
5 | # Laying these out as separate requirements files, allows us to
6 | # only included the relevant sets when running tox, and ensures
7 | # we are only ever declaring our dependencies in one place.
8 |
9 | -r requirements/requirements-optionals.txt
10 | -r requirements/requirements-testing.txt
11 | -r requirements/requirements-documentation.txt
12 | -r requirements/requirements-codestyle.txt
13 | -r requirements/requirements-packaging.txt
14 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/filters/ordering.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% load i18n %}
3 | {% trans "Ordering" %}
4 |
5 | {% for key, label in options %}
6 | {% if key == current %}
7 |
8 | {{ label }}
9 |
10 | {% else %}
11 |
{{ label }}
12 | {% endif %}
13 | {% endfor %}
14 |
15 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/checkbox.html:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/tests/test_templates.py:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | from django.shortcuts import render
4 |
5 |
6 | def test_base_template_with_context():
7 | context = {'request': True, 'csrf_token': 'TOKEN'}
8 | result = render({}, 'rest_framework/base.html', context=context)
9 | assert re.search(r'\bcsrfToken: "TOKEN"', result.content.decode())
10 |
11 |
12 | def test_base_template_with_no_context():
13 | # base.html should be renderable with no context,
14 | # so it can be easily extended.
15 | result = render({}, 'rest_framework/base.html')
16 | # note that this response will not include a valid CSRF token
17 | assert re.search(r'\bcsrfToken: ""', result.content.decode())
18 |
--------------------------------------------------------------------------------
/tests/authentication/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.db import migrations, models
3 |
4 |
5 | class Migration(migrations.Migration):
6 |
7 | initial = True
8 |
9 | dependencies = [
10 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
11 | ]
12 |
13 | operations = [
14 | migrations.CreateModel(
15 | name='CustomToken',
16 | fields=[
17 | ('key', models.CharField(max_length=40, primary_key=True, serialize=False)),
18 | ('user', models.OneToOneField(on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL)),
19 | ],
20 | ),
21 | ]
22 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/filters/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 | {% for element in elements %}
10 | {% if not forloop.first %}
{% endif %}
11 | {{ element }}
12 | {% endfor %}
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/rest_framework/urls.py:
--------------------------------------------------------------------------------
1 | """
2 | Login and logout views for the browsable API.
3 |
4 | Add these to your root URLconf if you're using the browsable API and
5 | your API requires authentication:
6 |
7 | urlpatterns = [
8 | ...
9 | url(r'^auth/', include('rest_framework.urls'))
10 | ]
11 |
12 | You should make sure your authentication settings include `SessionAuthentication`.
13 | """
14 | from django.conf.urls import url
15 | from django.contrib.auth import views
16 |
17 | app_name = 'rest_framework'
18 | urlpatterns = [
19 | url(r'^login/$', views.LoginView.as_view(template_name='rest_framework/login.html'), name='login'),
20 | url(r'^logout/$', views.LogoutView.as_view(), name='logout'),
21 | ]
22 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | license_file = LICENSE.md
3 |
4 | [tool:pytest]
5 | addopts=--tb=short --strict -ra
6 | testspath = tests
7 |
8 | [flake8]
9 | ignore = E501,W504
10 | banned-modules = json = use from rest_framework.utils import json!
11 |
12 | [isort]
13 | skip=.tox
14 | atomic=true
15 | multi_line_output=5
16 | known_standard_library=types
17 | known_third_party=pytest,_pytest,django,pytz,uritemplate
18 | known_first_party=rest_framework,tests
19 |
20 | [coverage:run]
21 | # NOTE: source is ignored with pytest-cov (but uses the same).
22 | source = .
23 | include = rest_framework/*,tests/*
24 | branch = 1
25 |
26 | [coverage:report]
27 | include = rest_framework/*,tests/*
28 | exclude_lines =
29 | pragma: no cover
30 | raise NotImplementedError
31 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/langs/python.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% code python %}import coreapi
3 |
4 | # Initialize a client & load the schema document
5 | client = coreapi.Client()
6 | schema = client.get("{{ document.url }}"{% if schema_format %}, format="{{ schema_format }}"{% endif %})
7 |
8 | # Interact with the API endpoint
9 | action = [{% if section_key %}"{{ section_key }}", {% endif %}"{{ link_key }}"]
10 | {% if link.fields %}params = {
11 | {% for field in link.fields %} "{{ field.name }}": ...{% if not loop.last %},{% endif %}
12 | {% endfor %}}
13 | {% endif %}result = client.action(schema, action{% if link.fields %}, params=params{% endif %}){% endcode %}
14 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/checkbox.html:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/textarea.html:
--------------------------------------------------------------------------------
1 |
2 | {% if field.label %}
3 |
4 | {{ field.label }}
5 |
6 | {% endif %}
7 |
8 |
9 |
10 | {% if field.errors %}
11 | {% for error in field.errors %}{{ error }} {% endfor %}
12 | {% endif %}
13 |
14 | {% if field.help_text %}
15 | {{ field.help_text|safe }}
16 | {% endif %}
17 |
18 |
--------------------------------------------------------------------------------
/tests/importable/test_installed.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 |
3 | from tests import importable
4 |
5 |
6 | def test_installed():
7 | # ensure the test app hasn't been removed from the test suite
8 | assert 'tests.importable' in settings.INSTALLED_APPS
9 |
10 |
11 | def test_compat():
12 | assert hasattr(importable, 'compat')
13 |
14 |
15 | def test_serializer_fields_initialization():
16 | assert hasattr(importable, 'ExampleSerializer')
17 |
18 | serializer = importable.ExampleSerializer()
19 | assert 'charfield' in serializer.fields
20 | assert 'integerfield' in serializer.fields
21 | assert 'floatfield' in serializer.fields
22 | assert 'decimalfield' in serializer.fields
23 | assert 'durationfield' in serializer.fields
24 | assert 'listfield' in serializer.fields
25 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/langs/javascript.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 | {% code javascript %}var coreapi = window.coreapi // Loaded by `coreapi.js`
3 | var schema = window.schema // Loaded by `schema.js`
4 |
5 | // Initialize a client
6 | var client = new coreapi.Client()
7 |
8 | // Interact with the API endpoint
9 | var action = [{% if section_key %}"{{ section_key }}", {% endif %}"{{ link_key }}"]
10 | {% if link.fields %}var params = {
11 | {% for field in link.fields %} {{ field.name }}: ...{% if not loop.last %},{% endif %}
12 | {% endfor %}}
13 | {% endif %}client.action(schema, action{% if link.fields %}, params{% endif %}).then(function(result) {
14 | // Return value is in 'result'
15 | }){% endcode %}
16 |
--------------------------------------------------------------------------------
/tests/importable/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | This test "app" exists to ensure that parts of Django REST Framework can be
3 | imported/invoked before Django itself has been fully initialized.
4 | """
5 |
6 | from rest_framework import compat, serializers # noqa
7 |
8 |
9 | # test initializing fields with lazy translations
10 | class ExampleSerializer(serializers.Serializer):
11 | charfield = serializers.CharField(min_length=1, max_length=2)
12 | integerfield = serializers.IntegerField(min_value=1, max_value=2)
13 | floatfield = serializers.FloatField(min_value=1, max_value=2)
14 | decimalfield = serializers.DecimalField(max_digits=10, decimal_places=1, min_value=1, max_value=2)
15 | durationfield = serializers.DurationField(min_value=1, max_value=2)
16 | listfield = serializers.ListField(min_length=1, max_length=2)
17 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.db import migrations, models
3 |
4 |
5 | class Migration(migrations.Migration):
6 |
7 | dependencies = [
8 | migrations.swappable_dependency(settings.AUTH_USER_MODEL),
9 | ]
10 |
11 | operations = [
12 | migrations.CreateModel(
13 | name='Token',
14 | fields=[
15 | ('key', models.CharField(primary_key=True, serialize=False, max_length=40)),
16 | ('created', models.DateTimeField(auto_now_add=True)),
17 | ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, related_name='auth_token', on_delete=models.CASCADE)),
18 | ],
19 | options={
20 | },
21 | bases=(models.Model,),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/input.html:
--------------------------------------------------------------------------------
1 |
2 | {% if field.label %}
3 | {{ field.label }}
4 | {% endif %}
5 |
6 |
7 |
8 | {% if field.errors %}
9 | {% for error in field.errors %}
10 | {{ error }}
11 | {% endfor %}
12 | {% endif %}
13 |
14 | {% if field.help_text %}
15 | {{ field.help_text|safe }}
16 | {% endif %}
17 |
18 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/textarea.html:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Checklist
2 |
3 | - [ ] I have verified that that issue exists against the `master` branch of Django REST framework.
4 | - [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
5 | - [ ] This is not a usage question. (Those should be directed to the [discussion group](https://groups.google.com/forum/#!forum/django-rest-framework) instead.)
6 | - [ ] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](https://www.django-rest-framework.org/community/third-party-packages/#about-third-party-packages) where possible.)
7 | - [ ] I have reduced the issue to the simplest possible case.
8 | - [ ] I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)
9 |
10 | ## Steps to reproduce
11 |
12 | ## Expected behavior
13 |
14 | ## Actual behavior
15 |
--------------------------------------------------------------------------------
/docs_theme/js/theme.js:
--------------------------------------------------------------------------------
1 | var getSearchTerm = function() {
2 | var sPageURL = window.location.search.substring(1);
3 | var sURLVariables = sPageURL.split('&');
4 | for (var i = 0; i < sURLVariables.length; i++) {
5 | var sParameterName = sURLVariables[i].split('=');
6 | if (sParameterName[0] === 'q') {
7 | return sParameterName[1];
8 | }
9 | }
10 | };
11 |
12 | $(function() {
13 | var searchTerm = getSearchTerm(),
14 | $searchModal = $('#mkdocs_search_modal'),
15 | $searchQuery = $searchModal.find('#mkdocs-search-query'),
16 | $searchResults = $searchModal.find('#mkdocs-search-results');
17 |
18 | $('pre code').parent().addClass('prettyprint well');
19 |
20 | if (searchTerm) {
21 | $searchQuery.val(searchTerm);
22 | $searchResults.text('Searching...');
23 | $searchModal.modal();
24 | }
25 |
26 | $searchModal.on('shown', function() {
27 | $searchQuery.focus();
28 | });
29 | });
30 |
--------------------------------------------------------------------------------
/docs_theme/css/prettify.css:
--------------------------------------------------------------------------------
1 | .com { color: #93a1a1; }
2 | .lit { color: #195f91; }
3 | .pun, .opn, .clo { color: #93a1a1; }
4 | .fun { color: #dc322f; }
5 | .str, .atv { color: #D14; }
6 | .kwd, .prettyprint .tag { color: #1e347b; }
7 | .typ, .atn, .dec, .var { color: teal; }
8 | .pln { color: #48484c; }
9 |
10 | .prettyprint {
11 | padding: 8px;
12 | background-color: #f7f7f9;
13 | border: 1px solid #e1e1e8;
14 | }
15 | .prettyprint.linenums {
16 | -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
17 | -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
18 | box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
19 | }
20 |
21 | /* Specify class=linenums on a pre to get line numbering */
22 | ol.linenums {
23 | margin: 0 0 0 33px; /* IE indents via margin-left */
24 | }
25 | ol.linenums li {
26 | padding-left: 12px;
27 | color: #bebec5;
28 | line-height: 20px;
29 | text-shadow: 0 1px 0 #fff;
30 | }
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/radio.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load rest_framework %}
3 | {% trans "None" as none_choice %}
4 |
5 |
30 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/admin/list.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 | {% for column in columns%}{{ column|capfirst }} {% endfor %}
5 |
6 |
7 | {% for row in results %}
8 |
9 | {% for key, value in row|items %}
10 | {% if key in columns %}
11 |
12 | {{ value|format_value }}
13 |
14 | {% endif %}
15 | {% endfor %}
16 |
17 | {% if row.url %}
18 |
19 | {% else %}
20 |
21 | {% endif %}
22 |
23 |
24 | {% endfor %}
25 |
26 |
27 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/css/prettify.css:
--------------------------------------------------------------------------------
1 | .com { color: #93a1a1; }
2 | .lit { color: #195f91; }
3 | .pun, .opn, .clo { color: #93a1a1; }
4 | .fun { color: #dc322f; }
5 | .str, .atv { color: #D14; }
6 | .kwd, .prettyprint .tag { color: #1e347b; }
7 | .typ, .atn, .dec, .var { color: teal; }
8 | .pln { color: #48484c; }
9 |
10 | .prettyprint {
11 | padding: 8px;
12 | background-color: #f7f7f9;
13 | border: 1px solid #e1e1e8;
14 | }
15 | .prettyprint.linenums {
16 | -webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
17 | -moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
18 | box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
19 | }
20 |
21 | /* Specify class=linenums on a pre to get line numbering */
22 | ol.linenums {
23 | margin: 0 0 0 33px; /* IE indents via margin-left */
24 | }
25 | ol.linenums li {
26 | padding-left: 12px;
27 | color: #bebec5;
28 | line-height: 20px;
29 | text-shadow: 0 1px 0 #fff;
30 | }
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/input.html:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/select.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 | {% if field.label %}
5 |
6 | {{ field.label }}
7 |
8 | {% endif %}
9 |
10 |
11 | {% if field.allow_null or field.allow_blank %}
12 | --------
13 | {% endif %}
14 | {% for select in field.iter_options %}
15 | {% if select.start_option_group %}
16 |
17 | {% elif select.end_option_group %}
18 |
19 | {% else %}
20 | {{ select.display_text }}
21 | {% endif %}
22 | {% endfor %}
23 |
24 |
25 |
--------------------------------------------------------------------------------
/tests/test_write_only_fields.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | from rest_framework import serializers
4 |
5 |
6 | class WriteOnlyFieldTests(TestCase):
7 | def setUp(self):
8 | class ExampleSerializer(serializers.Serializer):
9 | email = serializers.EmailField()
10 | password = serializers.CharField(write_only=True)
11 |
12 | self.Serializer = ExampleSerializer
13 |
14 | def test_write_only_fields_are_present_on_input(self):
15 | data = {
16 | 'email': 'foo@example.com',
17 | 'password': '123'
18 | }
19 | serializer = self.Serializer(data=data)
20 | assert serializer.is_valid()
21 | assert serializer.validated_data == data
22 |
23 | def test_write_only_fields_are_not_present_on_output(self):
24 | instance = {
25 | 'email': 'foo@example.com',
26 | 'password': '123'
27 | }
28 | serializer = self.Serializer(instance)
29 | assert serializer.data == {'email': 'foo@example.com'}
30 |
--------------------------------------------------------------------------------
/rest_framework/checks.py:
--------------------------------------------------------------------------------
1 | from django.core.checks import Tags, Warning, register
2 |
3 |
4 | @register(Tags.compatibility)
5 | def pagination_system_check(app_configs, **kwargs):
6 | errors = []
7 | # Use of default page size setting requires a default Paginator class
8 | from rest_framework.settings import api_settings
9 | if api_settings.PAGE_SIZE and not api_settings.DEFAULT_PAGINATION_CLASS:
10 | errors.append(
11 | Warning(
12 | "You have specified a default PAGE_SIZE pagination rest_framework setting, "
13 | "without specifying also a DEFAULT_PAGINATION_CLASS.",
14 | hint="The default for DEFAULT_PAGINATION_CLASS is None. "
15 | "In previous versions this was PageNumberPagination. "
16 | "If you wish to define PAGE_SIZE globally whilst defining "
17 | "pagination_class on a per-view basis you may silence this check.",
18 | id="rest_framework.W001"
19 | )
20 | )
21 | return errors
22 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/inline/select_multiple.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load rest_framework %}
3 | {% trans "No items to select." as no_items %}
4 |
5 |
6 | {% if field.label %}
7 |
8 | {{ field.label }}
9 |
10 | {% endif %}
11 |
12 |
13 | {% for select in field.iter_options %}
14 | {% if select.start_option_group %}
15 |
16 | {% elif select.end_option_group %}
17 |
18 | {% else %}
19 | {{ select.display_text }}
20 | {% endif %}
21 | {% empty %}
22 | {{ no_items }}
23 | {% endfor %}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/document.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 |
5 |
{{ document.title }}
6 | {% if document.description %}
7 |
{% render_markdown document.description %}
8 | {% endif %}
9 |
10 |
11 | {% for html in lang_intro_htmls %}
12 | {% include html %}
13 | {% endfor %}
14 |
15 |
16 | {% if document|data %}
17 | {% for section_key, section in document|data|items %}
18 | {% if section_key %}
19 | {{ section_key }}
20 |
21 | {% endif %}
22 |
23 | {% for link_key, link in section|schema_links|items %}
24 | {% include "rest_framework/docs/link.html" %}
25 | {% endfor %}
26 | {% endfor %}
27 |
28 | {% for link_key, link in document.links|items %}
29 | {% include "rest_framework/docs/link.html" %}
30 | {% endfor %}
31 | {% endif %}
32 |
--------------------------------------------------------------------------------
/tests/schemas/test_get_schema_view.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from django.test import TestCase, override_settings
3 |
4 | from rest_framework import renderers
5 | from rest_framework.schemas import coreapi, get_schema_view, openapi
6 |
7 |
8 | class GetSchemaViewTests(TestCase):
9 | """For the get_schema_view() helper."""
10 | def test_openapi(self):
11 | schema_view = get_schema_view(title="With OpenAPI")
12 | assert isinstance(schema_view.initkwargs['schema_generator'], openapi.SchemaGenerator)
13 | assert renderers.OpenAPIRenderer in schema_view.cls().renderer_classes
14 |
15 | @pytest.mark.skipif(not coreapi.coreapi, reason='coreapi is not installed')
16 | def test_coreapi(self):
17 | with override_settings(REST_FRAMEWORK={'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema'}):
18 | schema_view = get_schema_view(title="With CoreAPI")
19 | assert isinstance(schema_view.initkwargs['schema_generator'], coreapi.SchemaGenerator)
20 | assert renderers.CoreAPIOpenAPIRenderer in schema_view.cls().renderer_classes
21 |
--------------------------------------------------------------------------------
/rest_framework/__init__.py:
--------------------------------------------------------------------------------
1 | r"""
2 | ______ _____ _____ _____ __
3 | | ___ \ ___/ ___|_ _| / _| | |
4 | | |_/ / |__ \ `--. | | | |_ _ __ __ _ _ __ ___ _____ _____ _ __| |__
5 | | /| __| `--. \ | | | _| '__/ _` | '_ ` _ \ / _ \ \ /\ / / _ \| '__| |/ /
6 | | |\ \| |___/\__/ / | | | | | | | (_| | | | | | | __/\ V V / (_) | | | <
7 | \_| \_\____/\____/ \_/ |_| |_| \__,_|_| |_| |_|\___| \_/\_/ \___/|_| |_|\_|
8 | """
9 |
10 | __title__ = 'Django REST framework'
11 | __version__ = '3.11.0'
12 | __author__ = 'Tom Christie'
13 | __license__ = 'BSD 3-Clause'
14 | __copyright__ = 'Copyright 2011-2019 Encode OSS Ltd'
15 |
16 | # Version synonym
17 | VERSION = __version__
18 |
19 | # Header encoding (see RFC5987)
20 | HTTP_HEADER_ENCODING = 'iso-8859-1'
21 |
22 | # Default datetime input and output formats
23 | ISO_8601 = 'iso-8601'
24 |
25 | default_app_config = 'rest_framework.apps.RestFrameworkConfig'
26 |
27 |
28 | class RemovedInDRF313Warning(DeprecationWarning):
29 | pass
30 |
31 |
32 | class RemovedInDRF314Warning(PendingDeprecationWarning):
33 | pass
34 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/migrations/0002_auto_20160226_1747.py:
--------------------------------------------------------------------------------
1 | from django.conf import settings
2 | from django.db import migrations, models
3 |
4 |
5 | class Migration(migrations.Migration):
6 |
7 | dependencies = [
8 | ('authtoken', '0001_initial'),
9 | ]
10 |
11 | operations = [
12 | migrations.AlterModelOptions(
13 | name='token',
14 | options={'verbose_name_plural': 'Tokens', 'verbose_name': 'Token'},
15 | ),
16 | migrations.AlterField(
17 | model_name='token',
18 | name='created',
19 | field=models.DateTimeField(verbose_name='Created', auto_now_add=True),
20 | ),
21 | migrations.AlterField(
22 | model_name='token',
23 | name='key',
24 | field=models.CharField(verbose_name='Key', max_length=40, primary_key=True, serialize=False),
25 | ),
26 | migrations.AlterField(
27 | model_name='token',
28 | name='user',
29 | field=models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name='User', related_name='auth_token', on_delete=models.CASCADE),
30 | ),
31 | ]
32 |
--------------------------------------------------------------------------------
/rest_framework/utils/urls.py:
--------------------------------------------------------------------------------
1 | from urllib import parse
2 |
3 | from django.utils.encoding import force_str
4 |
5 |
6 | def replace_query_param(url, key, val):
7 | """
8 | Given a URL and a key/val pair, set or replace an item in the query
9 | parameters of the URL, and return the new URL.
10 | """
11 | (scheme, netloc, path, query, fragment) = parse.urlsplit(force_str(url))
12 | query_dict = parse.parse_qs(query, keep_blank_values=True)
13 | query_dict[force_str(key)] = [force_str(val)]
14 | query = parse.urlencode(sorted(list(query_dict.items())), doseq=True)
15 | return parse.urlunsplit((scheme, netloc, path, query, fragment))
16 |
17 |
18 | def remove_query_param(url, key):
19 | """
20 | Given a URL and a key/val pair, remove an item in the query
21 | parameters of the URL, and return the new URL.
22 | """
23 | (scheme, netloc, path, query, fragment) = parse.urlsplit(force_str(url))
24 | query_dict = parse.parse_qs(query, keep_blank_values=True)
25 | query_dict.pop(key, None)
26 | query = parse.urlencode(sorted(list(query_dict.items())), doseq=True)
27 | return parse.urlunsplit((scheme, netloc, path, query, fragment))
28 |
--------------------------------------------------------------------------------
/licenses/bootstrap.md:
--------------------------------------------------------------------------------
1 | https://github.com/twbs/bootstrap/
2 |
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2011-2016 Twitter, Inc.
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in
15 | all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 |
--------------------------------------------------------------------------------
/rest_framework/utils/json.py:
--------------------------------------------------------------------------------
1 | """
2 | Wrapper for the builtin json module that ensures compliance with the JSON spec.
3 |
4 | REST framework should always import this wrapper module in order to maintain
5 | spec-compliant encoding/decoding. Support for non-standard features should be
6 | handled by users at the renderer and parser layer.
7 | """
8 | import functools
9 | import json # noqa
10 |
11 |
12 | def strict_constant(o):
13 | raise ValueError('Out of range float values are not JSON compliant: ' + repr(o))
14 |
15 |
16 | @functools.wraps(json.dump)
17 | def dump(*args, **kwargs):
18 | kwargs.setdefault('allow_nan', False)
19 | return json.dump(*args, **kwargs)
20 |
21 |
22 | @functools.wraps(json.dumps)
23 | def dumps(*args, **kwargs):
24 | kwargs.setdefault('allow_nan', False)
25 | return json.dumps(*args, **kwargs)
26 |
27 |
28 | @functools.wraps(json.load)
29 | def load(*args, **kwargs):
30 | kwargs.setdefault('parse_constant', strict_constant)
31 | return json.load(*args, **kwargs)
32 |
33 |
34 | @functools.wraps(json.loads)
35 | def loads(*args, **kwargs):
36 | kwargs.setdefault('parse_constant', strict_constant)
37 | return json.loads(*args, **kwargs)
38 |
--------------------------------------------------------------------------------
/tests/generic_relations/models.py:
--------------------------------------------------------------------------------
1 | from django.contrib.contenttypes.fields import (
2 | GenericForeignKey, GenericRelation
3 | )
4 | from django.contrib.contenttypes.models import ContentType
5 | from django.db import models
6 |
7 |
8 | class Tag(models.Model):
9 | """
10 | Tags have a descriptive slug, and are attached to an arbitrary object.
11 | """
12 | tag = models.SlugField()
13 | content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
14 | object_id = models.PositiveIntegerField()
15 | tagged_item = GenericForeignKey('content_type', 'object_id')
16 |
17 | def __str__(self):
18 | return self.tag
19 |
20 |
21 | class Bookmark(models.Model):
22 | """
23 | A URL bookmark that may have multiple tags attached.
24 | """
25 | url = models.URLField()
26 | tags = GenericRelation(Tag)
27 |
28 | def __str__(self):
29 | return 'Bookmark: %s' % self.url
30 |
31 |
32 | class Note(models.Model):
33 | """
34 | A textual note that may have multiple tags attached.
35 | """
36 | text = models.TextField()
37 | tags = GenericRelation(Tag)
38 |
39 | def __str__(self):
40 | return 'Note: %s' % self.text
41 |
--------------------------------------------------------------------------------
/licenses/jquery.json-view.md:
--------------------------------------------------------------------------------
1 | https://github.com/bazh/jquery.json-view/
2 |
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2014 bazh. (https://github.com/bazh)
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy of
8 | this software and associated documentation files (the "Software"), to deal in
9 | the Software without restriction, including without limitation the rights to
10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11 | the Software, and to permit persons to whom the Software is furnished to do so,
12 | subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/tests/test_status.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | from rest_framework.status import (
4 | is_client_error, is_informational, is_redirect, is_server_error,
5 | is_success
6 | )
7 |
8 |
9 | class TestStatus(TestCase):
10 | def test_status_categories(self):
11 | self.assertFalse(is_informational(99))
12 | self.assertTrue(is_informational(100))
13 | self.assertTrue(is_informational(199))
14 | self.assertFalse(is_informational(200))
15 |
16 | self.assertFalse(is_success(199))
17 | self.assertTrue(is_success(200))
18 | self.assertTrue(is_success(299))
19 | self.assertFalse(is_success(300))
20 |
21 | self.assertFalse(is_redirect(299))
22 | self.assertTrue(is_redirect(300))
23 | self.assertTrue(is_redirect(399))
24 | self.assertFalse(is_redirect(400))
25 |
26 | self.assertFalse(is_client_error(399))
27 | self.assertTrue(is_client_error(400))
28 | self.assertTrue(is_client_error(499))
29 | self.assertFalse(is_client_error(500))
30 |
31 | self.assertFalse(is_server_error(499))
32 | self.assertTrue(is_server_error(500))
33 | self.assertTrue(is_server_error(599))
34 | self.assertFalse(is_server_error(600))
35 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | cache: pip
3 | dist: xenial
4 | matrix:
5 | fast_finish: true
6 | include:
7 |
8 | - { python: "3.5", env: DJANGO=2.2 }
9 |
10 | - { python: "3.6", env: DJANGO=2.2 }
11 | - { python: "3.6", env: DJANGO=3.0 }
12 | - { python: "3.6", env: DJANGO=master }
13 |
14 | - { python: "3.7", env: DJANGO=2.2 }
15 | - { python: "3.7", env: DJANGO=3.0 }
16 | - { python: "3.7", env: DJANGO=master }
17 |
18 | - { python: "3.8", env: DJANGO=3.0 }
19 | - { python: "3.8", env: DJANGO=master }
20 |
21 | - { python: "3.8", env: TOXENV=base }
22 | - { python: "3.8", env: TOXENV=lint }
23 | - { python: "3.8", env: TOXENV=docs }
24 |
25 | - python: "3.8"
26 | env: TOXENV=dist
27 | script:
28 | - python setup.py bdist_wheel
29 | - rm -r djangorestframework.egg-info # see #6139
30 | - tox --installpkg ./dist/djangorestframework-*.whl
31 | - tox # test sdist
32 |
33 | allow_failures:
34 | - env: DJANGO=master
35 |
36 | install:
37 | - pip install tox tox-venv tox-travis
38 |
39 | script:
40 | - tox
41 |
42 | after_success:
43 | - pip install codecov
44 | - codecov -e TOXENV,DJANGO
45 |
46 | notifications:
47 | email: false
48 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/auth/session.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 |
36 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/select.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 | {% if field.label %}
5 |
6 | {{ field.label }}
7 |
8 | {% endif %}
9 |
10 |
11 | {% if field.allow_null or field.allow_blank %}
12 | --------
13 | {% endif %}
14 | {% for select in field.iter_options %}
15 | {% if select.start_option_group %}
16 |
17 | {% elif select.end_option_group %}
18 |
19 | {% else %}
20 | {{ select.display_text }}
21 | {% endif %}
22 | {% endfor %}
23 |
24 |
25 | {% if field.errors %}
26 | {% for error in field.errors %}
27 | {{ error }}
28 | {% endfor %}
29 | {% endif %}
30 |
31 | {% if field.help_text %}
32 | {{ field.help_text|safe }}
33 | {% endif %}
34 |
35 |
--------------------------------------------------------------------------------
/tests/generic_relations/migrations/0001_initial.py:
--------------------------------------------------------------------------------
1 | from django.db import migrations, models
2 |
3 |
4 | class Migration(migrations.Migration):
5 |
6 | initial = True
7 |
8 | dependencies = [
9 | ('contenttypes', '0002_remove_content_type_name'),
10 | ]
11 |
12 | operations = [
13 | migrations.CreateModel(
14 | name='Bookmark',
15 | fields=[
16 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
17 | ('url', models.URLField()),
18 | ],
19 | ),
20 | migrations.CreateModel(
21 | name='Note',
22 | fields=[
23 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
24 | ('text', models.TextField()),
25 | ],
26 | ),
27 | migrations.CreateModel(
28 | name='Tag',
29 | fields=[
30 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31 | ('tag', models.SlugField()),
32 | ('object_id', models.PositiveIntegerField()),
33 | ('content_type', models.ForeignKey(on_delete=models.CASCADE, to='contenttypes.ContentType')),
34 | ],
35 | ),
36 | ]
37 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/checkbox_multiple.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
38 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/select_multiple.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load rest_framework %}
3 | {% trans "No items to select." as no_items %}
4 |
5 |
6 | {% if field.label %}
7 |
8 | {{ field.label }}
9 |
10 | {% endif %}
11 |
12 |
13 | {% for select in field.iter_options %}
14 | {% if select.start_option_group %}
15 |
16 | {% elif select.end_option_group %}
17 |
18 | {% else %}
19 | {{ select.display_text }}
20 | {% endif %}
21 | {% empty %}
22 | {{ no_items }}
23 | {% endfor %}
24 |
25 |
26 | {% if field.errors %}
27 | {% for error in field.errors %}{{ error }} {% endfor %}
28 | {% endif %}
29 |
30 | {% if field.help_text %}
31 | {{ field.help_text|safe }}
32 | {% endif %}
33 |
34 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/docs/css/jquery.json-view.min.css:
--------------------------------------------------------------------------------
1 | .json-view{position:relative}
2 | .json-view .collapser{width:20px;height:18px;display:block;position:absolute;left:-1.7em;top:-.2em;z-index:5;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAD1JREFUeNpiYGBgOADE%2F3Hgw0DM4IRHgSsDFOzFInmMAQnY49ONzZRjDFiADT7dMLALiE8y4AGW6LoBAgwAuIkf%2F%2FB7O9sAAAAASUVORK5CYII%3D);background-repeat:no-repeat;background-position:center center;opacity:.5;cursor:pointer}
3 | .json-view .collapsed{-ms-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-khtml-transform:rotate(-90deg);-webkit-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}
4 | .json-view .bl{display:block;padding-left:20px;margin-left:-20px;position:relative}
5 | .json-view{font-family:monospace}
6 | .json-view ul{list-style-type:none;padding-left:2em;border-left:1px dotted;margin:.3em}
7 | .json-view ul li{position:relative}
8 | .json-view .comments,.json-view .dots{display:none;-moz-user-select:none;-ms-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-o-user-select:none;user-select:none}
9 | .json-view .comments{padding-left:.8em;font-style:italic;color:#888}
10 | .json-view .bool,.json-view .null,.json-view .num,.json-view .undef{font-weight:700;color:#1A01CC}
11 | .json-view .str{color:#800}
--------------------------------------------------------------------------------
/rest_framework/authtoken/models.py:
--------------------------------------------------------------------------------
1 | import binascii
2 | import os
3 |
4 | from django.conf import settings
5 | from django.db import models
6 | from django.utils.translation import gettext_lazy as _
7 |
8 |
9 | class Token(models.Model):
10 | """
11 | The default authorization token model.
12 | """
13 | key = models.CharField(_("Key"), max_length=40, primary_key=True)
14 | user = models.OneToOneField(
15 | settings.AUTH_USER_MODEL, related_name='auth_token',
16 | on_delete=models.CASCADE, verbose_name=_("User")
17 | )
18 | created = models.DateTimeField(_("Created"), auto_now_add=True)
19 |
20 | class Meta:
21 | # Work around for a bug in Django:
22 | # https://code.djangoproject.com/ticket/19422
23 | #
24 | # Also see corresponding ticket:
25 | # https://github.com/encode/django-rest-framework/issues/705
26 | abstract = 'rest_framework.authtoken' not in settings.INSTALLED_APPS
27 | verbose_name = _("Token")
28 | verbose_name_plural = _("Tokens")
29 |
30 | def save(self, *args, **kwargs):
31 | if not self.key:
32 | self.key = self.generate_key()
33 | return super().save(*args, **kwargs)
34 |
35 | def generate_key(self):
36 | return binascii.hexlify(os.urandom(20)).decode()
37 |
38 | def __str__(self):
39 | return self.key
40 |
--------------------------------------------------------------------------------
/rest_framework/schemas/utils.py:
--------------------------------------------------------------------------------
1 | """
2 | utils.py # Shared helper functions
3 |
4 | See schemas.__init__.py for package overview.
5 | """
6 | from django.db import models
7 | from django.utils.translation import gettext_lazy as _
8 |
9 | from rest_framework.mixins import RetrieveModelMixin
10 |
11 |
12 | def is_list_view(path, method, view):
13 | """
14 | Return True if the given path/method appears to represent a list view.
15 | """
16 | if hasattr(view, 'action'):
17 | # Viewsets have an explicitly defined action, which we can inspect.
18 | return view.action == 'list'
19 |
20 | if method.lower() != 'get':
21 | return False
22 | if isinstance(view, RetrieveModelMixin):
23 | return False
24 | path_components = path.strip('/').split('/')
25 | if path_components and '{' in path_components[-1]:
26 | return False
27 | return True
28 |
29 |
30 | def get_pk_description(model, model_field):
31 | if isinstance(model_field, models.AutoField):
32 | value_type = _('unique integer value')
33 | elif isinstance(model_field, models.UUIDField):
34 | value_type = _('UUID string')
35 | else:
36 | value_type = _('unique value')
37 |
38 | return _('A {value_type} identifying this {name}.').format(
39 | value_type=value_type,
40 | name=model._meta.verbose_name,
41 | )
42 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/checkbox_multiple.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
40 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/select.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
37 |
--------------------------------------------------------------------------------
/docs/coreapi/index.md:
--------------------------------------------------------------------------------
1 | # Legacy CoreAPI Schemas Docs
2 |
3 | Use of CoreAPI-based schemas were deprecated with the introduction of native OpenAPI-based schema generation in Django REST Framework v3.10.
4 |
5 | See the [Version 3.10 Release Announcement](/community/3.10-announcement.md) for more details.
6 |
7 | ----
8 |
9 | You can continue to use CoreAPI schemas by setting the appropriate default schema class:
10 |
11 | ```python
12 | # In settings.py
13 | REST_FRAMEWORK = {
14 | 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
15 | }
16 | ```
17 |
18 | Under-the-hood, any subclass of `coreapi.AutoSchema` here will trigger use of the old CoreAPI schemas.
19 | **Otherwise** you will automatically be opted-in to the new OpenAPI schemas.
20 |
21 | All CoreAPI related code will be removed in Django REST Framework v3.12. Switch to OpenAPI schemas by then.
22 |
23 | ----
24 |
25 | For reference this folder contains the old CoreAPI related documentation:
26 |
27 | * [Tutorial 7: Schemas & client libraries](https://github.com/encode/django-rest-framework/blob/master/docs/coreapi//7-schemas-and-client-libraries.md).
28 | * [Excerpts from _Documenting your API_ topic page](https://github.com/encode/django-rest-framework/blob/master/docs/coreapi//from-documenting-your-api.md).
29 | * [`rest_framework.schemas` API Reference](https://github.com/encode/django-rest-framework/blob/master/docs/coreapi//schemas.md).
30 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/pagination/numbers.html:
--------------------------------------------------------------------------------
1 |
48 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/select_multiple.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load rest_framework %}
3 |
4 | {% trans "No items to select." as no_items %}
5 |
6 |
39 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/auth/basic.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 |
39 |
--------------------------------------------------------------------------------
/tests/test_one_to_one_with_inheritance.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.test import TestCase
3 |
4 | from rest_framework import serializers
5 | from tests.models import RESTFrameworkModel
6 | # Models
7 | from tests.test_multitable_inheritance import ChildModel
8 |
9 |
10 | # Regression test for #4290
11 | class ChildAssociatedModel(RESTFrameworkModel):
12 | child_model = models.OneToOneField(ChildModel, on_delete=models.CASCADE)
13 | child_name = models.CharField(max_length=100)
14 |
15 |
16 | # Serializers
17 | class DerivedModelSerializer(serializers.ModelSerializer):
18 | class Meta:
19 | model = ChildModel
20 | fields = ['id', 'name1', 'name2', 'childassociatedmodel']
21 |
22 |
23 | class ChildAssociatedModelSerializer(serializers.ModelSerializer):
24 |
25 | class Meta:
26 | model = ChildAssociatedModel
27 | fields = ['id', 'child_name']
28 |
29 |
30 | # Tests
31 | class InheritedModelSerializationTests(TestCase):
32 |
33 | def test_multitable_inherited_model_fields_as_expected(self):
34 | """
35 | Assert that the parent pointer field is not included in the fields
36 | serialized fields
37 | """
38 | child = ChildModel(name1='parent name', name2='child name')
39 | serializer = DerivedModelSerializer(child)
40 | self.assertEqual(set(serializer.data),
41 | {'name1', 'name2', 'id', 'childassociatedmodel'})
42 |
--------------------------------------------------------------------------------
/tests/browsable_api/test_browsable_nested_api.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 | from django.test import TestCase
3 | from django.test.utils import override_settings
4 |
5 | from rest_framework import serializers
6 | from rest_framework.generics import ListCreateAPIView
7 | from rest_framework.renderers import BrowsableAPIRenderer
8 |
9 |
10 | class NestedSerializer(serializers.Serializer):
11 | one = serializers.IntegerField(max_value=10)
12 | two = serializers.IntegerField(max_value=10)
13 |
14 |
15 | class NestedSerializerTestSerializer(serializers.Serializer):
16 | nested = NestedSerializer()
17 |
18 |
19 | class NestedSerializersView(ListCreateAPIView):
20 | renderer_classes = (BrowsableAPIRenderer, )
21 | serializer_class = NestedSerializerTestSerializer
22 | queryset = [{'nested': {'one': 1, 'two': 2}}]
23 |
24 |
25 | urlpatterns = [
26 | url(r'^api/$', NestedSerializersView.as_view(), name='api'),
27 | ]
28 |
29 |
30 | class DropdownWithAuthTests(TestCase):
31 | """Tests correct dropdown behaviour with Auth views enabled."""
32 |
33 | @override_settings(ROOT_URLCONF='tests.browsable_api.test_browsable_nested_api')
34 | def test_login(self):
35 | response = self.client.get('/api/')
36 | assert 200 == response.status_code
37 | content = response.content.decode()
38 | assert 'form action="/api/"' in content
39 | assert 'input name="nested.one"' in content
40 | assert 'input name="nested.two"' in content
41 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/js/default.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 | // JSON highlighting.
3 | prettyPrint();
4 |
5 | // Bootstrap tooltips.
6 | $('.js-tooltip').tooltip({
7 | delay: 1000,
8 | container: 'body'
9 | });
10 |
11 | // Deal with rounded tab styling after tab clicks.
12 | $('a[data-toggle="tab"]:first').on('shown', function(e) {
13 | $(e.target).parents('.tabbable').addClass('first-tab-active');
14 | });
15 |
16 | $('a[data-toggle="tab"]:not(:first)').on('shown', function(e) {
17 | $(e.target).parents('.tabbable').removeClass('first-tab-active');
18 | });
19 |
20 | $('a[data-toggle="tab"]').click(function() {
21 | document.cookie = "tabstyle=" + this.name + "; path=/";
22 | });
23 |
24 | // Store tab preference in cookies & display appropriate tab on load.
25 | var selectedTab = null;
26 | var selectedTabName = getCookie('tabstyle');
27 |
28 | if (selectedTabName) {
29 | selectedTabName = selectedTabName.replace(/[^a-z-]/g, '');
30 | }
31 |
32 | if (selectedTabName) {
33 | selectedTab = $('.form-switcher a[name=' + selectedTabName + ']');
34 | }
35 |
36 | if (selectedTab && selectedTab.length > 0) {
37 | // Display whichever tab is selected.
38 | selectedTab.tab('show');
39 | } else {
40 | // If no tab selected, display rightmost tab.
41 | $('.form-switcher a:first').tab('show');
42 | }
43 |
44 | $(window).on('load', function() {
45 | $('#errorModal').modal('show');
46 | });
47 | });
48 |
--------------------------------------------------------------------------------
/rest_framework/utils/humanize_datetime.py:
--------------------------------------------------------------------------------
1 | """
2 | Helper functions that convert strftime formats into more readable representations.
3 | """
4 | from rest_framework import ISO_8601
5 |
6 |
7 | def datetime_formats(formats):
8 | format = ', '.join(formats).replace(
9 | ISO_8601,
10 | 'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]'
11 | )
12 | return humanize_strptime(format)
13 |
14 |
15 | def date_formats(formats):
16 | format = ', '.join(formats).replace(ISO_8601, 'YYYY-MM-DD')
17 | return humanize_strptime(format)
18 |
19 |
20 | def time_formats(formats):
21 | format = ', '.join(formats).replace(ISO_8601, 'hh:mm[:ss[.uuuuuu]]')
22 | return humanize_strptime(format)
23 |
24 |
25 | def humanize_strptime(format_string):
26 | # Note that we're missing some of the locale specific mappings that
27 | # don't really make sense.
28 | mapping = {
29 | "%Y": "YYYY",
30 | "%y": "YY",
31 | "%m": "MM",
32 | "%b": "[Jan-Dec]",
33 | "%B": "[January-December]",
34 | "%d": "DD",
35 | "%H": "hh",
36 | "%I": "hh", # Requires '%p' to differentiate from '%H'.
37 | "%M": "mm",
38 | "%S": "ss",
39 | "%f": "uuuuuu",
40 | "%a": "[Mon-Sun]",
41 | "%A": "[Monday-Sunday]",
42 | "%p": "[AM|PM]",
43 | "%z": "[+HHMM|-HHMM]"
44 | }
45 | for key, val in mapping.items():
46 | format_string = format_string.replace(key, val)
47 | return format_string
48 |
--------------------------------------------------------------------------------
/tox.ini:
--------------------------------------------------------------------------------
1 | [tox]
2 | envlist =
3 | {py35,py36,py37}-django22,
4 | {py36,py37,py38}-django30,
5 | {py36,py37,py38}-djangomaster,
6 | base,dist,lint,docs,
7 |
8 | [travis:env]
9 | DJANGO =
10 | 2.2: django22
11 | 3.0: django30
12 | master: djangomaster
13 |
14 | [testenv]
15 | commands = ./runtests.py --fast --coverage {posargs}
16 | envdir = {toxworkdir}/venvs/{envname}
17 | setenv =
18 | PYTHONDONTWRITEBYTECODE=1
19 | PYTHONWARNINGS=once
20 | deps =
21 | django22: Django>=2.2,<3.0
22 | django30: Django>=3.0,<3.1
23 | djangomaster: https://github.com/django/django/archive/master.tar.gz
24 | -rrequirements/requirements-testing.txt
25 | -rrequirements/requirements-optionals.txt
26 |
27 | [testenv:base]
28 | ; Ensure optional dependencies are not required
29 | deps =
30 | django
31 | -rrequirements/requirements-testing.txt
32 |
33 | [testenv:dist]
34 | commands = ./runtests.py --fast --no-pkgroot --staticfiles {posargs}
35 | deps =
36 | django
37 | -rrequirements/requirements-testing.txt
38 | -rrequirements/requirements-optionals.txt
39 |
40 | [testenv:lint]
41 | commands = ./runtests.py --lintonly
42 | deps =
43 | -rrequirements/requirements-codestyle.txt
44 | -rrequirements/requirements-testing.txt
45 |
46 | [testenv:docs]
47 | skip_install = true
48 | commands = mkdocs build
49 | deps =
50 | -rrequirements/requirements-testing.txt
51 | -rrequirements/requirements-documentation.txt
52 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/css/default.css:
--------------------------------------------------------------------------------
1 | /* The navbar is fixed at >= 980px wide, so add padding to the body to prevent
2 | content running up underneath it. */
3 |
4 | h1 {
5 | font-weight: 300;
6 | }
7 |
8 | h2, h3 {
9 | font-weight: 300;
10 | }
11 |
12 | .resource-description, .response-info {
13 | margin-bottom: 2em;
14 | }
15 |
16 | .version:before {
17 | content: "v";
18 | opacity: 0.6;
19 | padding-right: 0.25em;
20 | }
21 |
22 | .version {
23 | font-size: 70%;
24 | }
25 |
26 | .format-option {
27 | font-family: Menlo, Consolas, "Andale Mono", "Lucida Console", monospace;
28 | }
29 |
30 | .button-form {
31 | float: right;
32 | margin-right: 1em;
33 | }
34 |
35 | td.nested {
36 | padding: 0 !important;
37 | }
38 |
39 | td.nested > table {
40 | margin: 0;
41 | }
42 |
43 | form select, form input, form textarea {
44 | width: 90%;
45 | }
46 |
47 | form select[multiple] {
48 | height: 150px;
49 | }
50 |
51 | /* To allow tooltips to work on disabled elements */
52 | .disabled-tooltip-shield {
53 | position: absolute;
54 | top: 0;
55 | right: 0;
56 | bottom: 0;
57 | left: 0;
58 | }
59 |
60 | .errorlist {
61 | margin-top: 0.5em;
62 | }
63 |
64 | pre {
65 | overflow: auto;
66 | word-wrap: normal;
67 | white-space: pre;
68 | font-size: 12px;
69 | }
70 |
71 | .page-header {
72 | border-bottom: none;
73 | padding-bottom: 0px;
74 | }
75 |
76 | #filtersModal form input[type=submit] {
77 | width: auto;
78 | }
79 |
80 | #filtersModal .modal-body h2 {
81 | margin-top: 0
82 | }
83 |
--------------------------------------------------------------------------------
/tests/test_lazy_hyperlinks.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 | from django.db import models
3 | from django.test import TestCase, override_settings
4 |
5 | from rest_framework import serializers
6 | from rest_framework.renderers import JSONRenderer
7 | from rest_framework.templatetags.rest_framework import format_value
8 |
9 | str_called = False
10 |
11 |
12 | class Example(models.Model):
13 | text = models.CharField(max_length=100)
14 |
15 | def __str__(self):
16 | global str_called
17 | str_called = True
18 | return 'An example'
19 |
20 |
21 | class ExampleSerializer(serializers.HyperlinkedModelSerializer):
22 | class Meta:
23 | model = Example
24 | fields = ('url', 'id', 'text')
25 |
26 |
27 | def dummy_view(request):
28 | pass
29 |
30 |
31 | urlpatterns = [
32 | url(r'^example/(?P[0-9]+)/$', dummy_view, name='example-detail'),
33 | ]
34 |
35 |
36 | @override_settings(ROOT_URLCONF='tests.test_lazy_hyperlinks')
37 | class TestLazyHyperlinkNames(TestCase):
38 | def setUp(self):
39 | self.example = Example.objects.create(text='foo')
40 |
41 | def test_lazy_hyperlink_names(self):
42 | global str_called
43 | context = {'request': None}
44 | serializer = ExampleSerializer(self.example, context=context)
45 | JSONRenderer().render(serializer.data)
46 | assert not str_called
47 | hyperlink_string = format_value(serializer.data['url'])
48 | assert hyperlink_string == 'An example '
49 | assert str_called
50 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/serializers.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth import authenticate
2 | from django.utils.translation import gettext_lazy as _
3 |
4 | from rest_framework import serializers
5 |
6 |
7 | class AuthTokenSerializer(serializers.Serializer):
8 | username = serializers.CharField(
9 | label=_("Username"),
10 | write_only=True
11 | )
12 | password = serializers.CharField(
13 | label=_("Password"),
14 | style={'input_type': 'password'},
15 | trim_whitespace=False,
16 | write_only=True
17 | )
18 | token = serializers.CharField(
19 | label=_("Token"),
20 | read_only=True
21 | )
22 |
23 | def validate(self, attrs):
24 | username = attrs.get('username')
25 | password = attrs.get('password')
26 |
27 | if username and password:
28 | user = authenticate(request=self.context.get('request'),
29 | username=username, password=password)
30 |
31 | # The authenticate call simply returns None for is_active=False
32 | # users. (Assuming the default ModelBackend authentication
33 | # backend.)
34 | if not user:
35 | msg = _('Unable to log in with provided credentials.')
36 | raise serializers.ValidationError(msg, code='authorization')
37 | else:
38 | msg = _('Must include "username" and "password".')
39 | raise serializers.ValidationError(msg, code='authorization')
40 |
41 | attrs['user'] = user
42 | return attrs
43 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/management/commands/drf_create_token.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth import get_user_model
2 | from django.core.management.base import BaseCommand, CommandError
3 |
4 | from rest_framework.authtoken.models import Token
5 |
6 | UserModel = get_user_model()
7 |
8 |
9 | class Command(BaseCommand):
10 | help = 'Create DRF Token for a given user'
11 |
12 | def create_user_token(self, username, reset_token):
13 | user = UserModel._default_manager.get_by_natural_key(username)
14 |
15 | if reset_token:
16 | Token.objects.filter(user=user).delete()
17 |
18 | token = Token.objects.get_or_create(user=user)
19 | return token[0]
20 |
21 | def add_arguments(self, parser):
22 | parser.add_argument('username', type=str)
23 |
24 | parser.add_argument(
25 | '-r',
26 | '--reset',
27 | action='store_true',
28 | dest='reset_token',
29 | default=False,
30 | help='Reset existing User token and create a new one',
31 | )
32 |
33 | def handle(self, *args, **options):
34 | username = options['username']
35 | reset_token = options['reset_token']
36 |
37 | try:
38 | token = self.create_user_token(username, reset_token)
39 | except UserModel.DoesNotExist:
40 | raise CommandError(
41 | 'Cannot create the Token: user {} does not exist'.format(
42 | username)
43 | )
44 | self.stdout.write(
45 | 'Generated token {} for user {}'.format(token.key, username))
46 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # License
2 |
3 | Copyright © 2011-present, [Encode OSS Ltd](https://www.encode.io/).
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/tests/test_reverse.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 | from django.test import TestCase, override_settings
3 | from django.urls import NoReverseMatch
4 |
5 | from rest_framework.reverse import reverse
6 | from rest_framework.test import APIRequestFactory
7 |
8 | factory = APIRequestFactory()
9 |
10 |
11 | def null_view(request):
12 | pass
13 |
14 |
15 | urlpatterns = [
16 | url(r'^view$', null_view, name='view'),
17 | ]
18 |
19 |
20 | class MockVersioningScheme:
21 |
22 | def __init__(self, raise_error=False):
23 | self.raise_error = raise_error
24 |
25 | def reverse(self, *args, **kwargs):
26 | if self.raise_error:
27 | raise NoReverseMatch()
28 |
29 | return 'http://scheme-reversed/view'
30 |
31 |
32 | @override_settings(ROOT_URLCONF='tests.test_reverse')
33 | class ReverseTests(TestCase):
34 | """
35 | Tests for fully qualified URLs when using `reverse`.
36 | """
37 | def test_reversed_urls_are_fully_qualified(self):
38 | request = factory.get('/view')
39 | url = reverse('view', request=request)
40 | assert url == 'http://testserver/view'
41 |
42 | def test_reverse_with_versioning_scheme(self):
43 | request = factory.get('/view')
44 | request.versioning_scheme = MockVersioningScheme()
45 |
46 | url = reverse('view', request=request)
47 | assert url == 'http://scheme-reversed/view'
48 |
49 | def test_reverse_with_versioning_scheme_fallback_to_default_on_error(self):
50 | request = factory.get('/view')
51 | request.versioning_scheme = MockVersioningScheme(raise_error=True)
52 |
53 | url = reverse('view', request=request)
54 | assert url == 'http://testserver/view'
55 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/auth/token.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 |
37 |
--------------------------------------------------------------------------------
/tests/utils.py:
--------------------------------------------------------------------------------
1 | from django.core.exceptions import ObjectDoesNotExist
2 | from django.urls import NoReverseMatch
3 |
4 |
5 | class MockObject:
6 | def __init__(self, **kwargs):
7 | self._kwargs = kwargs
8 | for key, val in kwargs.items():
9 | setattr(self, key, val)
10 |
11 | def __str__(self):
12 | kwargs_str = ', '.join([
13 | '%s=%s' % (key, value)
14 | for key, value in sorted(self._kwargs.items())
15 | ])
16 | return '' % kwargs_str
17 |
18 |
19 | class MockQueryset:
20 | def __init__(self, iterable):
21 | self.items = iterable
22 |
23 | def __getitem__(self, val):
24 | return self.items[val]
25 |
26 | def get(self, **lookup):
27 | for item in self.items:
28 | if all([
29 | getattr(item, key, None) == value
30 | for key, value in lookup.items()
31 | ]):
32 | return item
33 | raise ObjectDoesNotExist()
34 |
35 |
36 | class BadType:
37 | """
38 | When used as a lookup with a `MockQueryset`, these objects
39 | will raise a `TypeError`, as occurs in Django when making
40 | queryset lookups with an incorrect type for the lookup value.
41 | """
42 | def __eq__(self):
43 | raise TypeError()
44 |
45 |
46 | def mock_reverse(view_name, args=None, kwargs=None, request=None, format=None):
47 | args = args or []
48 | kwargs = kwargs or {}
49 | value = (args + list(kwargs.values()) + ['-'])[0]
50 | prefix = 'http://example.org' if request else ''
51 | suffix = ('.' + format) if (format is not None) else ''
52 | return '%s/%s/%s%s/' % (prefix, view_name, value, suffix)
53 |
54 |
55 | def fail_reverse(view_name, args=None, kwargs=None, request=None, format=None):
56 | raise NoReverseMatch()
57 |
--------------------------------------------------------------------------------
/docs/topics/writable-nested-serializers.md:
--------------------------------------------------------------------------------
1 | > To save HTTP requests, it may be convenient to send related documents along with the request.
2 | >
3 | > — [JSON API specification for Ember Data][cite].
4 |
5 | # Writable nested serializers
6 |
7 | Although flat data structures serve to properly delineate between the individual entities in your service, there are cases where it may be more appropriate or convenient to use nested data structures.
8 |
9 | Nested data structures are easy enough to work with if they're read-only - simply nest your serializer classes and you're good to go. However, there are a few more subtleties to using writable nested serializers, due to the dependencies between the various model instances, and the need to save or delete multiple instances in a single action.
10 |
11 | ## One-to-many data structures
12 |
13 | *Example of a **read-only** nested serializer. Nothing complex to worry about here.*
14 |
15 | class ToDoItemSerializer(serializers.ModelSerializer):
16 | class Meta:
17 | model = ToDoItem
18 | fields = ['text', 'is_completed']
19 |
20 | class ToDoListSerializer(serializers.ModelSerializer):
21 | items = ToDoItemSerializer(many=True, read_only=True)
22 |
23 | class Meta:
24 | model = ToDoList
25 | fields = ['title', 'items']
26 |
27 | Some example output from our serializer.
28 |
29 | {
30 | 'title': 'Leaving party preparations',
31 | 'items': [
32 | {'text': 'Compile playlist', 'is_completed': True},
33 | {'text': 'Send invites', 'is_completed': False},
34 | {'text': 'Clean house', 'is_completed': False}
35 | ]
36 | }
37 |
38 | Let's take a look at updating our nested one-to-many data structure.
39 |
40 | ### Validation errors
41 |
42 | ### Adding and removing items
43 |
44 | ### Making PATCH requests
45 |
46 |
47 | [cite]: http://jsonapi.org/format/#url-based-json-api
48 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/js/csrf.js:
--------------------------------------------------------------------------------
1 | function getCookie(name) {
2 | var cookieValue = null;
3 |
4 | if (document.cookie && document.cookie != '') {
5 | var cookies = document.cookie.split(';');
6 |
7 | for (var i = 0; i < cookies.length; i++) {
8 | var cookie = jQuery.trim(cookies[i]);
9 |
10 | // Does this cookie string begin with the name we want?
11 | if (cookie.substring(0, name.length + 1) == (name + '=')) {
12 | cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
13 | break;
14 | }
15 | }
16 | }
17 |
18 | return cookieValue;
19 | }
20 |
21 | function csrfSafeMethod(method) {
22 | // these HTTP methods do not require CSRF protection
23 | return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
24 | }
25 |
26 | function sameOrigin(url) {
27 | // test that a given url is a same-origin URL
28 | // url could be relative or scheme relative or absolute
29 | var host = document.location.host; // host + port
30 | var protocol = document.location.protocol;
31 | var sr_origin = '//' + host;
32 | var origin = protocol + sr_origin;
33 |
34 | // Allow absolute or scheme relative URLs to same origin
35 | return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
36 | (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
37 | // or any other URL that isn't scheme relative or absolute i.e relative.
38 | !(/^(\/\/|http:|https:).*/.test(url));
39 | }
40 |
41 | var csrftoken = window.drf.csrfToken;
42 |
43 | $.ajaxSetup({
44 | beforeSend: function(xhr, settings) {
45 | if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
46 | // Send the token to same-origin, relative URLs only.
47 | // Send the token only if the method warrants CSRF protection
48 | // Using the CSRFToken value acquired earlier
49 | xhr.setRequestHeader(window.drf.csrfHeaderName, csrftoken);
50 | }
51 | }
52 | });
53 |
--------------------------------------------------------------------------------
/rest_framework/schemas/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | rest_framework.schemas
3 |
4 | schemas:
5 | __init__.py
6 | generators.py # Top-down schema generation
7 | inspectors.py # Per-endpoint view introspection
8 | utils.py # Shared helper functions
9 | views.py # Houses `SchemaView`, `APIView` subclass.
10 |
11 | We expose a minimal "public" API directly from `schemas`. This covers the
12 | basic use-cases:
13 |
14 | from rest_framework.schemas import (
15 | AutoSchema,
16 | ManualSchema,
17 | get_schema_view,
18 | SchemaGenerator,
19 | )
20 |
21 | Other access should target the submodules directly
22 | """
23 | from rest_framework.settings import api_settings
24 |
25 | from . import coreapi, openapi
26 | from .coreapi import AutoSchema, ManualSchema, SchemaGenerator # noqa
27 | from .inspectors import DefaultSchema # noqa
28 |
29 |
30 | def get_schema_view(
31 | title=None, url=None, description=None, urlconf=None, renderer_classes=None,
32 | public=False, patterns=None, generator_class=None,
33 | authentication_classes=api_settings.DEFAULT_AUTHENTICATION_CLASSES,
34 | permission_classes=api_settings.DEFAULT_PERMISSION_CLASSES,
35 | version=None):
36 | """
37 | Return a schema view.
38 | """
39 | if generator_class is None:
40 | if coreapi.is_enabled():
41 | generator_class = coreapi.SchemaGenerator
42 | else:
43 | generator_class = openapi.SchemaGenerator
44 |
45 | generator = generator_class(
46 | title=title, url=url, description=description,
47 | urlconf=urlconf, patterns=patterns, version=version
48 | )
49 |
50 | # Avoid import cycle on APIView
51 | from .views import SchemaView
52 | return SchemaView.as_view(
53 | renderer_classes=renderer_classes,
54 | schema_generator=generator,
55 | public=public,
56 | authentication_classes=authentication_classes,
57 | permission_classes=permission_classes,
58 | )
59 |
--------------------------------------------------------------------------------
/rest_framework/schemas/views.py:
--------------------------------------------------------------------------------
1 | """
2 | views.py # Houses `SchemaView`, `APIView` subclass.
3 |
4 | See schemas.__init__.py for package overview.
5 | """
6 | from rest_framework import exceptions, renderers
7 | from rest_framework.response import Response
8 | from rest_framework.schemas import coreapi
9 | from rest_framework.settings import api_settings
10 | from rest_framework.views import APIView
11 |
12 |
13 | class SchemaView(APIView):
14 | _ignore_model_permissions = True
15 | schema = None # exclude from schema
16 | renderer_classes = None
17 | schema_generator = None
18 | public = False
19 |
20 | def __init__(self, *args, **kwargs):
21 | super().__init__(*args, **kwargs)
22 | if self.renderer_classes is None:
23 | if coreapi.is_enabled():
24 | self.renderer_classes = [
25 | renderers.CoreAPIOpenAPIRenderer,
26 | renderers.CoreJSONRenderer
27 | ]
28 | else:
29 | self.renderer_classes = [
30 | renderers.OpenAPIRenderer,
31 | renderers.JSONOpenAPIRenderer,
32 | ]
33 | if renderers.BrowsableAPIRenderer in api_settings.DEFAULT_RENDERER_CLASSES:
34 | self.renderer_classes += [renderers.BrowsableAPIRenderer]
35 |
36 | def get(self, request, *args, **kwargs):
37 | schema = self.schema_generator.get_schema(request, self.public)
38 | if schema is None:
39 | raise exceptions.PermissionDenied()
40 | return Response(schema)
41 |
42 | def handle_exception(self, exc):
43 | # Schema renderers do not render exceptions, so re-perform content
44 | # negotiation with default renderers.
45 | self.renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
46 | neg = self.perform_content_negotiation(self.request, force=True)
47 | self.request.accepted_renderer, self.request.accepted_media_type = neg
48 | return super().handle_exception(exc)
49 |
--------------------------------------------------------------------------------
/docs/api-guide/caching.md:
--------------------------------------------------------------------------------
1 | # Caching
2 |
3 | > A certain woman had a very sharp consciousness but almost no
4 | > memory ... She remembered enough to work, and she worked hard.
5 | > - Lydia Davis
6 |
7 | Caching in REST Framework works well with the cache utilities
8 | provided in Django.
9 |
10 | ---
11 |
12 | ## Using cache with apiview and viewsets
13 |
14 | Django provides a [`method_decorator`][decorator] to use
15 | decorators with class based views. This can be used with
16 | other cache decorators such as [`cache_page`][page] and
17 | [`vary_on_cookie`][cookie].
18 |
19 | ```python
20 | from django.utils.decorators import method_decorator
21 | from django.views.decorators.cache import cache_page
22 | from django.views.decorators.vary import vary_on_cookie
23 |
24 | from rest_framework.response import Response
25 | from rest_framework.views import APIView
26 | from rest_framework import viewsets
27 |
28 |
29 | class UserViewSet(viewsets.ViewSet):
30 |
31 | # Cache requested url for each user for 2 hours
32 | @method_decorator(cache_page(60*60*2))
33 | @method_decorator(vary_on_cookie)
34 | def list(self, request, format=None):
35 | content = {
36 | 'user_feed': request.user.get_user_feed()
37 | }
38 | return Response(content)
39 |
40 |
41 | class PostView(APIView):
42 |
43 | # Cache page for the requested url
44 | @method_decorator(cache_page(60*60*2))
45 | def get(self, request, format=None):
46 | content = {
47 | 'title': 'Post title',
48 | 'body': 'Post content'
49 | }
50 | return Response(content)
51 | ```
52 |
53 | **NOTE:** The [`cache_page`][page] decorator only caches the
54 | `GET` and `HEAD` responses with status 200.
55 |
56 | [page]: https://docs.djangoproject.com/en/dev/topics/cache/#the-per-view-cache
57 | [cookie]: https://docs.djangoproject.com/en/dev/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie
58 | [decorator]: https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/#decorating-the-class
59 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/horizontal/radio.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load rest_framework %}
3 |
4 | {% trans "None" as none_choice %}
5 |
6 |
58 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/interact.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
3 |
4 |
52 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/vertical/radio.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load rest_framework %}
3 | {% trans "None" as none_choice %}
4 |
5 |
58 |
--------------------------------------------------------------------------------
/tests/test_settings.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase, override_settings
2 |
3 | from rest_framework.settings import APISettings, api_settings
4 |
5 |
6 | class TestSettings(TestCase):
7 | def test_import_error_message_maintained(self):
8 | """
9 | Make sure import errors are captured and raised sensibly.
10 | """
11 | settings = APISettings({
12 | 'DEFAULT_RENDERER_CLASSES': [
13 | 'tests.invalid_module.InvalidClassName'
14 | ]
15 | })
16 | with self.assertRaises(ImportError):
17 | settings.DEFAULT_RENDERER_CLASSES
18 |
19 | def test_warning_raised_on_removed_setting(self):
20 | """
21 | Make sure user is alerted with an error when a removed setting
22 | is set.
23 | """
24 | with self.assertRaises(RuntimeError):
25 | APISettings({
26 | 'MAX_PAGINATE_BY': 100
27 | })
28 |
29 | def test_compatibility_with_override_settings(self):
30 | """
31 | Ref #5658 & #2466: Documented usage of api_settings
32 | is bound at import time:
33 |
34 | from rest_framework.settings import api_settings
35 |
36 | setting_changed signal hook must ensure bound instance
37 | is refreshed.
38 | """
39 | assert api_settings.PAGE_SIZE is None, "Checking a known default should be None"
40 |
41 | with override_settings(REST_FRAMEWORK={'PAGE_SIZE': 10}):
42 | assert api_settings.PAGE_SIZE == 10, "Setting should have been updated"
43 |
44 | assert api_settings.PAGE_SIZE is None, "Setting should have been restored"
45 |
46 |
47 | class TestSettingTypes(TestCase):
48 | def test_settings_consistently_coerced_to_list(self):
49 | settings = APISettings({
50 | 'DEFAULT_THROTTLE_CLASSES': ('rest_framework.throttling.BaseThrottle',)
51 | })
52 | self.assertTrue(isinstance(settings.DEFAULT_THROTTLE_CLASSES, list))
53 |
54 | settings = APISettings({
55 | 'DEFAULT_THROTTLE_CLASSES': ()
56 | })
57 | self.assertTrue(isinstance(settings.DEFAULT_THROTTLE_CLASSES, list))
58 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/error.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Error Rendering Schema
10 |
11 |
12 |
13 |
14 |
15 | Error
16 |
17 |
18 | {{ data }}
19 |
20 |
21 |
22 | {% if debug is True %}
23 |
24 | Additional Information
25 | Note: You are seeing this message because DEBUG==True.
26 |
27 | Seeing this page is usually a configuration error: are your
28 | DEFAULT_AUTHENTICATION_CLASSES or DEFAULT_PERMISSION_CLASSES
29 | being applied unexpectedly?
30 |
31 | Your response status code is: {{ response.status_code }}
32 |
33 | 401 Unauthorised.
34 |
35 | Do you have SessionAuthentication enabled?
36 | Are you logged in?
37 |
38 |
39 |
40 | 403 Forbidden.
41 |
42 | Do you have sufficient permissions to access this view?
43 | Is you schema non-empty? (An empty schema will lead to a permission denied error being raised.)
44 |
45 |
46 |
47 | Most commonly the intended solution is to disable authentication and permissions
48 | when including the docs urls:
49 |
50 |
51 | url(r'^docs/', include_docs_urls(title='Your API',
52 | authentication_classes=[],
53 | permission_classes=[])),
54 |
55 |
56 |
57 | Overriding this template
58 |
59 | If you wish access to your docs to be authenticated you may override this template
60 | at rest_framework/docs/error.html.
61 |
62 | The available context is: data the error dict above, request,
63 | response and the debug flag.
64 |
65 | {% endif %}
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/tests/test_prefetch_related.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.models import Group, User
2 | from django.test import TestCase
3 |
4 | from rest_framework import generics, serializers
5 | from rest_framework.test import APIRequestFactory
6 |
7 | factory = APIRequestFactory()
8 |
9 |
10 | class UserSerializer(serializers.ModelSerializer):
11 | class Meta:
12 | model = User
13 | fields = ('id', 'username', 'email', 'groups')
14 |
15 |
16 | class UserUpdate(generics.UpdateAPIView):
17 | queryset = User.objects.exclude(username='exclude').prefetch_related('groups')
18 | serializer_class = UserSerializer
19 |
20 |
21 | class TestPrefetchRelatedUpdates(TestCase):
22 | def setUp(self):
23 | self.user = User.objects.create(username='tom', email='tom@example.com')
24 | self.groups = [Group.objects.create(name='a'), Group.objects.create(name='b')]
25 | self.user.groups.set(self.groups)
26 |
27 | def test_prefetch_related_updates(self):
28 | view = UserUpdate.as_view()
29 | pk = self.user.pk
30 | groups_pk = self.groups[0].pk
31 | request = factory.put('/', {'username': 'new', 'groups': [groups_pk]}, format='json')
32 | response = view(request, pk=pk)
33 | assert User.objects.get(pk=pk).groups.count() == 1
34 | expected = {
35 | 'id': pk,
36 | 'username': 'new',
37 | 'groups': [1],
38 | 'email': 'tom@example.com'
39 | }
40 | assert response.data == expected
41 |
42 | def test_prefetch_related_excluding_instance_from_original_queryset(self):
43 | """
44 | Regression test for https://github.com/encode/django-rest-framework/issues/4661
45 | """
46 | view = UserUpdate.as_view()
47 | pk = self.user.pk
48 | groups_pk = self.groups[0].pk
49 | request = factory.put('/', {'username': 'exclude', 'groups': [groups_pk]}, format='json')
50 | response = view(request, pk=pk)
51 | assert User.objects.get(pk=pk).groups.count() == 1
52 | expected = {
53 | 'id': pk,
54 | 'username': 'exclude',
55 | 'groups': [1],
56 | 'email': 'tom@example.com'
57 | }
58 | assert response.data == expected
59 |
--------------------------------------------------------------------------------
/rest_framework/utils/breadcrumbs.py:
--------------------------------------------------------------------------------
1 | from django.urls import get_script_prefix, resolve
2 |
3 |
4 | def get_breadcrumbs(url, request=None):
5 | """
6 | Given a url returns a list of breadcrumbs, which are each a
7 | tuple of (name, url).
8 | """
9 | from rest_framework.reverse import preserve_builtin_query_params
10 | from rest_framework.views import APIView
11 |
12 | def breadcrumbs_recursive(url, breadcrumbs_list, prefix, seen):
13 | """
14 | Add tuples of (name, url) to the breadcrumbs list,
15 | progressively chomping off parts of the url.
16 | """
17 | try:
18 | (view, unused_args, unused_kwargs) = resolve(url)
19 | except Exception:
20 | pass
21 | else:
22 | # Check if this is a REST framework view,
23 | # and if so add it to the breadcrumbs
24 | cls = getattr(view, 'cls', None)
25 | initkwargs = getattr(view, 'initkwargs', {})
26 | if cls is not None and issubclass(cls, APIView):
27 | # Don't list the same view twice in a row.
28 | # Probably an optional trailing slash.
29 | if not seen or seen[-1] != view:
30 | c = cls(**initkwargs)
31 | name = c.get_view_name()
32 | insert_url = preserve_builtin_query_params(prefix + url, request)
33 | breadcrumbs_list.insert(0, (name, insert_url))
34 | seen.append(view)
35 |
36 | if url == '':
37 | # All done
38 | return breadcrumbs_list
39 |
40 | elif url.endswith('/'):
41 | # Drop trailing slash off the end and continue to try to
42 | # resolve more breadcrumbs
43 | url = url.rstrip('/')
44 | return breadcrumbs_recursive(url, breadcrumbs_list, prefix, seen)
45 |
46 | # Drop trailing non-slash off the end and continue to try to
47 | # resolve more breadcrumbs
48 | url = url[:url.rfind('/') + 1]
49 | return breadcrumbs_recursive(url, breadcrumbs_list, prefix, seen)
50 |
51 | prefix = get_script_prefix().rstrip('/')
52 | url = url[len(prefix):]
53 | return breadcrumbs_recursive(url, [], prefix, [])
54 |
--------------------------------------------------------------------------------
/docs/community/jobs.md:
--------------------------------------------------------------------------------
1 | # Jobs
2 |
3 | Looking for a new Django REST Framework related role? On this site we provide a list of job resources that may be helpful. It's also worth checking out if any of [our sponsors are hiring][drf-funding].
4 |
5 |
6 | ## Places to look for Django REST Framework Jobs
7 |
8 | * [https://www.djangoproject.com/community/jobs/][djangoproject-website]
9 | * [https://www.python.org/jobs/][python-org-jobs]
10 | * [https://djangogigs.com][django-gigs-com]
11 | * [https://djangojobs.net/jobs/][django-jobs-net]
12 | * [https://findwork.dev/django-rest-framework-jobs][findwork-dev]
13 | * [https://www.indeed.com/q-Django-jobs.html][indeed-com]
14 | * [https://stackoverflow.com/jobs/developer-jobs-using-django][stackoverflow-com]
15 | * [https://www.upwork.com/o/jobs/browse/skill/django-framework/][upwork-com]
16 | * [https://www.technojobs.co.uk/django-jobs][technobjobs-co-uk]
17 | * [https://remoteok.io/remote-django-jobs][remoteok-io]
18 | * [https://www.remotepython.com/jobs/][remotepython-com]
19 |
20 |
21 | 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].
22 |
23 | Wonder how else you can help? One of the best ways you can help Django REST Framework is to ask interviewers if their company is signed up for [REST Framework sponsorship][drf-funding] yet.
24 |
25 |
26 | [djangoproject-website]: https://www.djangoproject.com/community/jobs/
27 | [python-org-jobs]: https://www.python.org/jobs/
28 | [django-gigs-com]: https://djangogigs.com
29 | [django-jobs-net]: https://djangojobs.net/jobs/
30 | [findwork-dev]: https://findwork.dev/django-rest-framework-jobs
31 | [indeed-com]: https://www.indeed.com/q-Django-jobs.html
32 | [stackoverflow-com]: https://stackoverflow.com/jobs/developer-jobs-using-django
33 | [upwork-com]: https://www.upwork.com/o/jobs/browse/skill/django-framework/
34 | [technobjobs-co-uk]: https://www.technojobs.co.uk/django-jobs
35 | [remoteok-io]: https://remoteok.io/remote-django-jobs
36 | [remotepython-com]: https://www.remotepython.com/jobs/
37 | [drf-funding]: https://fund.django-rest-framework.org/topics/funding/
38 | [submit-pr]: https://github.com/encode/django-rest-framework
39 | [anna-email]: mailto:anna@django-rest-framework.org
40 |
--------------------------------------------------------------------------------
/tests/test_multitable_inheritance.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 | from django.test import TestCase
3 |
4 | from rest_framework import serializers
5 | from tests.models import RESTFrameworkModel
6 |
7 |
8 | # Models
9 | class ParentModel(RESTFrameworkModel):
10 | name1 = models.CharField(max_length=100)
11 |
12 |
13 | class ChildModel(ParentModel):
14 | name2 = models.CharField(max_length=100)
15 |
16 |
17 | class AssociatedModel(RESTFrameworkModel):
18 | ref = models.OneToOneField(ParentModel, primary_key=True, on_delete=models.CASCADE)
19 | name = models.CharField(max_length=100)
20 |
21 |
22 | # Serializers
23 | class DerivedModelSerializer(serializers.ModelSerializer):
24 | class Meta:
25 | model = ChildModel
26 | fields = '__all__'
27 |
28 |
29 | class AssociatedModelSerializer(serializers.ModelSerializer):
30 | class Meta:
31 | model = AssociatedModel
32 | fields = '__all__'
33 |
34 |
35 | # Tests
36 | class InheritedModelSerializationTests(TestCase):
37 |
38 | def test_multitable_inherited_model_fields_as_expected(self):
39 | """
40 | Assert that the parent pointer field is not included in the fields
41 | serialized fields
42 | """
43 | child = ChildModel(name1='parent name', name2='child name')
44 | serializer = DerivedModelSerializer(child)
45 | assert set(serializer.data) == {'name1', 'name2', 'id'}
46 |
47 | def test_onetoone_primary_key_model_fields_as_expected(self):
48 | """
49 | Assert that a model with a onetoone field that is the primary key is
50 | not treated like a derived model
51 | """
52 | parent = ParentModel.objects.create(name1='parent name')
53 | associate = AssociatedModel.objects.create(name='hello', ref=parent)
54 | serializer = AssociatedModelSerializer(associate)
55 | assert set(serializer.data) == {'name', 'ref'}
56 |
57 | def test_data_is_valid_without_parent_ptr(self):
58 | """
59 | Assert that the pointer to the parent table is not a required field
60 | for input data
61 | """
62 | data = {
63 | 'name1': 'parent name',
64 | 'name2': 'child name',
65 | }
66 | serializer = DerivedModelSerializer(data=data)
67 | assert serializer.is_valid() is True
68 |
--------------------------------------------------------------------------------
/tests/generic_relations/test_generic_relations.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | from rest_framework import serializers
4 |
5 | from .models import Bookmark, Note, Tag
6 |
7 |
8 | class TestGenericRelations(TestCase):
9 | def setUp(self):
10 | self.bookmark = Bookmark.objects.create(url='https://www.djangoproject.com/')
11 | Tag.objects.create(tagged_item=self.bookmark, tag='django')
12 | Tag.objects.create(tagged_item=self.bookmark, tag='python')
13 | self.note = Note.objects.create(text='Remember the milk')
14 | Tag.objects.create(tagged_item=self.note, tag='reminder')
15 |
16 | def test_generic_relation(self):
17 | """
18 | Test a relationship that spans a GenericRelation field.
19 | IE. A reverse generic relationship.
20 | """
21 |
22 | class BookmarkSerializer(serializers.ModelSerializer):
23 | tags = serializers.StringRelatedField(many=True)
24 |
25 | class Meta:
26 | model = Bookmark
27 | fields = ('tags', 'url')
28 |
29 | serializer = BookmarkSerializer(self.bookmark)
30 | expected = {
31 | 'tags': ['django', 'python'],
32 | 'url': 'https://www.djangoproject.com/'
33 | }
34 | assert serializer.data == expected
35 |
36 | def test_generic_fk(self):
37 | """
38 | Test a relationship that spans a GenericForeignKey field.
39 | IE. A forward generic relationship.
40 | """
41 |
42 | class TagSerializer(serializers.ModelSerializer):
43 | tagged_item = serializers.StringRelatedField()
44 |
45 | class Meta:
46 | model = Tag
47 | fields = ('tag', 'tagged_item')
48 |
49 | serializer = TagSerializer(Tag.objects.all(), many=True)
50 | expected = [
51 | {
52 | 'tag': 'django',
53 | 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
54 | },
55 | {
56 | 'tag': 'python',
57 | 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
58 | },
59 | {
60 | 'tag': 'reminder',
61 | 'tagged_item': 'Note: Remember the milk'
62 | }
63 | ]
64 | assert serializer.data == expected
65 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/docs/css/highlight.css:
--------------------------------------------------------------------------------
1 | /*
2 | This is the GitHub theme for highlight.js
3 |
4 | github.com style (c) Vasily Polovnyov
5 |
6 | */
7 |
8 | .hljs {
9 | display: block;
10 | overflow-x: auto;
11 | padding: 0.5em;
12 | color: #333;
13 | -webkit-text-size-adjust: none;
14 | }
15 |
16 | .hljs-comment,
17 | .diff .hljs-header,
18 | .hljs-javadoc {
19 | color: #998;
20 | font-style: italic;
21 | }
22 |
23 | .hljs-keyword,
24 | .css .rule .hljs-keyword,
25 | .hljs-winutils,
26 | .nginx .hljs-title,
27 | .hljs-subst,
28 | .hljs-request,
29 | .hljs-status {
30 | color: #333;
31 | font-weight: bold;
32 | }
33 |
34 | .hljs-number,
35 | .hljs-hexcolor,
36 | .ruby .hljs-constant {
37 | color: #008080;
38 | }
39 |
40 | .hljs-string,
41 | .hljs-tag .hljs-value,
42 | .hljs-phpdoc,
43 | .hljs-dartdoc,
44 | .tex .hljs-formula {
45 | color: #d14;
46 | }
47 |
48 | .hljs-title,
49 | .hljs-id,
50 | .scss .hljs-preprocessor {
51 | color: #900;
52 | font-weight: bold;
53 | }
54 |
55 | .hljs-list .hljs-keyword,
56 | .hljs-subst {
57 | font-weight: normal;
58 | }
59 |
60 | .hljs-class .hljs-title,
61 | .hljs-type,
62 | .vhdl .hljs-literal,
63 | .tex .hljs-command {
64 | color: #458;
65 | font-weight: bold;
66 | }
67 |
68 | .hljs-tag,
69 | .hljs-tag .hljs-title,
70 | .hljs-rule .hljs-property,
71 | .django .hljs-tag .hljs-keyword {
72 | color: #000080;
73 | font-weight: normal;
74 | }
75 |
76 | .hljs-attribute,
77 | .hljs-variable,
78 | .lisp .hljs-body,
79 | .hljs-name {
80 | color: #008080;
81 | }
82 |
83 | .hljs-regexp {
84 | color: #009926;
85 | }
86 |
87 | .hljs-symbol,
88 | .ruby .hljs-symbol .hljs-string,
89 | .lisp .hljs-keyword,
90 | .clojure .hljs-keyword,
91 | .scheme .hljs-keyword,
92 | .tex .hljs-special,
93 | .hljs-prompt {
94 | color: #990073;
95 | }
96 |
97 | .hljs-built_in {
98 | color: #0086b3;
99 | }
100 |
101 | .hljs-preprocessor,
102 | .hljs-pragma,
103 | .hljs-pi,
104 | .hljs-doctype,
105 | .hljs-shebang,
106 | .hljs-cdata {
107 | color: #999;
108 | font-weight: bold;
109 | }
110 |
111 | .hljs-deletion {
112 | background: #fdd;
113 | }
114 |
115 | .hljs-addition {
116 | background: #dfd;
117 | }
118 |
119 | .diff .hljs-change {
120 | background: #0086b3;
121 | }
122 |
123 | .hljs-chunk {
124 | color: #aaa;
125 | }
126 |
--------------------------------------------------------------------------------
/rest_framework/reverse.py:
--------------------------------------------------------------------------------
1 | """
2 | Provide urlresolver functions that return fully qualified URLs or view names
3 | """
4 | from django.urls import NoReverseMatch
5 | from django.urls import reverse as django_reverse
6 | from django.utils.functional import lazy
7 |
8 | from rest_framework.settings import api_settings
9 | from rest_framework.utils.urls import replace_query_param
10 |
11 |
12 | def preserve_builtin_query_params(url, request=None):
13 | """
14 | Given an incoming request, and an outgoing URL representation,
15 | append the value of any built-in query parameters.
16 | """
17 | if request is None:
18 | return url
19 |
20 | overrides = [
21 | api_settings.URL_FORMAT_OVERRIDE,
22 | ]
23 |
24 | for param in overrides:
25 | if param and (param in request.GET):
26 | value = request.GET[param]
27 | url = replace_query_param(url, param, value)
28 |
29 | return url
30 |
31 |
32 | def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra):
33 | """
34 | If versioning is being used then we pass any `reverse` calls through
35 | to the versioning scheme instance, so that the resulting URL
36 | can be modified if needed.
37 | """
38 | scheme = getattr(request, 'versioning_scheme', None)
39 | if scheme is not None:
40 | try:
41 | url = scheme.reverse(viewname, args, kwargs, request, format, **extra)
42 | except NoReverseMatch:
43 | # In case the versioning scheme reversal fails, fallback to the
44 | # default implementation
45 | url = _reverse(viewname, args, kwargs, request, format, **extra)
46 | else:
47 | url = _reverse(viewname, args, kwargs, request, format, **extra)
48 |
49 | return preserve_builtin_query_params(url, request)
50 |
51 |
52 | def _reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra):
53 | """
54 | Same as `django.urls.reverse`, but optionally takes a request
55 | and returns a fully qualified URL, using the request to get the base URL.
56 | """
57 | if format is not None:
58 | kwargs = kwargs or {}
59 | kwargs['format'] = format
60 | url = django_reverse(viewname, args=args, kwargs=kwargs, **extra)
61 | if request:
62 | return request.build_absolute_uri(url)
63 | return url
64 |
65 |
66 | reverse_lazy = lazy(reverse, str)
67 |
--------------------------------------------------------------------------------
/rest_framework/authtoken/views.py:
--------------------------------------------------------------------------------
1 | from rest_framework import parsers, renderers
2 | from rest_framework.authtoken.models import Token
3 | from rest_framework.authtoken.serializers import AuthTokenSerializer
4 | from rest_framework.compat import coreapi, coreschema
5 | from rest_framework.response import Response
6 | from rest_framework.schemas import ManualSchema
7 | from rest_framework.schemas import coreapi as coreapi_schema
8 | from rest_framework.views import APIView
9 |
10 |
11 | class ObtainAuthToken(APIView):
12 | throttle_classes = ()
13 | permission_classes = ()
14 | parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
15 | renderer_classes = (renderers.JSONRenderer,)
16 | serializer_class = AuthTokenSerializer
17 |
18 | if coreapi_schema.is_enabled():
19 | schema = ManualSchema(
20 | fields=[
21 | coreapi.Field(
22 | name="username",
23 | required=True,
24 | location='form',
25 | schema=coreschema.String(
26 | title="Username",
27 | description="Valid username for authentication",
28 | ),
29 | ),
30 | coreapi.Field(
31 | name="password",
32 | required=True,
33 | location='form',
34 | schema=coreschema.String(
35 | title="Password",
36 | description="Valid password for authentication",
37 | ),
38 | ),
39 | ],
40 | encoding="application/json",
41 | )
42 |
43 | def get_serializer_context(self):
44 | return {
45 | 'request': self.request,
46 | 'format': self.format_kwarg,
47 | 'view': self
48 | }
49 |
50 | def get_serializer(self, *args, **kwargs):
51 | kwargs['context'] = self.get_serializer_context()
52 | return self.serializer_class(*args, **kwargs)
53 |
54 | def post(self, request, *args, **kwargs):
55 | serializer = self.get_serializer(data=request.data)
56 | serializer.is_valid(raise_exception=True)
57 | user = serializer.validated_data['user']
58 | token, created = Token.objects.get_or_create(user=user)
59 | return Response({'token': token.key})
60 |
61 |
62 | obtain_auth_token = ObtainAuthToken.as_view()
63 |
--------------------------------------------------------------------------------
/docs_theme/nav.html:
--------------------------------------------------------------------------------
1 |
47 |
--------------------------------------------------------------------------------
/docs/api-guide/reverse.md:
--------------------------------------------------------------------------------
1 | ---
2 | source:
3 | - reverse.py
4 | ---
5 |
6 | # Returning URLs
7 |
8 | > The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components.
9 | >
10 | > — Roy Fielding, [Architectural Styles and the Design of Network-based Software Architectures][cite]
11 |
12 | As a rule, it's probably better practice to return absolute URIs from your Web APIs, such as `http://example.com/foobar`, rather than returning relative URIs, such as `/foobar`.
13 |
14 | The advantages of doing so are:
15 |
16 | * It's more explicit.
17 | * It leaves less work for your API clients.
18 | * There's no ambiguity about the meaning of the string when it's found in representations such as JSON that do not have a native URI type.
19 | * It makes it easy to do things like markup HTML representations with hyperlinks.
20 |
21 | REST framework provides two utility functions to make it more simple to return absolute URIs from your Web API.
22 |
23 | There's no requirement for you to use them, but if you do then the self-describing API will be able to automatically hyperlink its output for you, which makes browsing the API much easier.
24 |
25 | ## reverse
26 |
27 | **Signature:** `reverse(viewname, *args, **kwargs)`
28 |
29 | Has the same behavior as [`django.urls.reverse`][reverse], except that it returns a fully qualified URL, using the request to determine the host and port.
30 |
31 | You should **include the request as a keyword argument** to the function, for example:
32 |
33 | from rest_framework.reverse import reverse
34 | from rest_framework.views import APIView
35 | from django.utils.timezone import now
36 |
37 | class APIRootView(APIView):
38 | def get(self, request):
39 | year = now().year
40 | data = {
41 | ...
42 | 'year-summary-url': reverse('year-summary', args=[year], request=request)
43 | }
44 | return Response(data)
45 |
46 | ## reverse_lazy
47 |
48 | **Signature:** `reverse_lazy(viewname, *args, **kwargs)`
49 |
50 | Has the same behavior as [`django.urls.reverse_lazy`][reverse-lazy], except that it returns a fully qualified URL, using the request to determine the host and port.
51 |
52 | As with the `reverse` function, you should **include the request as a keyword argument** to the function, for example:
53 |
54 | api_root = reverse_lazy('api-root', request=request)
55 |
56 | [cite]: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5
57 | [reverse]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse
58 | [reverse-lazy]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse-lazy
59 |
--------------------------------------------------------------------------------
/rest_framework/static/rest_framework/docs/js/jquery.json-view.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jquery.json-view - jQuery collapsible JSON plugin
3 | * @version v1.0.0
4 | * @link http://github.com/bazh/jquery.json-view
5 | * @license MIT
6 | */
7 | !function(e){"use strict";var n=function(n){var a=e(" ",{"class":"collapser",on:{click:function(){var n=e(this);n.toggleClass("collapsed");var a=n.parent().children(".block"),p=a.children("ul");n.hasClass("collapsed")?(p.hide(),a.children(".dots, .comments").show()):(p.show(),a.children(".dots, .comments").hide())}}});return n&&a.addClass("collapsed"),a},a=function(a,p){var t=e.extend({},{nl2br:!0},p),r=function(e){return e.toString()?e.toString().replace(/&/g,"&").replace(/"/g,""").replace(//g,">"):""},s=function(n,a){return e(" ",{"class":a,html:r(n)})},l=function(a,p){switch(e.type(a)){case"object":p||(p=0);var c=e(" ",{"class":"block"}),d=Object.keys(a).length;if(!d)return c.append(s("{","b")).append(" ").append(s("}","b"));c.append(s("{","b"));var i=e("",{"class":"obj collapsible level"+p});return e.each(a,function(a,t){d--;var r=e(" ").append(s('"',"q")).append(a).append(s('"',"q")).append(": ").append(l(t,p+1));-1===["object","array"].indexOf(e.type(t))||e.isEmptyObject(t)||r.prepend(n()),d>0&&r.append(","),i.append(r)}),c.append(i),c.append(s("...","dots")),c.append(s("}","b")),c.append(1===Object.keys(a).length?s("// 1 item","comments"):s("// "+Object.keys(a).length+" items","comments")),c;case"array":p||(p=0);var d=a.length,c=e(" ",{"class":"block"});if(!d)return c.append(s("[","b")).append(" ").append(s("]","b"));c.append(s("[","b"));var i=e("",{"class":"obj collapsible level"+p});return e.each(a,function(a,t){d--;var r=e(" ").append(l(t,p+1));-1===["object","array"].indexOf(e.type(t))||e.isEmptyObject(t)||r.prepend(n()),d>0&&r.append(","),i.append(r)}),c.append(i),c.append(s("...","dots")),c.append(s("]","b")),c.append(1===a.length?s("// 1 item","comments"):s("// "+a.length+" items","comments")),c;case"string":if(a=r(a),/^(http|https|file):\/\/[^\s]+$/i.test(a))return e(" ").append(s('"',"q")).append(e(" ",{href:a,text:a})).append(s('"',"q"));if(t.nl2br){var o=/\n/g;o.test(a)&&(a=(a+"").replace(o," "))}var u=e(" ",{"class":"str"}).html(a);return e(" ").append(s('"',"q")).append(u).append(s('"',"q"));case"number":return s(a.toString(),"num");case"undefined":return s("undefined","undef");case"null":return s("null","null");case"boolean":return s(a?"true":"false","bool")}};return l(a)};return e.fn.jsonView=function(n,p){var t=e(this);if(p=e.extend({},{nl2br:!0},p),"string"==typeof n)try{n=JSON.parse(n)}catch(r){}return t.append(e("
",{"class":"json-view"}).append(a(n,p))),t}}(jQuery);
--------------------------------------------------------------------------------
/rest_framework/utils/html.py:
--------------------------------------------------------------------------------
1 | """
2 | Helpers for dealing with HTML input.
3 | """
4 | import re
5 |
6 | from django.utils.datastructures import MultiValueDict
7 |
8 |
9 | def is_html_input(dictionary):
10 | # MultiDict type datastructures are used to represent HTML form input,
11 | # which may have more than one value for each key.
12 | return hasattr(dictionary, 'getlist')
13 |
14 |
15 | def parse_html_list(dictionary, prefix='', default=None):
16 | """
17 | Used to support list values in HTML forms.
18 | Supports lists of primitives and/or dictionaries.
19 |
20 | * List of primitives.
21 |
22 | {
23 | '[0]': 'abc',
24 | '[1]': 'def',
25 | '[2]': 'hij'
26 | }
27 | -->
28 | [
29 | 'abc',
30 | 'def',
31 | 'hij'
32 | ]
33 |
34 | * List of dictionaries.
35 |
36 | {
37 | '[0]foo': 'abc',
38 | '[0]bar': 'def',
39 | '[1]foo': 'hij',
40 | '[1]bar': 'klm',
41 | }
42 | -->
43 | [
44 | {'foo': 'abc', 'bar': 'def'},
45 | {'foo': 'hij', 'bar': 'klm'}
46 | ]
47 |
48 | :returns a list of objects, or the value specified in ``default`` if the list is empty
49 | """
50 | ret = {}
51 | regex = re.compile(r'^%s\[([0-9]+)\](.*)$' % re.escape(prefix))
52 | for field, value in dictionary.items():
53 | match = regex.match(field)
54 | if not match:
55 | continue
56 | index, key = match.groups()
57 | index = int(index)
58 | if not key:
59 | ret[index] = value
60 | elif isinstance(ret.get(index), dict):
61 | ret[index][key] = value
62 | else:
63 | ret[index] = MultiValueDict({key: [value]})
64 |
65 | # return the items of the ``ret`` dict, sorted by key, or ``default`` if the dict is empty
66 | return [ret[item] for item in sorted(ret)] if ret else default
67 |
68 |
69 | def parse_html_dict(dictionary, prefix=''):
70 | """
71 | Used to support dictionary values in HTML forms.
72 |
73 | {
74 | 'profile.username': 'example',
75 | 'profile.email': 'example@example.com',
76 | }
77 | -->
78 | {
79 | 'profile': {
80 | 'username': 'example',
81 | 'email': 'example@example.com'
82 | }
83 | }
84 | """
85 | ret = MultiValueDict()
86 | regex = re.compile(r'^%s\.(.+)$' % re.escape(prefix))
87 | for field in dictionary:
88 | match = regex.match(field)
89 | if not match:
90 | continue
91 | key = match.groups()[0]
92 | value = dictionary.getlist(field)
93 | ret.setlist(key, value)
94 |
95 | return ret
96 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/index.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ document.title }}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | {% if code_style %}{% endif %}
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | {% include "rest_framework/docs/sidebar.html" %}
28 |
29 |
30 |
31 |
32 | {% include "rest_framework/docs/document.html" %}
33 |
34 |
35 |
36 |
37 | {% include "rest_framework/docs/auth/token.html" %}
38 | {% include "rest_framework/docs/auth/basic.html" %}
39 | {% include "rest_framework/docs/auth/session.html" %}
40 |
41 |
42 |
43 |
44 |
45 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/rest_framework/templates/rest_framework/docs/sidebar.html:
--------------------------------------------------------------------------------
1 | {% load rest_framework %}
2 |
45 |
--------------------------------------------------------------------------------
/rest_framework/utils/encoders.py:
--------------------------------------------------------------------------------
1 | """
2 | Helper classes for parsers.
3 | """
4 | import datetime
5 | import decimal
6 | import json # noqa
7 | import uuid
8 |
9 | from django.db.models.query import QuerySet
10 | from django.utils import timezone
11 | from django.utils.encoding import force_str
12 | from django.utils.functional import Promise
13 |
14 | from rest_framework.compat import coreapi
15 |
16 |
17 | class JSONEncoder(json.JSONEncoder):
18 | """
19 | JSONEncoder subclass that knows how to encode date/time/timedelta,
20 | decimal types, generators and other basic python objects.
21 | """
22 | def default(self, obj):
23 | # For Date Time string spec, see ECMA 262
24 | # https://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
25 | if isinstance(obj, Promise):
26 | return force_str(obj)
27 | elif isinstance(obj, datetime.datetime):
28 | representation = obj.isoformat()
29 | if representation.endswith('+00:00'):
30 | representation = representation[:-6] + 'Z'
31 | return representation
32 | elif isinstance(obj, datetime.date):
33 | return obj.isoformat()
34 | elif isinstance(obj, datetime.time):
35 | if timezone and timezone.is_aware(obj):
36 | raise ValueError("JSON can't represent timezone-aware times.")
37 | representation = obj.isoformat()
38 | return representation
39 | elif isinstance(obj, datetime.timedelta):
40 | return str(obj.total_seconds())
41 | elif isinstance(obj, decimal.Decimal):
42 | # Serializers will coerce decimals to strings by default.
43 | return float(obj)
44 | elif isinstance(obj, uuid.UUID):
45 | return str(obj)
46 | elif isinstance(obj, QuerySet):
47 | return tuple(obj)
48 | elif isinstance(obj, bytes):
49 | # Best-effort for binary blobs. See #4187.
50 | return obj.decode()
51 | elif hasattr(obj, 'tolist'):
52 | # Numpy arrays and array scalars.
53 | return obj.tolist()
54 | elif (coreapi is not None) and isinstance(obj, (coreapi.Document, coreapi.Error)):
55 | raise RuntimeError(
56 | 'Cannot return a coreapi object from a JSON view. '
57 | 'You should be using a schema renderer instead for this view.'
58 | )
59 | elif hasattr(obj, '__getitem__'):
60 | cls = (list if isinstance(obj, (list, tuple)) else dict)
61 | try:
62 | return cls(obj)
63 | except Exception:
64 | pass
65 | elif hasattr(obj, '__iter__'):
66 | return tuple(item for item in obj)
67 | return super().default(obj)
68 |
--------------------------------------------------------------------------------
/rest_framework/status.py:
--------------------------------------------------------------------------------
1 | """
2 | Descriptive HTTP status codes, for code readability.
3 |
4 | See RFC 2616 - https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
5 | And RFC 6585 - https://tools.ietf.org/html/rfc6585
6 | And RFC 4918 - https://tools.ietf.org/html/rfc4918
7 | """
8 |
9 |
10 | def is_informational(code):
11 | return 100 <= code <= 199
12 |
13 |
14 | def is_success(code):
15 | return 200 <= code <= 299
16 |
17 |
18 | def is_redirect(code):
19 | return 300 <= code <= 399
20 |
21 |
22 | def is_client_error(code):
23 | return 400 <= code <= 499
24 |
25 |
26 | def is_server_error(code):
27 | return 500 <= code <= 599
28 |
29 |
30 | HTTP_100_CONTINUE = 100
31 | HTTP_101_SWITCHING_PROTOCOLS = 101
32 | HTTP_200_OK = 200
33 | HTTP_201_CREATED = 201
34 | HTTP_202_ACCEPTED = 202
35 | HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203
36 | HTTP_204_NO_CONTENT = 204
37 | HTTP_205_RESET_CONTENT = 205
38 | HTTP_206_PARTIAL_CONTENT = 206
39 | HTTP_207_MULTI_STATUS = 207
40 | HTTP_208_ALREADY_REPORTED = 208
41 | HTTP_226_IM_USED = 226
42 | HTTP_300_MULTIPLE_CHOICES = 300
43 | HTTP_301_MOVED_PERMANENTLY = 301
44 | HTTP_302_FOUND = 302
45 | HTTP_303_SEE_OTHER = 303
46 | HTTP_304_NOT_MODIFIED = 304
47 | HTTP_305_USE_PROXY = 305
48 | HTTP_306_RESERVED = 306
49 | HTTP_307_TEMPORARY_REDIRECT = 307
50 | HTTP_308_PERMANENT_REDIRECT = 308
51 | HTTP_400_BAD_REQUEST = 400
52 | HTTP_401_UNAUTHORIZED = 401
53 | HTTP_402_PAYMENT_REQUIRED = 402
54 | HTTP_403_FORBIDDEN = 403
55 | HTTP_404_NOT_FOUND = 404
56 | HTTP_405_METHOD_NOT_ALLOWED = 405
57 | HTTP_406_NOT_ACCEPTABLE = 406
58 | HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407
59 | HTTP_408_REQUEST_TIMEOUT = 408
60 | HTTP_409_CONFLICT = 409
61 | HTTP_410_GONE = 410
62 | HTTP_411_LENGTH_REQUIRED = 411
63 | HTTP_412_PRECONDITION_FAILED = 412
64 | HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413
65 | HTTP_414_REQUEST_URI_TOO_LONG = 414
66 | HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415
67 | HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416
68 | HTTP_417_EXPECTATION_FAILED = 417
69 | HTTP_418_IM_A_TEAPOT = 418
70 | HTTP_422_UNPROCESSABLE_ENTITY = 422
71 | HTTP_423_LOCKED = 423
72 | HTTP_424_FAILED_DEPENDENCY = 424
73 | HTTP_426_UPGRADE_REQUIRED = 426
74 | HTTP_428_PRECONDITION_REQUIRED = 428
75 | HTTP_429_TOO_MANY_REQUESTS = 429
76 | HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
77 | HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451
78 | HTTP_500_INTERNAL_SERVER_ERROR = 500
79 | HTTP_501_NOT_IMPLEMENTED = 501
80 | HTTP_502_BAD_GATEWAY = 502
81 | HTTP_503_SERVICE_UNAVAILABLE = 503
82 | HTTP_504_GATEWAY_TIMEOUT = 504
83 | HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505
84 | HTTP_506_VARIANT_ALSO_NEGOTIATES = 506
85 | HTTP_507_INSUFFICIENT_STORAGE = 507
86 | HTTP_508_LOOP_DETECTED = 508
87 | HTTP_509_BANDWIDTH_LIMIT_EXCEEDED = 509
88 | HTTP_510_NOT_EXTENDED = 510
89 | HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511
90 |
--------------------------------------------------------------------------------
/tests/test_middleware.py:
--------------------------------------------------------------------------------
1 | from django.conf.urls import url
2 | from django.contrib.auth.models import User
3 | from django.http import HttpRequest
4 | from django.test import override_settings
5 |
6 | from rest_framework.authentication import TokenAuthentication
7 | from rest_framework.authtoken.models import Token
8 | from rest_framework.request import is_form_media_type
9 | from rest_framework.response import Response
10 | from rest_framework.test import APITestCase
11 | from rest_framework.views import APIView
12 |
13 |
14 | class PostView(APIView):
15 | def post(self, request):
16 | return Response(data=request.data, status=200)
17 |
18 |
19 | urlpatterns = [
20 | url(r'^auth$', APIView.as_view(authentication_classes=(TokenAuthentication,))),
21 | url(r'^post$', PostView.as_view()),
22 | ]
23 |
24 |
25 | class RequestUserMiddleware:
26 | def __init__(self, get_response):
27 | self.get_response = get_response
28 |
29 | def __call__(self, request):
30 | response = self.get_response(request)
31 | assert hasattr(request, 'user'), '`user` is not set on request'
32 | assert request.user.is_authenticated, '`user` is not authenticated'
33 |
34 | return response
35 |
36 |
37 | class RequestPOSTMiddleware:
38 | def __init__(self, get_response):
39 | self.get_response = get_response
40 |
41 | def __call__(self, request):
42 | assert isinstance(request, HttpRequest)
43 |
44 | # Parse body with underlying Django request
45 | request.body
46 |
47 | # Process request with DRF view
48 | response = self.get_response(request)
49 |
50 | # Ensure request.POST is set as appropriate
51 | if is_form_media_type(request.content_type):
52 | assert request.POST == {'foo': ['bar']}
53 | else:
54 | assert request.POST == {}
55 |
56 | return response
57 |
58 |
59 | @override_settings(ROOT_URLCONF='tests.test_middleware')
60 | class TestMiddleware(APITestCase):
61 |
62 | @override_settings(MIDDLEWARE=('tests.test_middleware.RequestUserMiddleware',))
63 | def test_middleware_can_access_user_when_processing_response(self):
64 | user = User.objects.create_user('john', 'john@example.com', 'password')
65 | key = 'abcd1234'
66 | Token.objects.create(key=key, user=user)
67 |
68 | self.client.get('/auth', HTTP_AUTHORIZATION='Token %s' % key)
69 |
70 | @override_settings(MIDDLEWARE=('tests.test_middleware.RequestPOSTMiddleware',))
71 | def test_middleware_can_access_request_post_when_processing_response(self):
72 | response = self.client.post('/post', {'foo': 'bar'})
73 | assert response.status_code == 200
74 |
75 | response = self.client.post('/post', {'foo': 'bar'}, format='json')
76 | assert response.status_code == 200
77 |
--------------------------------------------------------------------------------