From 01587b9eb17bf68c716e84e616202d6e4ccbaecf Mon Sep 17 00:00:00 2001 From: Hang Park Date: Mon, 4 Dec 2017 21:00:03 +0900 Subject: [PATCH 001/520] Typos in serializers documentation (#5652) Fixes #5651. Change `update()` to `.update()` in serializers documentation to get a consistency with `.create()`. --- docs/api-guide/serializers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index ee6e41607..89196949d 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -73,7 +73,7 @@ Deserialization is similar. First we parse a stream into Python native datatypes ## Saving instances -If we want to be able to return complete object instances based on the validated data we need to implement one or both of the `.create()` and `update()` methods. For example: +If we want to be able to return complete object instances based on the validated data we need to implement one or both of the `.create()` and `.update()` methods. For example: class CommentSerializer(serializers.Serializer): email = serializers.EmailField() @@ -325,7 +325,7 @@ For updates you'll want to think carefully about how to handle updates to relati * Ignore the data and leave the instance as it is. * Raise a validation error. -Here's an example for an `update()` method on our previous `UserSerializer` class. +Here's an example for an `.update()` method on our previous `UserSerializer` class. def update(self, instance, validated_data): profile_data = validated_data.pop('profile') From 1692feb535472cb78c49328613a14aef48f77787 Mon Sep 17 00:00:00 2001 From: Anna Ossowski Date: Wed, 6 Dec 2017 03:10:41 +0100 Subject: [PATCH 002/520] Updated monthly report link --- docs/topics/funding.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/topics/funding.md b/docs/topics/funding.md index f9c31e79a..8b0735099 100644 --- a/docs/topics/funding.md +++ b/docs/topics/funding.md @@ -340,7 +340,7 @@ For further enquires please contact From 4a200d5e66e093ae6f8c6e94eb749ed588849ce0 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Dec 2017 10:33:48 +0100 Subject: [PATCH 003/520] Fix `override_settings` compat (#5668) * Add test checking override_settings compat * Refresh APISettings, rather than replace Fix suggested by @daggaz https://github.com/encode/django-rest-framework/issues/2466#issuecomment-344297213 --- rest_framework/settings.py | 14 +++++++++++--- tests/test_settings.py | 21 +++++++++++++++++++-- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/rest_framework/settings.py b/rest_framework/settings.py index d9e3a2942..478a5229f 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -200,6 +200,7 @@ class APISettings(object): self._user_settings = self.__check_user_settings(user_settings) self.defaults = defaults or DEFAULTS self.import_strings = import_strings or IMPORT_STRINGS + self._cached_attrs = set() @property def user_settings(self): @@ -223,6 +224,7 @@ class APISettings(object): val = perform_import(val, attr) # Cache the result + self._cached_attrs.add(attr) setattr(self, attr, val) return val @@ -233,15 +235,21 @@ class APISettings(object): raise RuntimeError("The '%s' setting has been removed. Please refer to '%s' for available settings." % (setting, SETTINGS_DOC)) return user_settings + def reload(self): + for attr in self._cached_attrs: + delattr(self, attr) + self._cached_attrs.clear() + if hasattr(self, '_user_settings'): + delattr(self, '_user_settings') + api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) def reload_api_settings(*args, **kwargs): - global api_settings - setting, value = kwargs['setting'], kwargs['value'] + setting = kwargs['setting'] if setting == 'REST_FRAMEWORK': - api_settings = APISettings(value, DEFAULTS, IMPORT_STRINGS) + api_settings.reload() setting_changed.connect(reload_api_settings) diff --git a/tests/test_settings.py b/tests/test_settings.py index 9ba552d28..51e9751b2 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -1,8 +1,8 @@ from __future__ import unicode_literals -from django.test import TestCase +from django.test import TestCase, override_settings -from rest_framework.settings import APISettings +from rest_framework.settings import APISettings, api_settings class TestSettings(TestCase): @@ -28,6 +28,23 @@ class TestSettings(TestCase): 'MAX_PAGINATE_BY': 100 }) + def test_compatibility_with_override_settings(self): + """ + Ref #5658 & #2466: Documented usage of api_settings + is bound at import time: + + from rest_framework.settings import api_settings + + setting_changed signal hook must ensure bound instance + is refreshed. + """ + assert api_settings.PAGE_SIZE is None, "Checking a known default should be None" + + with override_settings(REST_FRAMEWORK={'PAGE_SIZE': 10}): + assert api_settings.PAGE_SIZE == 10, "Setting should have been updated" + + assert api_settings.PAGE_SIZE is None, "Setting should have been restored" + class TestSettingTypes(TestCase): def test_settings_consistently_coerced_to_list(self): From 791539acecb801f3830948dea727f459cbd4b122 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Dec 2017 11:24:21 +0100 Subject: [PATCH 004/520] Add DEFAULT_SCHEMA_CLASS setting (#5658) * Add test for new setting * Add DefaultSchema utility * Add new setting to docs --- docs/api-guide/settings.md | 6 ++++++ rest_framework/schemas/__init__.py | 2 +- rest_framework/schemas/inspectors.py | 11 +++++++++++ rest_framework/settings.py | 4 ++++ rest_framework/views.py | 4 ++-- tests/test_schemas.py | 17 +++++++++++++++++ 6 files changed, 41 insertions(+), 3 deletions(-) diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 5c9eaa12c..a8abd2a63 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -94,6 +94,12 @@ A content negotiation class, that determines how a renderer is selected for the Default: `'rest_framework.negotiation.DefaultContentNegotiation'` +#### DEFAULT_SCHEMA_CLASS + +A view inspector class that will be used for schema generation. + +Default: `'rest_framework.schemas.AutoSchema'` + --- ## Generic view settings diff --git a/rest_framework/schemas/__init__.py b/rest_framework/schemas/__init__.py index 1af0b9fc5..ba0ec6536 100644 --- a/rest_framework/schemas/__init__.py +++ b/rest_framework/schemas/__init__.py @@ -23,7 +23,7 @@ Other access should target the submodules directly from rest_framework.settings import api_settings from .generators import SchemaGenerator -from .inspectors import AutoSchema, ManualSchema # noqa +from .inspectors import AutoSchema, DefaultSchema, ManualSchema # noqa def get_schema_view( diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py index 008d7c091..b2a5320bd 100644 --- a/rest_framework/schemas/inspectors.py +++ b/rest_framework/schemas/inspectors.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ inspectors.py # Per-endpoint view introspection @@ -456,3 +457,13 @@ class ManualSchema(ViewInspector): ) return self._link + + +class DefaultSchema(object): + """Allows overriding AutoSchema using DEFAULT_SCHEMA_CLASS setting""" + def __get__(self, instance, owner): + inspector_class = api_settings.DEFAULT_SCHEMA_CLASS + assert issubclass(inspector_class, ViewInspector), "DEFAULT_SCHEMA_CLASS must be set to a ViewInspector (usually an AutoSchema) subclass" + inspector = inspector_class() + inspector.view = instance + return inspector diff --git a/rest_framework/settings.py b/rest_framework/settings.py index 478a5229f..db92b7a7b 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -55,6 +55,9 @@ DEFAULTS = { 'DEFAULT_PAGINATION_CLASS': None, 'DEFAULT_FILTER_BACKENDS': (), + # Schema + 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema', + # Throttling 'DEFAULT_THROTTLE_RATES': { 'user': None, @@ -140,6 +143,7 @@ IMPORT_STRINGS = ( 'DEFAULT_VERSIONING_CLASS', 'DEFAULT_PAGINATION_CLASS', 'DEFAULT_FILTER_BACKENDS', + 'DEFAULT_SCHEMA_CLASS', 'EXCEPTION_HANDLER', 'TEST_REQUEST_RENDERER_CLASSES', 'UNAUTHENTICATED_USER', diff --git a/rest_framework/views.py b/rest_framework/views.py index 3140bb9a3..f9ee7fb53 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -18,7 +18,7 @@ from django.views.generic import View from rest_framework import exceptions, status from rest_framework.request import Request from rest_framework.response import Response -from rest_framework.schemas import AutoSchema +from rest_framework.schemas import DefaultSchema from rest_framework.settings import api_settings from rest_framework.utils import formatting @@ -117,7 +117,7 @@ class APIView(View): # Allow dependency injection of other settings to make testing easier. settings = api_settings - schema = AutoSchema() + schema = DefaultSchema() @classmethod def as_view(cls, **initkwargs): diff --git a/tests/test_schemas.py b/tests/test_schemas.py index ba561a959..fa91bac03 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -516,6 +516,11 @@ class Test4605Regression(TestCase): assert prefix == '/' +class CustomViewInspector(AutoSchema): + """A dummy AutoSchema subclass""" + pass + + class TestAutoSchema(TestCase): def test_apiview_schema_descriptor(self): @@ -523,6 +528,18 @@ class TestAutoSchema(TestCase): assert hasattr(view, 'schema') assert isinstance(view.schema, AutoSchema) + def test_set_custom_inspector_class_on_view(self): + class CustomView(APIView): + schema = CustomViewInspector() + + view = CustomView() + assert isinstance(view.schema, CustomViewInspector) + + def test_set_custom_inspector_class_via_settings(self): + with override_settings(REST_FRAMEWORK={'DEFAULT_SCHEMA_CLASS': 'tests.test_schemas.CustomViewInspector'}): + view = APIView() + assert isinstance(view.schema, CustomViewInspector) + def test_get_link_requires_instance(self): descriptor = APIView.schema # Accessed from class with pytest.raises(AssertionError): From 2359d3981b0480fc850a784499a870353a7f2b8c Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 14 Dec 2017 11:39:54 +0100 Subject: [PATCH 005/520] Add docs note re generated BooleanField being `required=False` (#5665) * Note that BooleanField default is required=False Closes #5664 --- docs/api-guide/fields.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 8d61f2cbc..a8a1865a4 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -124,6 +124,8 @@ A boolean representation. When using HTML encoded form input be aware that omitting a value will always be treated as setting a field to `False`, even if it has a `default=True` option specified. This is because HTML checkbox inputs represent the unchecked state by omitting the value, so REST framework treats omission as if it is an empty checkbox input. +Note that default `BooleanField` instances will be generated with a `required=False` option (since Django `models.BooleanField` is always `blank=True`). If you want to change this behaviour explicitly declare the `BooleanField` on the serializer class. + Corresponds to `django.db.models.fields.BooleanField`. **Signature:** `BooleanField()` From d12005cf902e3969b5002593eab83bb63feda840 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Thu, 14 Dec 2017 05:48:03 -0500 Subject: [PATCH 006/520] Add 'dist' build (#5656) --- .travis.yml | 11 ++++++++++- runtests.py | 16 ++++++++++++++-- tox.ini | 10 +++++++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index c5a15140d..f503eb5e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,10 +22,19 @@ matrix: - { python: "3.6", env: DJANGO=2.0 } - { python: "2.7", env: TOXENV=lint } - { python: "2.7", env: TOXENV=docs } - - python: "2.7" + + - python: "3.6" + env: TOXENV=dist + script: + - python setup.py bdist_wheel + - tox --installpkg ./dist/djangorestframework-*.whl + - tox # test sdist + + - python: "3.6" env: TOXENV=readme addons: apt_packages: pandoc + exclude: - { python: "2.7", env: DJANGO=master } - { python: "2.7", env: DJANGO=2.0 } diff --git a/runtests.py b/runtests.py index 5e8460c85..a8f818ad7 100755 --- a/runtests.py +++ b/runtests.py @@ -16,8 +16,6 @@ FLAKE8_ARGS = ['rest_framework', 'tests'] ISORT_ARGS = ['--recursive', '--check-only', '-o' 'uritemplate', '-p', 'tests', 'rest_framework', 'tests'] -sys.path.append(os.path.dirname(__file__)) - def exit_on_failure(ret, message=None): if ret: @@ -84,6 +82,20 @@ if __name__ == "__main__": run_flake8 = False run_isort = False + try: + # Remove the package root directory from `sys.path`, ensuring that rest_framework + # is imported from the installed site packages. Used for testing the distribution + sys.argv.remove('--no-pkgroot') + except ValueError: + pass + else: + sys.path.pop(0) + + # import rest_framework before pytest re-adds the package root directory. + import rest_framework + package_dir = os.path.join(os.getcwd(), 'rest_framework') + assert not rest_framework.__file__.startswith(package_dir) + if len(sys.argv) > 1: pytest_args = sys.argv[1:] first_arg = pytest_args[0] diff --git a/tox.ini b/tox.ini index e2d7aa448..f04e6ba93 100644 --- a/tox.ini +++ b/tox.ini @@ -7,7 +7,7 @@ envlist = {py27,py34,py35,py36}-django111, {py34,py35,py36}-django20, {py35,py36}-djangomaster, - lint,docs,readme, + dist,lint,docs,readme, [travis:env] DJANGO = @@ -18,6 +18,7 @@ DJANGO = [testenv] commands = ./runtests.py --fast {posargs} --coverage -rw +envdir = {toxworkdir}/venvs/{envname} setenv = PYTHONDONTWRITEBYTECODE=1 PYTHONWARNINGS=once @@ -29,6 +30,13 @@ deps = -rrequirements/requirements-testing.txt -rrequirements/requirements-optionals.txt +[testenv:dist] +commands = ./runtests.py --fast {posargs} --no-pkgroot -rw +deps = + django + -rrequirements/requirements-testing.txt + -rrequirements/requirements-optionals.txt + [testenv:lint] basepython = python2.7 commands = ./runtests.py --lintonly From 21a9740156eed349b908057856aef9acd0e620a9 Mon Sep 17 00:00:00 2001 From: Pavlin Gergov Date: Tue, 19 Dec 2017 09:45:33 +0200 Subject: [PATCH 007/520] Fix typo in docstring (#5678) --- rest_framework/throttling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/throttling.py b/rest_framework/throttling.py index 422431566..834ced148 100644 --- a/rest_framework/throttling.py +++ b/rest_framework/throttling.py @@ -54,7 +54,7 @@ class SimpleRateThrottle(BaseThrottle): A simple cache implementation, that only requires `.get_cache_key()` to be overridden. - The rate (requests / seconds) is set by a `throttle` attribute on the View + The rate (requests / seconds) is set by a `rate` attribute on the View class. The attribute is a string of the form 'number_of_requests/period'. Period should be one of: ('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day') From cc25f57f7b88ad22a9b4d29fa53063c85bdca5d9 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Tue, 19 Dec 2017 10:31:20 +0100 Subject: [PATCH 008/520] Add UNAUTHENTICATED_USER = None note (#5679) When removing authentication entirely you cannot import `django.contrib.auth.models.AnonymousUser` Closes #3494 --- docs/api-guide/settings.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index a8abd2a63..caa065389 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -202,6 +202,8 @@ Default: `'version'` #### UNAUTHENTICATED_USER The class that should be used to initialize `request.user` for unauthenticated requests. +(If removing authentication entirely, e.g. by removing `django.contrib.auth` from +`INSTALLED_APPS`, set `UNAUTHENTICATED_USER` to `None`.) Default: `django.contrib.auth.models.AnonymousUser` From 6560f44912de615a0dfc2e6ee0f8ab42767d3a95 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Tue, 19 Dec 2017 12:05:46 +0100 Subject: [PATCH 009/520] =?UTF-8?q?Update=20OPTIONS=20example=20from=20?= =?UTF-8?q?=E2=80=9CDocumenting=20Your=20API=E2=80=9D=20(#5680)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #3489 * Updates example to post-3.0 API, using metadata class * Adds link to metadata docs. --- docs/topics/documenting-your-api.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/topics/documenting-your-api.md b/docs/topics/documenting-your-api.md index 425b02eb8..ae592e636 100644 --- a/docs/topics/documenting-your-api.md +++ b/docs/topics/documenting-your-api.md @@ -254,16 +254,19 @@ REST framework APIs also support programmatically accessible descriptions, using When using the generic views, any `OPTIONS` requests will additionally respond with metadata regarding any `POST` or `PUT` actions available, describing which fields are on the serializer. -You can modify the response behavior to `OPTIONS` requests by overriding the `metadata` view method. For example: +You can modify the response behavior to `OPTIONS` requests by overriding the `options` view method and/or by providing a custom Metadata class. For example: - def metadata(self, request): + def options(self, request, *args, **kwargs): """ Don't include the view description in OPTIONS responses. """ - data = super(ExampleView, self).metadata(request) + meta = self.metadata_class() + data = meta.determine_metadata(request, self) data.pop('description') return data +See [the Metadata docs][metadata-docs] for more details. + --- ## The hypermedia approach @@ -292,3 +295,4 @@ To implement a hypermedia API you'll need to decide on an appropriate media type [image-apiary]: ../img/apiary.png [image-self-describing-api]: ../img/self-describing.png [schemas-examples]: ../api-guide/schemas/#example +[metadata-docs]: ../api-guide/metadata/ From 43c2c91dde3be7128df01b53e114d65d8e23438d Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Tue, 19 Dec 2017 12:05:59 +0100 Subject: [PATCH 010/520] Add note on object permissions for FBVs (#5681) Closes #3269 --- docs/api-guide/permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 3b89e9141..0a3d0ef65 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -192,7 +192,7 @@ If you need to test if a request is a read operation or a write operation, you s --- -**Note**: The instance-level `has_object_permission` method will only be called if the view-level `has_permission` checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call `.check_object_permissions(request, obj)`. If you are using the generic views then this will be handled for you by default. +**Note**: The instance-level `has_object_permission` method will only be called if the view-level `has_permission` checks have already passed. Also note that in order for the instance-level checks to run, the view code should explicitly call `.check_object_permissions(request, obj)`. If you are using the generic views then this will be handled for you by default. (Function-based views will need to check object permissions explicitly, raising `PermissionDenied` on failure.) --- From b3a0b271cd21365d8167c9b581c7f7e7deab85d2 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Tue, 19 Dec 2017 12:06:24 +0100 Subject: [PATCH 011/520] Add example to to_representation docs (#5682) Closes #5425 as per https://github.com/encode/django-rest-framework/issues/5425#issuecomment-341063819 --- docs/api-guide/serializers.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 89196949d..85682838b 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -1007,6 +1007,14 @@ The signatures for these methods are as follows: Takes the object instance that requires serialization, and should return a primitive representation. Typically this means returning a structure of built-in Python datatypes. The exact types that can be handled will depend on the render classes you have configured for your API. +May be overridden in order modify the representation style. For example: + + def to_representation(self, instance): + """Convert `username` to lowercase.""" + ret = super().to_representation(instance) + ret['username'] = ret['username'].lower() + return ret + #### ``.to_internal_value(self, data)`` Takes the unvalidated incoming data as input and should return the validated data that will be made available as `serializer.validated_data`. The return value will also be passed to the `.create()` or `.update()` methods if `.save()` is called on the serializer class. From e87fcbb99d38fab6be973843abe9f43d33cbd399 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Tue, 19 Dec 2017 12:06:41 +0100 Subject: [PATCH 012/520] Add link to Classy DRF in docs (#5683) Closes #5636 as per https://github.com/encode/django-rest-framework/issues/5636#issuecomment-348143281 --- docs/api-guide/views.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/api-guide/views.md b/docs/api-guide/views.md index 2f9f51cf9..017bcad0c 100644 --- a/docs/api-guide/views.md +++ b/docs/api-guide/views.md @@ -42,6 +42,13 @@ For example: usernames = [user.username for user in User.objects.all()] return Response(usernames) +--- + +**Note**: The full methods, attributes on, and relations between Django REST Framework's `APIView`, `GenericAPIView`, various `Mixins`, and `Viewsets` can be initially complex. In addition to the documentation here, the [Classy Django REST Framework][classy-drf] resource provides a browsable reference, with full methods and attributes, for each of Django REST Framework's class-based views. + +--- + + ## API policy attributes The following attributes control the pluggable aspects of API views. @@ -212,3 +219,5 @@ You may pass `None` in order to exclude the view from schema generation. [settings]: settings.md [throttling]: throttling.md [schemas]: schemas.md +[classy-drf]: http://www.cdrf.co + From 4bcbf691cf312a4e41b8c20568cbf6e8cff4bd00 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Tue, 19 Dec 2017 12:06:57 +0100 Subject: [PATCH 013/520] Document ViewSet.action (#5685) Closes #2941 Provides example of adjusting permission by action. --- docs/api-guide/viewsets.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/viewsets.md b/docs/api-guide/viewsets.md index 04ce7357d..27fb1d780 100644 --- a/docs/api-guide/viewsets.md +++ b/docs/api-guide/viewsets.md @@ -70,9 +70,10 @@ There are two main advantages of using a `ViewSet` class over using a `View` cla Both of these come with a trade-off. Using regular views and URL confs is more explicit and gives you more control. ViewSets are helpful if you want to get up and running quickly, or when you have a large API and you want to enforce a consistent URL configuration throughout. -## Marking extra actions for routing -The default routers included with REST framework will provide routes for a standard set of create/retrieve/update/destroy style operations, as shown below: +## ViewSet actions + +The default routers included with REST framework will provide routes for a standard set of create/retrieve/update/destroy style actions, as shown below: class UserViewSet(viewsets.ViewSet): """ @@ -101,6 +102,23 @@ The default routers included with REST framework will provide routes for a stand def destroy(self, request, pk=None): pass +During dispatch the name of the current action is available via the `.action` attribute. +You may inspect `.action` to adjust behaviour based on the current action. + +For example, you could restrict permissions to everything except the `list` action similar to this: + + def get_permissions(self): + """ + Instantiates and returns the list of permissions that this view requires. + """ + if self.action == 'list': + permission_classes = [IsAuthenticated] + else: + permission_classes = [IsAdmin] + return [permission() for permission in permission_classes] + +## Marking extra actions for routing + If you have ad-hoc methods that you need to be routed to, you can mark them as requiring routing using the `@detail_route` or `@list_route` decorators. The `@detail_route` decorator contains `pk` in its URL pattern and is intended for methods which require a single instance. The `@list_route` decorator is intended for methods which operate on a list of objects. From ea0b3b32ad49d9ac34af8caf49c81b9d8f231b83 Mon Sep 17 00:00:00 2001 From: Jimmy Merrild Krag Date: Tue, 19 Dec 2017 15:03:47 +0100 Subject: [PATCH 014/520] Fix typo (#5687) Fixed `include_docs_url` to be `include_docs_urls` --- docs/topics/documenting-your-api.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/topics/documenting-your-api.md b/docs/topics/documenting-your-api.md index ae592e636..b38d301a6 100644 --- a/docs/topics/documenting-your-api.md +++ b/docs/topics/documenting-your-api.md @@ -93,11 +93,11 @@ When using viewsets, you should use the relevant action names as delimiters. ### `documentation` API Reference -The `rest_framework.documentation` module provides three helper functions to help configure the interactive API documentation, `include_docs_url` (usage shown above), `get_docs_view` and `get_schemajs_view`. +The `rest_framework.documentation` module provides three helper functions to help configure the interactive API documentation, `include_docs_urls` (usage shown above), `get_docs_view` and `get_schemajs_view`. - `include_docs_url` employs `get_docs_view` and `get_schemajs_view` to generate the url patterns for the documentation page and JavaScript resource that exposes the API schema respectively. They expose the following options for customisation. (`get_docs_view` and `get_schemajs_view` ultimately call `rest_frameworks.schemas.get_schema_view()`, see the Schemas docs for more options there.) + `include_docs_urls` employs `get_docs_view` and `get_schemajs_view` to generate the url patterns for the documentation page and JavaScript resource that exposes the API schema respectively. They expose the following options for customisation. (`get_docs_view` and `get_schemajs_view` ultimately call `rest_frameworks.schemas.get_schema_view()`, see the Schemas docs for more options there.) -#### `include_docs_url` +#### `include_docs_urls` * `title`: Default `None`. May be used to provide a descriptive title for the schema definition. * `description`: Default `None`. May be used to provide a description for the schema definition. From d38b94fd74572ab7e5d741e1ff056bebe9f4c783 Mon Sep 17 00:00:00 2001 From: Tilmann Becker Date: Wed, 20 Dec 2017 09:10:28 +0100 Subject: [PATCH 015/520] Fix URL pattern parsing in schema generation (#5689) * Fix url parsing in schema generation - Call `str(pattern)` to get non-escaped route - Strip converters from path to comply with uritemplate format. Background: https://github.com/encode/django-rest-framework/issues/5675#issuecomment-352829363 Fixes #5675 --- rest_framework/compat.py | 10 ++++- rest_framework/schemas/generators.py | 10 ++++- tests/test_schemas.py | 55 +++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 5009ffee1..9502c245f 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -32,7 +32,7 @@ except ImportError: def get_regex_pattern(urlpattern): if hasattr(urlpattern, 'pattern'): # Django 2.0 - return urlpattern.pattern.regex.pattern + return str(urlpattern.pattern) else: # Django < 2.0 return urlpattern.regex.pattern @@ -255,6 +255,14 @@ try: except ImportError: InvalidTimeError = Exception +# Django 1.x url routing syntax. Remove when dropping Django 1.11 support. +try: + from django.urls import include, path, re_path # noqa +except ImportError: + from django.conf.urls import include, url # noqa + path = None + re_path = url + # `separators` argument to `json.dumps()` differs between 2.x and 3.x # See: http://bugs.python.org/issue22767 diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 2fe4927d8..6f5c04475 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -3,6 +3,7 @@ generators.py # Top-down schema generation See schemas.__init__.py for package overview. """ +import re import warnings from collections import Counter, OrderedDict from importlib import import_module @@ -135,6 +136,11 @@ def endpoint_ordering(endpoint): return (path, method_priority) +_PATH_PARAMETER_COMPONENT_RE = re.compile( + r'<(?:(?P[^>:]+):)?(?P\w+)>' +) + + class EndpointEnumerator(object): """ A class to determine the available API endpoints that a project exposes. @@ -189,7 +195,9 @@ class EndpointEnumerator(object): Given a URL conf regex, return a URI template string. """ path = simplify_regex(path_regex) - path = path.replace('<', '{').replace('>', '}') + + # Strip Django 2.0 convertors as they are incompatible with uritemplate format + path = re.sub(_PATH_PARAMETER_COMPONENT_RE, r'{\g}', path) return path def should_include_endpoint(self, path, callback): diff --git a/tests/test_schemas.py b/tests/test_schemas.py index fa91bac03..34cb20798 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -9,7 +9,7 @@ from django.test import TestCase, override_settings from rest_framework import ( filters, generics, pagination, permissions, serializers ) -from rest_framework.compat import coreapi, coreschema, get_regex_pattern +from rest_framework.compat import coreapi, coreschema, get_regex_pattern, path from rest_framework.decorators import ( api_view, detail_route, list_route, schema ) @@ -361,6 +361,59 @@ class TestSchemaGenerator(TestCase): assert schema == expected +@unittest.skipUnless(coreapi, 'coreapi is not installed') +@unittest.skipUnless(path, 'needs Django 2') +class TestSchemaGeneratorDjango2(TestCase): + def setUp(self): + self.patterns = [ + path('example/', ExampleListView.as_view()), + path('example//', ExampleDetailView.as_view()), + path('example//sub/', ExampleDetailView.as_view()), + ] + + def test_schema_for_regular_views(self): + """ + Ensure that schema generation works for APIView classes. + """ + generator = SchemaGenerator(title='Example API', patterns=self.patterns) + schema = generator.get_schema() + expected = coreapi.Document( + url='', + title='Example API', + content={ + 'example': { + 'create': coreapi.Link( + url='/example/', + action='post', + fields=[] + ), + 'list': coreapi.Link( + url='/example/', + action='get', + fields=[] + ), + 'read': coreapi.Link( + url='/example/{id}/', + action='get', + fields=[ + coreapi.Field('id', required=True, location='path', schema=coreschema.String()) + ] + ), + 'sub': { + 'list': coreapi.Link( + url='/example/{id}/sub/', + action='get', + fields=[ + coreapi.Field('id', required=True, location='path', schema=coreschema.String()) + ] + ) + } + } + } + ) + assert schema == expected + + @unittest.skipUnless(coreapi, 'coreapi is not installed') class TestSchemaGeneratorNotAtRoot(TestCase): def setUp(self): From cf3929d88dc3d8f311acf4a1179160db4511f658 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 20 Dec 2017 10:04:12 +0100 Subject: [PATCH 016/520] =?UTF-8?q?Add=20example=20using=20`source=3D?= =?UTF-8?q?=E2=80=98*=E2=80=99`=20to=20custom=20field=20docs.=20(#5688)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add example using `source=‘*’` to custom field docs. * Add nested serialiser example Closes #2032 closes #3066 --- docs/api-guide/fields.md | 135 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index a8a1865a4..6bf0ed15e 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -561,6 +561,8 @@ Note that the `WritableField` class that was present in version 2.x no longer ex ## Examples +### A Basic Custom Field + Let's look at an example of serializing a class that represents an RGB color value: class Color(object): @@ -600,7 +602,7 @@ As an example, let's create a field that can be used to represent the class name """ return obj.__class__.__name__ -#### Raising validation errors +### Raising validation errors Our `ColorField` class above currently does not perform any data validation. To indicate invalid data, we should raise a `serializers.ValidationError`, like so: @@ -646,6 +648,137 @@ The `.fail()` method is a shortcut for raising `ValidationError` that takes a me This style keeps your error messages cleaner and more separated from your code, and should be preferred. +### Using `source='*'` + +Here we'll take an example of a _flat_ `DataPoint` model with `x_coordinate` and `y_coordinate` attributes. + + class DataPoint(models.Model): + label = models.CharField(max_length=50) + x_coordinate = models.SmallIntegerField() + y_coordinate = models.SmallIntegerField() + +Using a custom field and `source='*'` we can provide a nested representation of +the coordinate pair: + + class CoordinateField(serializers.Field): + + def to_representation(self, obj): + ret = { + "x": obj.x_coordinate, + "y": obj.y_coordinate + } + return ret + + def to_internal_value(self, data): + ret = { + "x_coordinate": data["x"], + "y_coordinate": data["y"], + } + return ret + + + class DataPointSerializer(serializers.ModelSerializer): + coordinates = CoordinateField(source='*') + + class Meta: + model = DataPoint + fields = ['label', 'coordinates'] + +Note that this example doesn't handle validation. Partly for that reason, in a +real project, the coordinate nesting might be better handled with a nested serialiser +using `source='*'`, with two `IntegerField` instances, each with their own `source` +pointing to the relevant field. + +The key points from the example, though, are: + +* `to_representation` is passed the entire `DataPoint` object and must map from that +to the desired output. + + >>> instance = DataPoint(label='Example', x_coordinate=1, y_coordinate=2) + >>> out_serializer = DataPointSerializer(instance) + >>> out_serializer.data + ReturnDict([('label', 'testing'), ('coordinates', {'x': 1, 'y': 2})]) + +* Unless our field is to be read-only, `to_internal_value` must map back to a dict +suitable for updating our target object. With `source='*'`, the return from +`to_internal_value` will update the root validated data dictionary, rather than a single key. + + >>> data = { + ... "label": "Second Example", + ... "coordinates": { + ... "x": 3, + ... "y": 4, + ... } + ... } + >>> in_serializer = DataPointSerializer(data=data) + >>> in_serializer.is_valid() + True + >>> in_serializer.validated_data + OrderedDict([('label', 'Second Example'), + ('y_coordinate', 4), + ('x_coordinate', 3)]) + +For completeness lets do the same thing again but with the nested serialiser +approach suggested above: + + class NestedCoordinateSerializer(serializers.Serializer): + x = serializers.IntegerField(source='x_coordinate') + y = serializers.IntegerField(source='y_coordinate') + + + class DataPointSerializer(serializers.ModelSerializer): + coordinates = NestedCoordinateSerializer(source='*') + + class Meta: + model = DataPoint + fields = ['label', 'coordinates'] + +Here the mapping between the target and source attribute pairs (`x` and +`x_coordinate`, `y` and `y_coordinate`) is handled in the `IntegerField` +declarations. It's our `NestedCoordinateSerializer` that takes `source='*'`. + +Our new `DataPointSerializer` exhibits the same behaviour as the custom field +approach. + +Serialising: + + >>> out_serializer = DataPointSerializer(instance) + >>> out_serializer.data + ReturnDict([('label', 'testing'), + ('coordinates', OrderedDict([('x', 1), ('y', 2)]))]) + +Deserialising: + + >>> in_serializer = DataPointSerializer(data=data) + >>> in_serializer.is_valid() + True + >>> in_serializer.validated_data + OrderedDict([('label', 'still testing'), + ('x_coordinate', 3), + ('y_coordinate', 4)]) + +But we also get the built-in validation for free: + + >>> invalid_data = { + ... "label": "still testing", + ... "coordinates": { + ... "x": 'a', + ... "y": 'b', + ... } + ... } + >>> invalid_serializer = DataPointSerializer(data=invalid_data) + >>> invalid_serializer.is_valid() + False + >>> invalid_serializer.errors + ReturnDict([('coordinates', + {'x': ['A valid integer is required.'], + 'y': ['A valid integer is required.']})]) + +For this reason, the nested serialiser approach would be the first to try. You +would use the custom field approach when the nested serialiser becomes infeasible +or overly complex. + + # Third party packages The following third party packages are also available. From 6de12e574e4ec059664c0bc14f8ba1a1b1de4087 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=20V=C3=AEjdea?= Date: Wed, 20 Dec 2017 13:17:54 +0100 Subject: [PATCH 017/520] Fix format_suffix_patterns behavior with Django 2 path() routes (#5691) * Add failing test for #5672 * Add get_original_route to complement get_regex_pattern * [WIP] Fix path handling * needs more tests * maybe needs some refactoring * Add django 2 variant for all tests and fix trailing slash bug * Add more combinations to mixed path test --- rest_framework/compat.py | 32 ++++- rest_framework/schemas/generators.py | 4 +- rest_framework/urlpatterns.py | 68 +++++++++- tests/test_urlpatterns.py | 186 ++++++++++++++++++++++----- 4 files changed, 249 insertions(+), 41 deletions(-) diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 9502c245f..9870fe77e 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -29,7 +29,11 @@ except ImportError: ) -def get_regex_pattern(urlpattern): +def get_original_route(urlpattern): + """ + Get the original route/regex that was typed in by the user into the path(), re_path() or url() directive. This + is in contrast with get_regex_pattern below, which for RoutePattern returns the raw regex generated from the path(). + """ if hasattr(urlpattern, 'pattern'): # Django 2.0 return str(urlpattern.pattern) @@ -38,6 +42,29 @@ def get_regex_pattern(urlpattern): return urlpattern.regex.pattern +def get_regex_pattern(urlpattern): + """ + Get the raw regex out of the urlpattern's RegexPattern or RoutePattern. This is always a regular expression, + unlike get_original_route above. + """ + if hasattr(urlpattern, 'pattern'): + # Django 2.0 + return urlpattern.pattern.regex.pattern + else: + # Django < 2.0 + return urlpattern.regex.pattern + + +def is_route_pattern(urlpattern): + if hasattr(urlpattern, 'pattern'): + # Django 2.0 + from django.urls.resolvers import RoutePattern + return isinstance(urlpattern.pattern, RoutePattern) + else: + # Django < 2.0 + return False + + def make_url_resolver(regex, urlpatterns): try: # Django 2.0 @@ -257,10 +284,11 @@ except ImportError: # Django 1.x url routing syntax. Remove when dropping Django 1.11 support. try: - from django.urls import include, path, re_path # noqa + from django.urls import include, path, re_path, register_converter # noqa except ImportError: from django.conf.urls import include, url # noqa path = None + register_converter = None re_path = url diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 6f5c04475..10af6ee04 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -16,7 +16,7 @@ from django.utils import six from rest_framework import exceptions from rest_framework.compat import ( - URLPattern, URLResolver, coreapi, coreschema, get_regex_pattern + URLPattern, URLResolver, coreapi, coreschema, get_original_route ) from rest_framework.request import clone_request from rest_framework.settings import api_settings @@ -170,7 +170,7 @@ class EndpointEnumerator(object): api_endpoints = [] for pattern in patterns: - path_regex = prefix + get_regex_pattern(pattern) + path_regex = prefix + get_original_route(pattern) if isinstance(pattern, URLPattern): path = self.get_path_from_regex(path_regex) callback = pattern.callback diff --git a/rest_framework/urlpatterns.py b/rest_framework/urlpatterns.py index 4aabc7f14..ab3a74978 100644 --- a/rest_framework/urlpatterns.py +++ b/rest_framework/urlpatterns.py @@ -2,11 +2,39 @@ from __future__ import unicode_literals from django.conf.urls import include, url -from rest_framework.compat import URLResolver, get_regex_pattern +from rest_framework.compat import ( + URLResolver, get_regex_pattern, is_route_pattern, path, register_converter +) from rest_framework.settings import api_settings -def apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required): +def _get_format_path_converter(suffix_kwarg, allowed): + if allowed: + if len(allowed) == 1: + allowed_pattern = allowed[0] + else: + allowed_pattern = '(?:%s)' % '|'.join(allowed) + suffix_pattern = r"\.%s/?" % allowed_pattern + else: + suffix_pattern = r"\.[a-z0-9]+/?" + + class FormatSuffixConverter: + regex = suffix_pattern + + def to_python(self, value): + return value.strip('./') + + def to_url(self, value): + return '.' + value + '/' + + converter_name = 'drf_format_suffix' + if allowed: + converter_name += '_' + '_'.join(allowed) + + return converter_name, FormatSuffixConverter + + +def apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required, suffix_route=None): ret = [] for urlpattern in urlpatterns: if isinstance(urlpattern, URLResolver): @@ -18,8 +46,18 @@ def apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required): # Add in the included patterns, after applying the suffixes patterns = apply_suffix_patterns(urlpattern.url_patterns, suffix_pattern, - suffix_required) - ret.append(url(regex, include((patterns, app_name), namespace), kwargs)) + suffix_required, + suffix_route) + + # if the original pattern was a RoutePattern we need to preserve it + if is_route_pattern(urlpattern): + assert path is not None + route = str(urlpattern.pattern) + new_pattern = path(route, include((patterns, app_name), namespace), kwargs) + else: + new_pattern = url(regex, include((patterns, app_name), namespace), kwargs) + + ret.append(new_pattern) else: # Regular URL pattern regex = get_regex_pattern(urlpattern).rstrip('$').rstrip('/') + suffix_pattern @@ -29,7 +67,17 @@ def apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required): # Add in both the existing and the new urlpattern if not suffix_required: ret.append(urlpattern) - ret.append(url(regex, view, kwargs, name)) + + # if the original pattern was a RoutePattern we need to preserve it + if is_route_pattern(urlpattern): + assert path is not None + assert suffix_route is not None + route = str(urlpattern.pattern).rstrip('$').rstrip('/') + suffix_route + new_pattern = path(route, view, kwargs, name) + else: + new_pattern = url(regex, view, kwargs, name) + + ret.append(new_pattern) return ret @@ -60,4 +108,12 @@ def format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None): else: suffix_pattern = r'\.(?P<%s>[a-z0-9]+)/?$' % suffix_kwarg - return apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required) + if path and register_converter: + converter_name, suffix_converter = _get_format_path_converter(suffix_kwarg, allowed) + register_converter(suffix_converter, converter_name) + + suffix_route = '<%s:%s>' % (converter_name, suffix_kwarg) + else: + suffix_route = None + + return apply_suffix_patterns(urlpatterns, suffix_pattern, suffix_required, suffix_route) diff --git a/tests/test_urlpatterns.py b/tests/test_urlpatterns.py index e84465141..59ba395d2 100644 --- a/tests/test_urlpatterns.py +++ b/tests/test_urlpatterns.py @@ -1,12 +1,13 @@ from __future__ import unicode_literals +import unittest from collections import namedtuple from django.conf.urls import include, url from django.test import TestCase from django.urls import Resolver404 -from rest_framework.compat import make_url_resolver +from rest_framework.compat import make_url_resolver, path, re_path from rest_framework.test import APIRequestFactory from rest_framework.urlpatterns import format_suffix_patterns @@ -23,41 +24,29 @@ class FormatSuffixTests(TestCase): Tests `format_suffix_patterns` against different URLPatterns to ensure the URLs still resolve properly, including any captured parameters. """ - def _resolve_urlpatterns(self, urlpatterns, test_paths): + def _resolve_urlpatterns(self, urlpatterns, test_paths, allowed=None): factory = APIRequestFactory() try: - urlpatterns = format_suffix_patterns(urlpatterns) + urlpatterns = format_suffix_patterns(urlpatterns, allowed=allowed) except Exception: self.fail("Failed to apply `format_suffix_patterns` on the supplied urlpatterns") resolver = make_url_resolver(r'^/', urlpatterns) for test_path in test_paths: - request = factory.get(test_path.path) try: - callback, callback_args, callback_kwargs = resolver.resolve(request.path_info) - except Exception: - self.fail("Failed to resolve URL: %s" % request.path_info) - assert callback_args == test_path.args - assert callback_kwargs == test_path.kwargs + test_path, expected_resolved = test_path + except (TypeError, ValueError): + expected_resolved = True - def test_trailing_slash(self): - factory = APIRequestFactory() - urlpatterns = format_suffix_patterns([ - url(r'^test/$', dummy_view), - ]) - resolver = make_url_resolver(r'^/', urlpatterns) - - test_paths = [ - (URLTestPath('/test.api', (), {'format': 'api'}), True), - (URLTestPath('/test/.api', (), {'format': 'api'}), False), - (URLTestPath('/test.api/', (), {'format': 'api'}), True), - ] - - for test_path, expected_resolved in test_paths: request = factory.get(test_path.path) try: callback, callback_args, callback_kwargs = resolver.resolve(request.path_info) except Resolver404: callback, callback_args, callback_kwargs = (None, None, None) + if expected_resolved: + raise + except Exception: + self.fail("Failed to resolve URL: %s" % request.path_info) + if not expected_resolved: assert callback is None continue @@ -65,10 +54,28 @@ class FormatSuffixTests(TestCase): assert callback_args == test_path.args assert callback_kwargs == test_path.kwargs - def test_format_suffix(self): - urlpatterns = [ - url(r'^test$', dummy_view), + def _test_trailing_slash(self, urlpatterns): + test_paths = [ + (URLTestPath('/test.api', (), {'format': 'api'}), True), + (URLTestPath('/test/.api', (), {'format': 'api'}), False), + (URLTestPath('/test.api/', (), {'format': 'api'}), True), ] + self._resolve_urlpatterns(urlpatterns, test_paths) + + def test_trailing_slash(self): + urlpatterns = [ + url(r'^test/$', dummy_view), + ] + self._test_trailing_slash(urlpatterns) + + @unittest.skipUnless(path, 'needs Django 2') + def test_trailing_slash_django2(self): + urlpatterns = [ + path('test/', dummy_view), + ] + self._test_trailing_slash(urlpatterns) + + def _test_format_suffix(self, urlpatterns): test_paths = [ URLTestPath('/test', (), {}), URLTestPath('/test.api', (), {'format': 'api'}), @@ -76,10 +83,36 @@ class FormatSuffixTests(TestCase): ] self._resolve_urlpatterns(urlpatterns, test_paths) - def test_default_args(self): + def test_format_suffix(self): urlpatterns = [ - url(r'^test$', dummy_view, {'foo': 'bar'}), + url(r'^test$', dummy_view), ] + self._test_format_suffix(urlpatterns) + + @unittest.skipUnless(path, 'needs Django 2') + def test_format_suffix_django2(self): + urlpatterns = [ + path('test', dummy_view), + ] + self._test_format_suffix(urlpatterns) + + @unittest.skipUnless(path, 'needs Django 2') + def test_format_suffix_django2_args(self): + urlpatterns = [ + path('convtest/', dummy_view), + re_path(r'^retest/(?P[0-9]+)$', dummy_view), + ] + test_paths = [ + URLTestPath('/convtest/42', (), {'pk': 42}), + URLTestPath('/convtest/42.api', (), {'pk': 42, 'format': 'api'}), + URLTestPath('/convtest/42.asdf', (), {'pk': 42, 'format': 'asdf'}), + URLTestPath('/retest/42', (), {'pk': '42'}), + URLTestPath('/retest/42.api', (), {'pk': '42', 'format': 'api'}), + URLTestPath('/retest/42.asdf', (), {'pk': '42', 'format': 'asdf'}), + ] + self._resolve_urlpatterns(urlpatterns, test_paths) + + def _test_default_args(self, urlpatterns): test_paths = [ URLTestPath('/test', (), {'foo': 'bar', }), URLTestPath('/test.api', (), {'foo': 'bar', 'format': 'api'}), @@ -87,6 +120,27 @@ class FormatSuffixTests(TestCase): ] self._resolve_urlpatterns(urlpatterns, test_paths) + def test_default_args(self): + urlpatterns = [ + url(r'^test$', dummy_view, {'foo': 'bar'}), + ] + self._test_default_args(urlpatterns) + + @unittest.skipUnless(path, 'needs Django 2') + def test_default_args_django2(self): + urlpatterns = [ + path('test', dummy_view, {'foo': 'bar'}), + ] + self._test_default_args(urlpatterns) + + def _test_included_urls(self, urlpatterns): + test_paths = [ + URLTestPath('/test/path', (), {'foo': 'bar', }), + URLTestPath('/test/path.api', (), {'foo': 'bar', 'format': 'api'}), + URLTestPath('/test/path.asdf', (), {'foo': 'bar', 'format': 'asdf'}), + ] + self._resolve_urlpatterns(urlpatterns, test_paths) + def test_included_urls(self): nested_patterns = [ url(r'^path$', dummy_view) @@ -94,9 +148,79 @@ class FormatSuffixTests(TestCase): urlpatterns = [ url(r'^test/', include(nested_patterns), {'foo': 'bar'}), ] + self._test_included_urls(urlpatterns) + + @unittest.skipUnless(path, 'needs Django 2') + def test_included_urls_django2(self): + nested_patterns = [ + path('path', dummy_view) + ] + urlpatterns = [ + path('test/', include(nested_patterns), {'foo': 'bar'}), + ] + self._test_included_urls(urlpatterns) + + @unittest.skipUnless(path, 'needs Django 2') + def test_included_urls_django2_mixed(self): + nested_patterns = [ + path('path', dummy_view) + ] + urlpatterns = [ + url('^test/', include(nested_patterns), {'foo': 'bar'}), + ] + self._test_included_urls(urlpatterns) + + @unittest.skipUnless(path, 'needs Django 2') + def test_included_urls_django2_mixed_args(self): + nested_patterns = [ + path('path/', dummy_view), + url('^url/(?P[0-9]+)$', dummy_view) + ] + urlpatterns = [ + url('^purl/(?P[0-9]+)/', include(nested_patterns), {'foo': 'bar'}), + path('ppath//', include(nested_patterns), {'foo': 'bar'}), + ] test_paths = [ - URLTestPath('/test/path', (), {'foo': 'bar', }), - URLTestPath('/test/path.api', (), {'foo': 'bar', 'format': 'api'}), - URLTestPath('/test/path.asdf', (), {'foo': 'bar', 'format': 'asdf'}), + # parent url() nesting child path() + URLTestPath('/purl/87/path/42', (), {'parent': '87', 'child': 42, 'foo': 'bar', }), + URLTestPath('/purl/87/path/42.api', (), {'parent': '87', 'child': 42, 'foo': 'bar', 'format': 'api'}), + URLTestPath('/purl/87/path/42.asdf', (), {'parent': '87', 'child': 42, 'foo': 'bar', 'format': 'asdf'}), + + # parent path() nesting child url() + URLTestPath('/ppath/87/url/42', (), {'parent': 87, 'child': '42', 'foo': 'bar', }), + URLTestPath('/ppath/87/url/42.api', (), {'parent': 87, 'child': '42', 'foo': 'bar', 'format': 'api'}), + URLTestPath('/ppath/87/url/42.asdf', (), {'parent': 87, 'child': '42', 'foo': 'bar', 'format': 'asdf'}), + + # parent path() nesting child path() + URLTestPath('/ppath/87/path/42', (), {'parent': 87, 'child': 42, 'foo': 'bar', }), + URLTestPath('/ppath/87/path/42.api', (), {'parent': 87, 'child': 42, 'foo': 'bar', 'format': 'api'}), + URLTestPath('/ppath/87/path/42.asdf', (), {'parent': 87, 'child': 42, 'foo': 'bar', 'format': 'asdf'}), + + # parent url() nesting child url() + URLTestPath('/purl/87/url/42', (), {'parent': '87', 'child': '42', 'foo': 'bar', }), + URLTestPath('/purl/87/url/42.api', (), {'parent': '87', 'child': '42', 'foo': 'bar', 'format': 'api'}), + URLTestPath('/purl/87/url/42.asdf', (), {'parent': '87', 'child': '42', 'foo': 'bar', 'format': 'asdf'}), ] self._resolve_urlpatterns(urlpatterns, test_paths) + + def _test_allowed_formats(self, urlpatterns): + allowed_formats = ['good', 'ugly'] + test_paths = [ + (URLTestPath('/test.good/', (), {'format': 'good'}), True), + (URLTestPath('/test.bad', (), {}), False), + (URLTestPath('/test.ugly', (), {'format': 'ugly'}), True), + ] + self._resolve_urlpatterns(urlpatterns, test_paths, allowed=allowed_formats) + + def test_allowed_formats(self): + urlpatterns = [ + url('^test$', dummy_view), + ] + self._test_allowed_formats(urlpatterns) + + @unittest.skipUnless(path, 'needs Django 2') + def test_allowed_formats_django2(self): + urlpatterns = [ + path('test', dummy_view), + ] + self._test_allowed_formats(urlpatterns) From a81e60ff390b9b6788b2cac24a01ee4dd2dcffd2 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Wed, 20 Dec 2017 15:28:31 +0100 Subject: [PATCH 018/520] Version 3.7.4 Release (#5650) * Update version for 3.7.4 Release * Add release notes to 01587b9eb17bf68c7 * Django 2.0 is now final. * Add trove classifer for Django 2.0 * Finalise release notes for v3.7.4 * Set release date: December 20, 2017 * Update Transifex * Add release note for #5691 * Move Issue links to bottom --- README.md | 2 +- docs/topics/release-notes.md | 105 +++++++++++++++++- rest_framework/__init__.py | 2 +- .../locale/nb/LC_MESSAGES/django.mo | Bin 9803 -> 10358 bytes .../locale/nb/LC_MESSAGES/django.po | 33 +++--- .../locale/pt_BR/LC_MESSAGES/django.mo | Bin 10238 -> 10845 bytes .../locale/pt_BR/LC_MESSAGES/django.po | 29 ++--- setup.py | 1 + 8 files changed, 134 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index c19105bc7..92aad7499 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ There is a live example API for testing purposes, [available here][sandbox]. # Requirements * Python (2.7, 3.4, 3.5, 3.6) -* Django (1.10, 1.11, 2.0rc1) +* Django (1.10, 1.11, 2.0) # Installation diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 2f2cdf1a1..e6c9f78f2 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -42,9 +42,9 @@ You can determine your currently installed version using `pip freeze`: ### 3.7.4 -**Date**: UNRELEASED +**Date**: [20th December 2017][3.7.4-milestone] -* Extract method for `manual_fields` processing [#5633][gh5633] +* Schema: Extract method for `manual_fields` processing [#5633][gh5633] Allows for easier customisation of `manual_fields` processing, for example to provide per-method manual fields. `AutoSchema` adds `get_manual_fields`, @@ -54,10 +54,51 @@ You can determine your currently installed version using `pip freeze`: Note: `AutoSchema.__init__` now ensures `manual_fields` is a list. Previously may have been stored internally as `None`. - - -[gh5633]: https://github.com/encode/django-rest-framework/issues/5633 - +* Remove ulrparse compatability shim; use six instead [#5579][gh5579] +* Drop compat wrapper for `TimeDelta.total_seconds()` [#5577][gh5577] +* Clean up all whitespace throughout project [#5578][gh5578] +* Compat cleanup [#5581][gh5581] +* Add pygments CSS block in browsable API views [#5584][gh5584] [#5587][gh5587] +* Remove `set_rollback()` from compat [#5591][gh5591] +* Fix request body/POST access [#5590][gh5590] +* Rename test to reference correct issue [#5610][gh5610] +* Documentation Fixes [#5611][gh5611] [#5612][gh5612] +* Remove references to unsupported Django versions in docs and code [#5602][gh5602] +* Test Serializer exclude for declared fields [#5599][gh5599] +* Fixed schema generation for filter backends [#5613][gh5613] +* Minor cleanup for ModelSerializer tests [#5598][gh5598] +* Reimplement request attribute access w/ `__getattr__` [#5617][gh5617] +* Fixed SchemaJSRenderer renders invalid Javascript [#5607][gh5607] +* Make Django 2.0 support official/explicit [#5619][gh5619] +* Perform type check on passed request argument [#5618][gh5618] +* Fix AttributeError hiding on request authenticators [#5600][gh5600] +* Update test requirements [#5626][gh5626] +* Docs: `Serializer._declared_fields` enable modifying fields on a serializer [#5629][gh5629] +* Fix packaging [#5624][gh5624] +* Fix readme rendering for PyPI, add readme build to CI [#5625][gh5625] +* Update tutorial [#5622][gh5622] +* Non-required fields with `allow_null=True` should not imply a default value [#5639][gh5639] +* Docs: Add `allow_null` serialization output note [#5641][gh5641] +* Update to use the Django 2.0 release in tox.ini [#5645][gh5645] +* Fix `Serializer.data` for Browsable API rendering when provided invalid `data` [#5646][gh5646] +* Docs: Note AutoSchema limitations on bare APIView [#5649][gh5649] +* Add `.basename` and `.reverse_action()` to ViewSet [#5648][gh5648] +* Docs: Fix typos in serializers documentation [#5652][gh5652] +* Fix `override_settings` compat [#5668][gh5668] +* Add DEFAULT_SCHEMA_CLASS setting [#5658][gh5658] +* Add docs note re generated BooleanField being `required=False` [#5665][gh5665] +* Add 'dist' build [#5656][gh5656] +* Fix typo in docstring [#5678][gh5678] +* Docs: Add `UNAUTHENTICATED_USER = None` note [#5679][gh5679] +* Update OPTIONS example from “Documenting Your API” [#5680][gh5680] +* Docs: Add note on object permissions for FBVs [#5681][gh5681] +* Docs: Add example to `to_representation` docs [#5682][gh5682] +* Add link to Classy DRF in docs [#5683][gh5683] +* Document ViewSet.action [#5685][gh5685] +* Fix schema docs typo [#5687][gh5687] +* Fix URL pattern parsing in schema generation [#5689][gh5689] +* Add example using `source=‘*’` to custom field docs. [#5688][gh5688] +* Fix format_suffix_patterns behavior with Django 2 path() routes [#5691][gh5691] ### 3.7.3 @@ -882,6 +923,7 @@ For older release notes, [please see the version 2.x documentation][old-release- [3.7.1-milestone]: https://github.com/encode/django-rest-framework/milestone/58?closed=1 [3.7.2-milestone]: https://github.com/encode/django-rest-framework/milestone/59?closed=1 [3.7.3-milestone]: https://github.com/encode/django-rest-framework/milestone/60?closed=1 +[3.7.4-milestone]: https://github.com/encode/django-rest-framework/milestone/62?closed=1 @@ -1640,3 +1682,54 @@ For older release notes, [please see the version 2.x documentation][old-release- [gh5567]: https://github.com/encode/django-rest-framework/issues/5567 + + +[gh5691]: https://github.com/encode/django-rest-framework/issues/5691 +[gh5688]: https://github.com/encode/django-rest-framework/issues/5688 +[gh5689]: https://github.com/encode/django-rest-framework/issues/5689 +[gh5687]: https://github.com/encode/django-rest-framework/issues/5687 +[gh5685]: https://github.com/encode/django-rest-framework/issues/5685 +[gh5683]: https://github.com/encode/django-rest-framework/issues/5683 +[gh5682]: https://github.com/encode/django-rest-framework/issues/5682 +[gh5681]: https://github.com/encode/django-rest-framework/issues/5681 +[gh5680]: https://github.com/encode/django-rest-framework/issues/5680 +[gh5679]: https://github.com/encode/django-rest-framework/issues/5679 +[gh5678]: https://github.com/encode/django-rest-framework/issues/5678 +[gh5656]: https://github.com/encode/django-rest-framework/issues/5656 +[gh5665]: https://github.com/encode/django-rest-framework/issues/5665 +[gh5658]: https://github.com/encode/django-rest-framework/issues/5658 +[gh5668]: https://github.com/encode/django-rest-framework/issues/5668 +[gh5652]: https://github.com/encode/django-rest-framework/issues/5652 +[gh5648]: https://github.com/encode/django-rest-framework/issues/5648 +[gh5649]: https://github.com/encode/django-rest-framework/issues/5649 +[gh5646]: https://github.com/encode/django-rest-framework/issues/5646 +[gh5645]: https://github.com/encode/django-rest-framework/issues/5645 +[gh5641]: https://github.com/encode/django-rest-framework/issues/5641 +[gh5639]: https://github.com/encode/django-rest-framework/issues/5639 +[gh5622]: https://github.com/encode/django-rest-framework/issues/5622 +[gh5625]: https://github.com/encode/django-rest-framework/issues/5625 +[gh5624]: https://github.com/encode/django-rest-framework/issues/5624 +[gh5629]: https://github.com/encode/django-rest-framework/issues/5629 +[gh5626]: https://github.com/encode/django-rest-framework/issues/5626 +[gh5600]: https://github.com/encode/django-rest-framework/issues/5600 +[gh5618]: https://github.com/encode/django-rest-framework/issues/5618 +[gh5619]: https://github.com/encode/django-rest-framework/issues/5619 +[gh5607]: https://github.com/encode/django-rest-framework/issues/5607 +[gh5617]: https://github.com/encode/django-rest-framework/issues/5617 +[gh5598]: https://github.com/encode/django-rest-framework/issues/5598 +[gh5613]: https://github.com/encode/django-rest-framework/issues/5613 +[gh5599]: https://github.com/encode/django-rest-framework/issues/5599 +[gh5602]: https://github.com/encode/django-rest-framework/issues/5602 +[gh5612]: https://github.com/encode/django-rest-framework/issues/5612 +[gh5611]: https://github.com/encode/django-rest-framework/issues/5611 +[gh5610]: https://github.com/encode/django-rest-framework/issues/5610 +[gh5590]: https://github.com/encode/django-rest-framework/issues/5590 +[gh5591]: https://github.com/encode/django-rest-framework/issues/5591 +[gh5587]: https://github.com/encode/django-rest-framework/issues/5587 +[gh5584]: https://github.com/encode/django-rest-framework/issues/5584 +[gh5581]: https://github.com/encode/django-rest-framework/issues/5581 +[gh5578]: https://github.com/encode/django-rest-framework/issues/5578 +[gh5577]: https://github.com/encode/django-rest-framework/issues/5577 +[gh5579]: https://github.com/encode/django-rest-framework/issues/5579 +[gh5633]: https://github.com/encode/django-rest-framework/issues/5633 + diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index e1e55c612..8c3054407 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -8,7 +8,7 @@ ______ _____ _____ _____ __ """ __title__ = 'Django REST framework' -__version__ = '3.7.3' +__version__ = '3.7.4' __author__ = 'Tom Christie' __license__ = 'BSD 2-Clause' __copyright__ = 'Copyright 2011-2017 Tom Christie' diff --git a/rest_framework/locale/nb/LC_MESSAGES/django.mo b/rest_framework/locale/nb/LC_MESSAGES/django.mo index 18cc4bc8d98712a02b5ee5832dafdd3b7001880f..536cb327207b74f233a113299d3f24ee6262205f 100644 GIT binary patch delta 2662 zcmYk-Yitx%7{>9_ZRwVBE0@+5X*&h0P-qL30xj3JT#8-G#TKMOaqLdprR{FBvrq|! z6%9rplE{RpsKFaiKlrJLO439n$OlCdyu@fi#F(gw5Mlx*NYwu`yQn9;^E+qQJ#*f3 z-kp9Hy15~Fc~aIfL+d7{5ur?D4&vk4TxhT67*mF?p@nC$9Dl+R%pGk^A*nk30rXdSYzt3 z1NHyMFoYLy22LGk%p_cnTHr?1{itu!n4@$w;c2YJ-;sZ2=J?b~7osv=j(SiS7vl+B zf!|^i7EUmx3b!G*%wg2$j^j-H619`Ju>wo-cn;4u>*&nIEvN~e!FBjPF2jt8sR>u$ zRK~68aRimgW2nqtMz+*^m>%Cw|9=tbXL5fTY9|`F=;+!osR>;=_u&yNz|&~q1)Pl6 zFbe|=I29AbYMg|WfoV+Jf_&7pq2}p9mC-)D3lF5nub>isb28_zv;LYJ%Aj~k>Vx&D z@g`I;#c&}WMxF5|>G3U80`u}yp9`VIxEHm+gXr%Fj$(WpwV(j2n~kFj*#CKSYPqo$ zdr+Bvj79iq+8S78IdvOkag!)}yMHNdn7iCnQwiQ=19>SG4f?D`rs4X5%Hq$W=wNo{y zM7nV~K93}jG~dus)t6ev@XIi*xD-24XY>+kC(ffL_zn4Kn_~901}jkC@5D9uEH>a* zsGng0tDtMjQRB6!`8MM;o^STj(HCCuZy56(>I;8h5R3SYah#?MS*xi-HpOg3{c47g zIy5Jc(=(@#dNyC6itb0$f`36JbOUviWvn8|^UZ8JnxF=3 zXMYCu`AptUdT=Q+x2Z!VupMhLiHq<(T!2?m2~4LVlNOzobo2!qRTNKQ6OQ00%pgte zL=b1;1XPXGVJCKDHl9Q3(R_}2z|W|f7)9ZfU><4#)tH0fne4wh1Kh|!6<|G~?Hfbf zX(~i*nI5X9N$)h(fSNMp#QdiEX(5=_Zx3<3pHMP7!U{qQZP58|q@$)4ul9SXzgXMo zKSHb}bZ#m>H5C!>5&v(*8e}*9wu);T(M9Mj*i5LcPvO77l&qR|QEj`07D|)dh9xw??kKZv3Wq4sD+Q z+g0_dsrViwLK@K45fl7g>LsGC_h)dbcPV%-$7+l9IZ@N#wT>(D-py$UHpLw~;e>~; z=IqSQw0oT4(1f9ks`gDGYtT;gR#~fJj%!6@32VSkboE+xbdR;$iMx?l)QZ{zjyq^~ zIo@-5`QF*Qs>~K=&+zrUu^BF`+{}$Q7ZzpfP%G?04K#r*_y%sk%h-iw`DS%E zg8Z|ST=cs$xEkkCI~OQ0TZ5IDz^zz^Dcr2BK1-t=uOZJ^bD>!Y_MrNEQ7f24t;qF# z$G?9Gwc-U-NJ6({p0C7e`W+a-hta_&uozEcDn#R58tkr}$2;*eBuw@z>cxMfUXV{G z3s+(kYyEyVCg}H}LispqqBE%9{owciMCC?=(VMZMnEh7_C;S_)p;kVR`r&WrV8OD? z#1g0^+KYGK>sXJoxC;Zz&2Gg9e5ZV$!v^lZjdKCB?@=K-7iIqyqj{#e3jad&W2CfJ z+=UJfV>v#CRroS$#h+p~E?_Sc)C!*UeII-1U%^hSD$9g)3>C5iSb;}SJ8=rNfYc=#9W?$$ z&9I%fD?6V?^3mSI^*Dpt@&MbQ9f+e|umc0IwH? zLq*{u(Y<`?L4}t`y!e9+P*a6mbULZ%Q&I_1@1yd$dRy3zT5+7J!bW&W%Y40ZukQv_ z2sj|UkomVgydWxLo zsyJ&$b;zh_w-lOgs&-ICU(f&JE8aI2eQMXs5RD}D9;y;arJt&hsN_?XCyIF+RV6!v z_aDt5?Hzt!r>x5M3|6BVEu$`>D!E#zN;Xbh@2dbWn|ERd^?u!;I8+@_N~DDQO87_j zM9xt9=bVWww=uRnJykdqa0`m+(#fK{Kze8Kn?W}xGVNZBB-|y@E$&$Ksc@p+Nwl^# zwYUq>Xvx6%, 2017 # Petter Kjelkenes , 2015 # Thomas Bruun , 2017 msgid "" @@ -10,8 +11,8 @@ msgstr "" "Project-Id-Version: Django REST framework\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-07-12 16:13+0100\n" -"PO-Revision-Date: 2017-11-01 09:58+0000\n" -"Last-Translator: Thomas Bruun \n" +"PO-Revision-Date: 2017-11-28 15:25+0000\n" +"Last-Translator: Håken Lid \n" "Language-Team: Norwegian Bokmål (http://www.transifex.com/django-rest-framework-1/django-rest-framework/language/nb/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -25,7 +26,7 @@ msgstr "Ugyldig basic header. Ingen legitimasjon gitt." #: authentication.py:76 msgid "Invalid basic header. Credentials string should not contain spaces." -msgstr "Ugylid basic header. Legitimasjonsstreng bør ikke inneholde mellomrom." +msgstr "Ugyldig basic header. Legitimasjonsstreng bør ikke inneholde mellomrom." #: authentication.py:82 msgid "Invalid basic header. Credentials not correctly base64 encoded." @@ -58,35 +59,35 @@ msgstr "Ugyldig token." #: authtoken/apps.py:7 msgid "Auth Token" -msgstr "" +msgstr "Auth Token" #: authtoken/models.py:15 msgid "Key" -msgstr "" +msgstr "Nøkkel" #: authtoken/models.py:18 msgid "User" -msgstr "" +msgstr "Bruker" #: authtoken/models.py:20 msgid "Created" -msgstr "" +msgstr "Opprettet" #: authtoken/models.py:29 msgid "Token" -msgstr "" +msgstr "Token" #: authtoken/models.py:30 msgid "Tokens" -msgstr "" +msgstr "Tokener" #: authtoken/serializers.py:8 msgid "Username" -msgstr "" +msgstr "Brukernavn" #: authtoken/serializers.py:9 msgid "Password" -msgstr "" +msgstr "Passord" #: authtoken/serializers.py:20 msgid "User account is disabled." @@ -98,7 +99,7 @@ msgstr "Kan ikke logge inn med gitt legitimasjon." #: authtoken/serializers.py:26 msgid "Must include \"username\" and \"password\"." -msgstr "Må inkludere \"username\" og \"password\"." +msgstr "Må inneholde \"username\" og \"password\"." #: exceptions.py:49 msgid "A server error occurred." @@ -316,15 +317,15 @@ msgstr "Send inn" #: filters.py:336 msgid "ascending" -msgstr "" +msgstr "stigende" #: filters.py:337 msgid "descending" -msgstr "" +msgstr "synkende" #: pagination.py:193 msgid "Invalid page." -msgstr "" +msgstr "Ugyldig side" #: pagination.py:427 msgid "Invalid cursor" @@ -426,7 +427,7 @@ msgstr "Ugyldig versjon i URL-banen." #: versioning.py:115 msgid "Invalid version in URL path. Does not match any version namespace." -msgstr "" +msgstr "Ugyldig versjon i URL. Passer ikke med noen eksisterende versjon." #: versioning.py:147 msgid "Invalid version in hostname." diff --git a/rest_framework/locale/pt_BR/LC_MESSAGES/django.mo b/rest_framework/locale/pt_BR/LC_MESSAGES/django.mo index 482c07cdb98db3dec8f311ac8f3b150e21096025..2740e8c13ab167fca747b6f2a8835e6583e61962 100644 GIT binary patch delta 2737 zcmZA2TWl0n9LMp~mR^7Y)b|_k5!{4* z@Hw20ui-R2jrsT!HW-sMH>fmmV;WD(I4;KXSclntjaiG0I0p~oJiLO-uz#U3)!2&q z{1Arl5{|{;{frreHK-R{iMsCwCXG2rMID~OO8gV~Gn4wK-?R!f;~LaJ5qu1fVJ%+8 zMl2a%OgU~qZkc_k=MLi}{1TPP`#1$h7BLRvn#+?r z(~DS&pJx0KHPgG9b`H~-NxKZ$zh(t0Gp%?n%NPeWKqH-K?|4{+hj0vjftuhSNh%Yl z6fzBcFbnyvS&MVfMa|#@>dkN9LcERI{gtFgd*vlm`*UooNI0l|@u;;wr3QXJ~i6f=t$&Ld~EDm8st{mW@hxupH~Se*oFo<_hXXf5ypp1Lxyl zD?OnVxSaN$v`KT7N;NkojW&i2Z^Eb2baX%IG{)_6V6!@al;dvGb1 z@zYR$?a1WK?o9g)R6i$i9Q)5)rm}_`caX`M(75yi+fbY45Ng09s7#zfop@iNGIa|{ zo+;r&wX2X-Fg9`qnHNwm@;Yiy9KqiB8Rjy+xlBa^e1mLga}$-qf6>Cc3F-DkR3^$% zYiJ`$F&9t+{(#KE+(S)d6u;?NSd%e^`u+)2M!vo3GSY*Z`7fve|H9cgkTmtdrYYpVFO`+t$U?23_5#O2 za36xAboVBvrJKQ*Gu2>*s#g*$eNeRFwA*>VpghTSDWS>e1sN_lH|n+iD`}|cjWuhP z>BI)&8DcS^b*ms$bhdMj1pgzNa6F;1kZ2*ogqHJhLPfh>MVV8UR7gZnp4R%W$TYOu z8#8qawG>+CY+?(cHC{_-ZB=pzofWmjdO}6%)*iBn2$4^yXqg8Fwe-b-UPN*e7wys~ z2)2P~CbYJj39XfW89IpAQ^EPL099%T9WW1Q=$lyd1mDNreXN$|_&8DrD`j6Yb^JLeGg?u9vVn>_oWTvfbU*PA3+RdamW#9Zr0Q z9d`T!Ma6!1QF+cXXLss$QDIiT9gpwwVv*F{fgfZSriTo!asTZh7yQ=Z%7Qg@l1W( z3i~x9%lw-qt$B^Hs2%bA(1a5IcxkWHrqcQOMcrL(QP;Mj?#}M6?a_#xdeb_cRU5WD zqHeoqMQn>~m0Qj9Wre+1jGTC`hOu17ZSU-`gM{hRi1$#=ipC7{Lt|#=Hn!V4om6tn zoUGi{Ja4By9((Qjv#y*VZn>FF1sP7Nr20V}D zSbB$91Upd!8bb9?I^ROw?+dKgRBuozpre`(CS}d28Fr!`G>(mU1lw^2JF#TGSq+XM zfA$6+`rRR1ffrFL7brAaiRGBYjaY+e?A20#LZub|Lawof1!haJ8`T~~&0qpGBhUG% z>;Dcl z!b*%`!nM0FNxKiVmHSWw{RZ{BpIrNIRBjaU^aflVW&O2>_(Q<#GV1yhG1gyueU)KqM0uog8MdQl zupO6U+Vy{g8t@cqAOW7%g;7ce{helSgCgv$Hafj6-m z+j#l_zJyAiY19@3OR@uAf|_}|^J&!ehcSiMkaV);B!srC0jsbTTW}|8BIzSkHc`3k zOq6D`ejk!gb`mwyZ&44-k7t*%6?Ma>P&soDoADfO#n3Xd2k;TpeU2h?u+Lq48o54g zKU1mTiwNt^7;G)-#zRQH*nZR&dC02UY1E3GM%~q5bzc_$Q, 2015 # Filipe Rinaldi , 2015 # Hugo Leonardo Chalhoub Mendonça , 2015 +# Jonatas Baldin , 2017 msgid "" msgstr "" "Project-Id-Version: Django REST framework\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2016-07-12 16:13+0100\n" -"PO-Revision-Date: 2017-08-03 14:58+0000\n" -"Last-Translator: Thomas Christie \n" +"PO-Revision-Date: 2017-12-06 09:53+0000\n" +"Last-Translator: Jonatas Baldin \n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/django-rest-framework-1/django-rest-framework/language/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -60,35 +61,35 @@ msgstr "Token inválido." #: authtoken/apps.py:7 msgid "Auth Token" -msgstr "" +msgstr "Token de autenticação" #: authtoken/models.py:15 msgid "Key" -msgstr "" +msgstr "Chave" #: authtoken/models.py:18 msgid "User" -msgstr "" +msgstr "Usuário" #: authtoken/models.py:20 msgid "Created" -msgstr "" +msgstr "Criado" #: authtoken/models.py:29 msgid "Token" -msgstr "" +msgstr "Token" #: authtoken/models.py:30 msgid "Tokens" -msgstr "" +msgstr "Tokens" #: authtoken/serializers.py:8 msgid "Username" -msgstr "" +msgstr "Nome do usuário" #: authtoken/serializers.py:9 msgid "Password" -msgstr "" +msgstr "Senha" #: authtoken/serializers.py:20 msgid "User account is disabled." @@ -318,15 +319,15 @@ msgstr "Enviar" #: filters.py:336 msgid "ascending" -msgstr "" +msgstr "ascendente" #: filters.py:337 msgid "descending" -msgstr "" +msgstr "descendente" #: pagination.py:193 msgid "Invalid page." -msgstr "" +msgstr "Página inválida." #: pagination.py:427 msgid "Invalid cursor" @@ -428,7 +429,7 @@ msgstr "Versão inválida no caminho de URL." #: versioning.py:115 msgid "Invalid version in URL path. Does not match any version namespace." -msgstr "" +msgstr "Versão inválida no caminho da URL. Não corresponde a nenhuma versão do namespace." #: versioning.py:147 msgid "Invalid version in hostname." diff --git a/setup.py b/setup.py index 54acad01b..9223facc9 100755 --- a/setup.py +++ b/setup.py @@ -69,6 +69,7 @@ setup( 'Framework :: Django', 'Framework :: Django :: 1.10', 'Framework :: Django :: 1.11', + 'Framework :: Django :: 2.0', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', From 5e21bf852b3b00e62d6c8d8b1ef86d06de7f78a4 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Wed, 20 Dec 2017 21:27:22 +0100 Subject: [PATCH 019/520] Bumped Django 2.0 version in requirements list. --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 0e747463b..0b544e5bf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -87,7 +87,7 @@ continued development by **[signing up for a paid plan][funding]**. REST framework requires the following: * Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6) -* Django (1.10, 1.11, 2.0 alpha) +* Django (1.10, 1.11, 2.0) The following packages are optional: From 37cfe903385bc1c0b9de2674ad3b2d8682f93e53 Mon Sep 17 00:00:00 2001 From: Matthias Runge Date: Thu, 21 Dec 2017 11:00:43 +0100 Subject: [PATCH 020/520] Add locale files back to installed files (#5696) Resolves https://github.com/encode/django-rest-framework/issues/5695 --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index 48ec57edf..3c6c45e52 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,5 +2,6 @@ include README.md include LICENSE.md recursive-include rest_framework/static *.js *.css *.png *.eot *.svg *.ttf *.woff recursive-include rest_framework/templates *.html schema.js +recursice-include rest_framework/locale *.mo global-exclude __pycache__ global-exclude *.py[co] From df469260e148e569843541f8de7dca121fff6357 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 21 Dec 2017 10:03:03 +0000 Subject: [PATCH 021/520] Include woff2 in packaging. Closes #5692 --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 3c6c45e52..789f2bb16 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ include README.md include LICENSE.md -recursive-include rest_framework/static *.js *.css *.png *.eot *.svg *.ttf *.woff +recursive-include rest_framework/static *.js *.css *.png *.eot *.svg *.ttf *.woff *.woff2 recursive-include rest_framework/templates *.html schema.js recursice-include rest_framework/locale *.mo global-exclude __pycache__ From 3a22b1d1f0c8df2924dc35bb45a1f5b01a973c11 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 21 Dec 2017 10:03:41 +0000 Subject: [PATCH 022/520] Version 3.7.5 --- rest_framework/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index 8c3054407..492ecad15 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -8,7 +8,7 @@ ______ _____ _____ _____ __ """ __title__ = 'Django REST framework' -__version__ = '3.7.4' +__version__ = '3.7.5' __author__ = 'Tom Christie' __license__ = 'BSD 2-Clause' __copyright__ = 'Copyright 2011-2017 Tom Christie' From 0d96be9266488d0f7de0dcffad1092316d98e4bf Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 21 Dec 2017 10:13:18 +0000 Subject: [PATCH 023/520] Add 3.7.5 release notes --- docs/topics/release-notes.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index e6c9f78f2..52a7e6fbd 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -42,6 +42,13 @@ You can determine your currently installed version using `pip freeze`: ### 3.7.4 +**Date**: [21st December 2017][3.7.5-milestone] + +* Add missing *.woff2 font files to packaging. [#5692][gh5692] +* Add missing *.mo locale files to packaging. [#5695][gh5695], [#5696][gh5696] + +### 3.7.4 + **Date**: [20th December 2017][3.7.4-milestone] * Schema: Extract method for `manual_fields` processing [#5633][gh5633] @@ -924,7 +931,7 @@ For older release notes, [please see the version 2.x documentation][old-release- [3.7.2-milestone]: https://github.com/encode/django-rest-framework/milestone/59?closed=1 [3.7.3-milestone]: https://github.com/encode/django-rest-framework/milestone/60?closed=1 [3.7.4-milestone]: https://github.com/encode/django-rest-framework/milestone/62?closed=1 - +[3.7.5-milestone]: https://github.com/encode/django-rest-framework/milestone/63?closed=1 [gh2013]: https://github.com/encode/django-rest-framework/issues/2013 @@ -1733,3 +1740,7 @@ For older release notes, [please see the version 2.x documentation][old-release- [gh5579]: https://github.com/encode/django-rest-framework/issues/5579 [gh5633]: https://github.com/encode/django-rest-framework/issues/5633 + +[gh5692]: https://github.com/encode/django-rest-framework/issues/5692 +[gh5695]: https://github.com/encode/django-rest-framework/issues/5695 +[gh5696]: https://github.com/encode/django-rest-framework/issues/5696 From 65791d8c79bcf53ea578dad0a1dc78d17a39346c Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 21 Dec 2017 10:17:59 +0000 Subject: [PATCH 024/520] Version 3.7.5. Add missing .ico to packaging. --- MANIFEST.in | 2 +- docs/topics/release-notes.md | 9 ++++++++- rest_framework/__init__.py | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 789f2bb16..78f992897 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ include README.md include LICENSE.md -recursive-include rest_framework/static *.js *.css *.png *.eot *.svg *.ttf *.woff *.woff2 +recursive-include rest_framework/static *.js *.css *.png *.ico *.eot *.svg *.ttf *.woff *.woff2 recursive-include rest_framework/templates *.html schema.js recursice-include rest_framework/locale *.mo global-exclude __pycache__ diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 52a7e6fbd..7b6cad95e 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,7 +40,13 @@ You can determine your currently installed version using `pip freeze`: ## 3.7.x series -### 3.7.4 +### 3.7.6 + +**Date**: [21st December 2017][3.7.6-milestone] + +* Add missing *.ico icon files to packaging. + +### 3.7.5 **Date**: [21st December 2017][3.7.5-milestone] @@ -932,6 +938,7 @@ For older release notes, [please see the version 2.x documentation][old-release- [3.7.3-milestone]: https://github.com/encode/django-rest-framework/milestone/60?closed=1 [3.7.4-milestone]: https://github.com/encode/django-rest-framework/milestone/62?closed=1 [3.7.5-milestone]: https://github.com/encode/django-rest-framework/milestone/63?closed=1 +[3.7.6-milestone]: https://github.com/encode/django-rest-framework/milestone/64?closed=1 [gh2013]: https://github.com/encode/django-rest-framework/issues/2013 diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index 492ecad15..665d9ea41 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -8,7 +8,7 @@ ______ _____ _____ _____ __ """ __title__ = 'Django REST framework' -__version__ = '3.7.5' +__version__ = '3.7.6' __author__ = 'Tom Christie' __license__ = 'BSD 2-Clause' __copyright__ = 'Copyright 2011-2017 Tom Christie' From 67964a1bf4af3a9f37df03b419e8e7ff06b750ac Mon Sep 17 00:00:00 2001 From: Laurent Paoletti Date: Thu, 21 Dec 2017 12:12:08 +0100 Subject: [PATCH 025/520] Fix typo to bring locale back to installed files --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 78f992897..6f7cb8f13 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,6 +2,6 @@ include README.md include LICENSE.md recursive-include rest_framework/static *.js *.css *.png *.ico *.eot *.svg *.ttf *.woff *.woff2 recursive-include rest_framework/templates *.html schema.js -recursice-include rest_framework/locale *.mo +recursive-include rest_framework/locale *.mo global-exclude __pycache__ global-exclude *.py[co] From 955a6b902b0838cd4f4471dc5fab6b334f36615b Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Thu, 21 Dec 2017 12:35:37 +0100 Subject: [PATCH 026/520] Add 3.7.7 release notes --- docs/topics/release-notes.md | 8 ++++++++ rest_framework/__init__.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 7b6cad95e..4d668254c 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,6 +40,12 @@ You can determine your currently installed version using `pip freeze`: ## 3.7.x series +### 3.7.7 + +**Date**: [21st December 2017][3.7.7-milestone] + +* Fix typo to include *.mo locale files to packaging. [#5697][gh5697], [#5695][gh5695] + ### 3.7.6 **Date**: [21st December 2017][3.7.6-milestone] @@ -939,6 +945,7 @@ For older release notes, [please see the version 2.x documentation][old-release- [3.7.4-milestone]: https://github.com/encode/django-rest-framework/milestone/62?closed=1 [3.7.5-milestone]: https://github.com/encode/django-rest-framework/milestone/63?closed=1 [3.7.6-milestone]: https://github.com/encode/django-rest-framework/milestone/64?closed=1 +[3.7.7-milestone]: https://github.com/encode/django-rest-framework/milestone/65?closed=1 [gh2013]: https://github.com/encode/django-rest-framework/issues/2013 @@ -1751,3 +1758,4 @@ For older release notes, [please see the version 2.x documentation][old-release- [gh5692]: https://github.com/encode/django-rest-framework/issues/5692 [gh5695]: https://github.com/encode/django-rest-framework/issues/5695 [gh5696]: https://github.com/encode/django-rest-framework/issues/5696 +[gh5697]: https://github.com/encode/django-rest-framework/issues/5697 diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index 665d9ea41..5d16490e8 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -8,7 +8,7 @@ ______ _____ _____ _____ __ """ __title__ = 'Django REST framework' -__version__ = '3.7.6' +__version__ = '3.7.7' __author__ = 'Tom Christie' __license__ = 'BSD 2-Clause' __copyright__ = 'Copyright 2011-2017 Tom Christie' From 832267e945d65b97802b84fe70ef1e156ecb8ab1 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Fri, 22 Dec 2017 07:28:35 +0000 Subject: [PATCH 027/520] Fix formatting of the 3.7.4 release note (#5704) --- docs/topics/release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 4d668254c..244adef0b 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -73,6 +73,7 @@ You can determine your currently installed version using `pip freeze`: Note: `AutoSchema.__init__` now ensures `manual_fields` is a list. Previously may have been stored internally as `None`. + * Remove ulrparse compatability shim; use six instead [#5579][gh5579] * Drop compat wrapper for `TimeDelta.total_seconds()` [#5577][gh5577] * Clean up all whitespace throughout project [#5578][gh5578] From 5fc35eb7eb1ce8ca91fa6364978b5e423b80a332 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Fri, 22 Dec 2017 11:52:51 -0500 Subject: [PATCH 028/520] Add missing word in 'Field.allow_null' docs --- docs/api-guide/fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 6bf0ed15e..a2f10ed19 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -45,7 +45,7 @@ Defaults to `True`. Normally an error will be raised if `None` is passed to a serializer field. Set this keyword argument to `True` if `None` should be considered a valid value. -Note that setting this argument to `True` will imply a default value of `null` for serialization output, but does imply a default for input deserialization. +Note that setting this argument to `True` will imply a default value of `null` for serialization output, but does not imply a default for input deserialization. Defaults to `False` From 6ce60cd594ce3ddb14f08fb69f16b1901f1624ea Mon Sep 17 00:00:00 2001 From: Mariano Baragiola Date: Wed, 27 Dec 2017 10:17:10 -0300 Subject: [PATCH 029/520] Update writable nested serializers docs --- docs/api-guide/serializers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 85682838b..059e87391 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -352,7 +352,7 @@ Here's an example for an `.update()` method on our previous `UserSerializer` cla Because the behavior of nested creates and updates can be ambiguous, and may require complex dependencies between related models, REST framework 3 requires you to always write these methods explicitly. The default `ModelSerializer` `.create()` and `.update()` methods do not include support for writable nested representations. -It is possible that a third party package, providing automatic support some kinds of automatic writable nested representations may be released alongside the 3.1 release. +There are however, third-party packages available such as [DRF Writable Nested][route-decorators] that support automatic writable nested representations. #### Handling saving related instances in model manager classes From be0a57b0f12ad09d773cd9a898ddccd60324a608 Mon Sep 17 00:00:00 2001 From: Mariano Baragiola Date: Wed, 27 Dec 2017 10:28:59 -0300 Subject: [PATCH 030/520] FIX link --- docs/api-guide/serializers.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 059e87391..140de0fe2 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -352,7 +352,7 @@ Here's an example for an `.update()` method on our previous `UserSerializer` cla Because the behavior of nested creates and updates can be ambiguous, and may require complex dependencies between related models, REST framework 3 requires you to always write these methods explicitly. The default `ModelSerializer` `.create()` and `.update()` methods do not include support for writable nested representations. -There are however, third-party packages available such as [DRF Writable Nested][route-decorators] that support automatic writable nested representations. +There are however, third-party packages available such as [DRF Writable Nested][thirdparty-writable-nested] that support automatic writable nested representations. #### Handling saving related instances in model manager classes @@ -1173,6 +1173,7 @@ The [drf-writable-nested][drf-writable-nested] package provides writable nested [relations]: relations.md [model-managers]: https://docs.djangoproject.com/en/stable/topics/db/managers/ [encapsulation-blogpost]: http://www.dabapps.com/blog/django-models-and-encapsulation/ +[thirdparty-writable-nested]: serializers.md#drf-writable-nested [django-rest-marshmallow]: http://tomchristie.github.io/django-rest-marshmallow/ [marshmallow]: https://marshmallow.readthedocs.io/en/latest/ [serpy]: https://github.com/clarkduvall/serpy From 88c75ba808c5b0ac830efdf36117297e350f0925 Mon Sep 17 00:00:00 2001 From: guntanis Date: Thu, 28 Dec 2017 02:01:01 -0800 Subject: [PATCH 031/520] Fixed "typo" in example. Fixing code "typo" in example. In the original file, line 145 reads: url(r'^api-auth/', include('rest_framework.urls'), It's missing the closing parenthesis. --- docs/tutorial/4-authentication-and-permissions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index 6e5b077ce..af9a7c0ff 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -142,7 +142,7 @@ Add the following import at the top of the file: And, at the end of the file, add a pattern to include the login and logout views for the browsable API. urlpatterns += [ - url(r'^api-auth/', include('rest_framework.urls'), + url(r'^api-auth/', include('rest_framework.urls')), ] The `r'^api-auth/'` part of pattern can actually be whatever URL you want to use. From 6bd773e7f8bf3535ee51e67708f4396c00f78a1d Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 2 Jan 2018 04:45:59 -0500 Subject: [PATCH 032/520] Improve composite field child errors (#5655) * Fixup DictField test descriptions * Nest ListField/DictField errors under the idx/key * Add nested ListField/DictField tests --- rest_framework/fields.py | 37 +++++++++++++++++++++++++++----- tests/test_fields.py | 46 +++++++++++++++++++++++++++++++++++----- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index a710df7b4..9b88784c8 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1626,7 +1626,7 @@ class ListField(Field): self.fail('not_a_list', input_type=type(data).__name__) if not self.allow_empty and len(data) == 0: self.fail('empty') - return [self.child.run_validation(item) for item in data] + return self.run_child_validation(data) def to_representation(self, data): """ @@ -1634,6 +1634,20 @@ class ListField(Field): """ return [self.child.to_representation(item) if item is not None else None for item in data] + def run_child_validation(self, data): + result = [] + errors = OrderedDict() + + for idx, item in enumerate(data): + try: + result.append(self.child.run_validation(item)) + except ValidationError as e: + errors[idx] = e.detail + + if not errors: + return result + raise ValidationError(errors) + class DictField(Field): child = _UnvalidatedField() @@ -1669,10 +1683,7 @@ class DictField(Field): data = html.parse_html_dict(data) if not isinstance(data, dict): self.fail('not_a_dict', input_type=type(data).__name__) - return { - six.text_type(key): self.child.run_validation(value) - for key, value in data.items() - } + return self.run_child_validation(data) def to_representation(self, value): """ @@ -1683,6 +1694,22 @@ class DictField(Field): for key, val in value.items() } + def run_child_validation(self, data): + result = {} + errors = OrderedDict() + + for key, value in data.items(): + key = six.text_type(key) + + try: + result[key] = self.child.run_validation(value) + except ValidationError as e: + errors[key] = e.detail + + if not errors: + return result + raise ValidationError(errors) + class JSONField(Field): default_error_messages = { diff --git a/tests/test_fields.py b/tests/test_fields.py index fc9ce192a..bc11cd133 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1767,7 +1767,7 @@ class TestListField(FieldValues): ] invalid_inputs = [ ('not a list', ['Expected a list of items but got type "str".']), - ([1, 2, 'error'], ['A valid integer is required.']), + ([1, 2, 'error', 'error'], {2: ['A valid integer is required.'], 3: ['A valid integer is required.']}), ({'one': 'two'}, ['Expected a list of items but got type "dict".']) ] outputs = [ @@ -1794,6 +1794,25 @@ class TestListField(FieldValues): assert exc_info.value.detail == ['Expected a list of items but got type "dict".'] +class TestNestedListField(FieldValues): + """ + Values for nested `ListField` with IntegerField as child. + """ + valid_inputs = [ + ([[1, 2], [3]], [[1, 2], [3]]), + ([[]], [[]]) + ] + invalid_inputs = [ + (['not a list'], {0: ['Expected a list of items but got type "str".']}), + ([[1, 2, 'error'], ['error']], {0: {2: ['A valid integer is required.']}, 1: {0: ['A valid integer is required.']}}), + ([{'one': 'two'}], {0: ['Expected a list of items but got type "dict".']}) + ] + outputs = [ + ([[1, 2], [3]], [[1, 2], [3]]), + ] + field = serializers.ListField(child=serializers.ListField(child=serializers.IntegerField())) + + class TestEmptyListField(FieldValues): """ Values for `ListField` with allow_empty=False flag. @@ -1834,13 +1853,13 @@ class TestUnvalidatedListField(FieldValues): class TestDictField(FieldValues): """ - Values for `ListField` with CharField as child. + Values for `DictField` with CharField as child. """ valid_inputs = [ ({'a': 1, 'b': '2', 3: 3}, {'a': '1', 'b': '2', '3': '3'}), ] invalid_inputs = [ - ({'a': 1, 'b': None}, ['This field may not be null.']), + ({'a': 1, 'b': None, 'c': None}, {'b': ['This field may not be null.'], 'c': ['This field may not be null.']}), ('not a dict', ['Expected a dictionary of items but got type "str".']), ] outputs = [ @@ -1866,9 +1885,26 @@ class TestDictField(FieldValues): assert output is None +class TestNestedDictField(FieldValues): + """ + Values for nested `DictField` with CharField as child. + """ + valid_inputs = [ + ({0: {'a': 1, 'b': '2'}, 1: {3: 3}}, {'0': {'a': '1', 'b': '2'}, '1': {'3': '3'}}), + ] + invalid_inputs = [ + ({0: {'a': 1, 'b': None}, 1: {'c': None}}, {'0': {'b': ['This field may not be null.']}, '1': {'c': ['This field may not be null.']}}), + ({0: 'not a dict'}, {'0': ['Expected a dictionary of items but got type "str".']}), + ] + outputs = [ + ({0: {'a': 1, 'b': '2'}, 1: {3: 3}}, {'0': {'a': '1', 'b': '2'}, '1': {'3': '3'}}), + ] + field = serializers.DictField(child=serializers.DictField(child=serializers.CharField())) + + class TestDictFieldWithNullChild(FieldValues): """ - Values for `ListField` with allow_null CharField as child. + Values for `DictField` with allow_null CharField as child. """ valid_inputs = [ ({'a': None, 'b': '2', 3: 3}, {'a': None, 'b': '2', '3': '3'}), @@ -1883,7 +1919,7 @@ class TestDictFieldWithNullChild(FieldValues): class TestUnvalidatedDictField(FieldValues): """ - Values for `ListField` with no `child` argument. + Values for `DictField` with no `child` argument. """ valid_inputs = [ ({'a': 1, 'b': [4, 5, 6], 1: 123}, {'a': 1, 'b': [4, 5, 6], '1': 123}), From b7ed6459276f6416a155f1733abee7d1ce4ec7d2 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 2 Jan 2018 04:50:49 -0500 Subject: [PATCH 033/520] Disable HTML inputs for dict/list fields (#5702) --- rest_framework/renderers.py | 6 ++++++ .../rest_framework/horizontal/dict_field.html | 11 +++++++++++ .../rest_framework/horizontal/list_field.html | 11 +++++++++++ .../templates/rest_framework/inline/dict_field.html | 9 +++++++++ .../templates/rest_framework/inline/list_field.html | 9 +++++++++ .../templates/rest_framework/vertical/dict_field.html | 7 +++++++ .../templates/rest_framework/vertical/list_field.html | 7 +++++++ 7 files changed, 60 insertions(+) create mode 100644 rest_framework/templates/rest_framework/horizontal/dict_field.html create mode 100644 rest_framework/templates/rest_framework/horizontal/list_field.html create mode 100644 rest_framework/templates/rest_framework/inline/dict_field.html create mode 100644 rest_framework/templates/rest_framework/inline/list_field.html create mode 100644 rest_framework/templates/rest_framework/vertical/dict_field.html create mode 100644 rest_framework/templates/rest_framework/vertical/list_field.html diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 80a22dee5..f071e7b4d 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -320,6 +320,12 @@ class HTMLFormRenderer(BaseRenderer): serializers.ListSerializer: { 'base_template': 'list_fieldset.html' }, + serializers.ListField: { + 'base_template': 'list_field.html' + }, + serializers.DictField: { + 'base_template': 'dict_field.html' + }, serializers.FilePathField: { 'base_template': 'select.html', }, diff --git a/rest_framework/templates/rest_framework/horizontal/dict_field.html b/rest_framework/templates/rest_framework/horizontal/dict_field.html new file mode 100644 index 000000000..7c7414bc4 --- /dev/null +++ b/rest_framework/templates/rest_framework/horizontal/dict_field.html @@ -0,0 +1,11 @@ +
+ {% if field.label %} + + {% endif %} + +
+

Dictionaries are not currently supported in HTML input.

+
+
diff --git a/rest_framework/templates/rest_framework/horizontal/list_field.html b/rest_framework/templates/rest_framework/horizontal/list_field.html new file mode 100644 index 000000000..46a9b7ecd --- /dev/null +++ b/rest_framework/templates/rest_framework/horizontal/list_field.html @@ -0,0 +1,11 @@ +
+ {% if field.label %} + + {% endif %} + +
+

Lists are not currently supported in HTML input.

+
+
diff --git a/rest_framework/templates/rest_framework/inline/dict_field.html b/rest_framework/templates/rest_framework/inline/dict_field.html new file mode 100644 index 000000000..1301452b9 --- /dev/null +++ b/rest_framework/templates/rest_framework/inline/dict_field.html @@ -0,0 +1,9 @@ +
+ {% if field.label %} + + {% endif %} + +

Dictionaries are not currently supported in HTML input.

+
diff --git a/rest_framework/templates/rest_framework/inline/list_field.html b/rest_framework/templates/rest_framework/inline/list_field.html new file mode 100644 index 000000000..321d01bd1 --- /dev/null +++ b/rest_framework/templates/rest_framework/inline/list_field.html @@ -0,0 +1,9 @@ +
+ {% if field.label %} + + {% endif %} + +

Lists are not currently supported in HTML input.

+
diff --git a/rest_framework/templates/rest_framework/vertical/dict_field.html b/rest_framework/templates/rest_framework/vertical/dict_field.html new file mode 100644 index 000000000..dde803b49 --- /dev/null +++ b/rest_framework/templates/rest_framework/vertical/dict_field.html @@ -0,0 +1,7 @@ +
+ {% if field.label %} + + {% endif %} + +

Dictionaries are not currently supported in HTML input.

+
diff --git a/rest_framework/templates/rest_framework/vertical/list_field.html b/rest_framework/templates/rest_framework/vertical/list_field.html new file mode 100644 index 000000000..47a60c5d9 --- /dev/null +++ b/rest_framework/templates/rest_framework/vertical/list_field.html @@ -0,0 +1,7 @@ +
+ {% if field.label %} + + {% endif %} + +

Lists are not currently supported in HTML input.

+
From 7e2cca285dacf8bf2d32a7db6efd90303aff6d7b Mon Sep 17 00:00:00 2001 From: Floyd Hightower Date: Tue, 2 Jan 2018 05:51:42 -0400 Subject: [PATCH 034/520] Adding missing parenthesis (#5707) From 0712094ea2e846d41ef3ce2a4d12b9159911abfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=20V=C3=AEjdea?= Date: Tue, 2 Jan 2018 10:52:52 +0100 Subject: [PATCH 035/520] Fix typo in HostNameVersioning doc (#5709) --- docs/api-guide/versioning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/versioning.md b/docs/api-guide/versioning.md index 29672c96e..4a875b87e 100644 --- a/docs/api-guide/versioning.md +++ b/docs/api-guide/versioning.md @@ -183,7 +183,7 @@ By default this implementation expects the hostname to match this simple regular Note that the first group is enclosed in brackets, indicating that this is the matched portion of the hostname. -The `HostNameVersioning` scheme can be awkward to use in debug mode as you will typically be accessing a raw IP address such as `127.0.0.1`. There are various online services which you to [access localhost with a custom subdomain][lvh] which you may find helpful in this case. +The `HostNameVersioning` scheme can be awkward to use in debug mode as you will typically be accessing a raw IP address such as `127.0.0.1`. There are various online tutorials on how to [access localhost with a custom subdomain][lvh] which you may find helpful in this case. Hostname based versioning can be particularly useful if you have requirements to route incoming requests to different servers based on the version, as you can configure different DNS records for different API versions. From 6b0bf72bb8ba3e6ff1e7a334e6a23d95e8c2944a Mon Sep 17 00:00:00 2001 From: David De Sousa Date: Tue, 2 Jan 2018 10:59:08 +0100 Subject: [PATCH 036/520] using rsplit to get module and classname for imports (#5712) --- rest_framework/settings.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rest_framework/settings.py b/rest_framework/settings.py index db92b7a7b..6c581f8e8 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -179,8 +179,7 @@ def import_from_string(val, setting_name): """ try: # Nod to tastypie's use of importlib. - parts = val.split('.') - module_path, class_name = '.'.join(parts[:-1]), parts[-1] + module_path, class_name = val.rsplit('.', 1) module = import_module(module_path) return getattr(module, class_name) except (ImportError, AttributeError) as e: From b65967711c911de05a43cf494de076a13ff74448 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 2 Jan 2018 05:14:25 -0500 Subject: [PATCH 037/520] Formalize URLPatternsTestCase (#5703) * Add formalized URLPatternsTestCase * Update versioning tests w/ new URLPatternsTestCase * Cleanup router tests urlpatterns * Add docs for URLPatternsTestCase --- docs/api-guide/testing.md | 28 ++++++++++++++++++- rest_framework/test.py | 44 ++++++++++++++++++++++++++++- tests/test_routers.py | 59 ++++++++++++++++++++++----------------- tests/test_testing.py | 29 ++++++++++++++++++- tests/test_versioning.py | 33 ++++------------------ 5 files changed, 138 insertions(+), 55 deletions(-) diff --git a/docs/api-guide/testing.md b/docs/api-guide/testing.md index caba5cea2..d2ff6e7cb 100644 --- a/docs/api-guide/testing.md +++ b/docs/api-guide/testing.md @@ -292,7 +292,7 @@ similar way as with `RequestsClient`. --- -# Test cases +# API Test cases REST framework includes the following test case classes, that mirror the existing Django test case classes, but use `APIClient` instead of Django's default `Client`. @@ -324,6 +324,32 @@ You can use any of REST framework's test case classes as you would for the regul --- +# URLPatternsTestCase + +REST framework also provides a test case class for isolating `urlpatterns` on a per-class basis. Note that this inherits from Django's `SimpleTestCase`, and will most likely need to be mixed with another test case class. + +## Example + + from django.urls import include, path, reverse + from rest_framework.test import APITestCase, URLPatternsTestCase + + + class AccountTests(APITestCase, URLPatternsTestCase): + urlpatterns = [ + path('api/', include('api.urls')), + ] + + def test_create_account(self): + """ + Ensure we can create a new account object. + """ + url = reverse('account-list') + response = self.client.get(url, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(len(response.data), 1) + +--- + # Testing responses ## Checking the response data diff --git a/rest_framework/test.py b/rest_framework/test.py index ebad19a4e..3b745bd62 100644 --- a/rest_framework/test.py +++ b/rest_framework/test.py @@ -5,11 +5,12 @@ from __future__ import unicode_literals import io +from importlib import import_module from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.core.handlers.wsgi import WSGIHandler -from django.test import testcases +from django.test import override_settings, testcases from django.test.client import Client as DjangoClient from django.test.client import RequestFactory as DjangoRequestFactory from django.test.client import ClientHandler @@ -358,3 +359,44 @@ class APISimpleTestCase(testcases.SimpleTestCase): class APILiveServerTestCase(testcases.LiveServerTestCase): client_class = APIClient + + +class URLPatternsTestCase(testcases.SimpleTestCase): + """ + Isolate URL patterns on a per-TestCase basis. For example, + + class ATestCase(URLPatternsTestCase): + urlpatterns = [...] + + def test_something(self): + ... + + class AnotherTestCase(URLPatternsTestCase): + urlpatterns = [...] + + def test_something_else(self): + ... + """ + @classmethod + def setUpClass(cls): + # Get the module of the TestCase subclass + cls._module = import_module(cls.__module__) + cls._override = override_settings(ROOT_URLCONF=cls.__module__) + + if hasattr(cls._module, 'urlpatterns'): + cls._module_urlpatterns = cls._module.urlpatterns + + cls._module.urlpatterns = cls.urlpatterns + + cls._override.enable() + super(URLPatternsTestCase, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(URLPatternsTestCase, cls).tearDownClass() + cls._override.disable() + + if hasattr(cls, '_module_urlpatterns'): + cls._module.urlpatterns = cls._module_urlpatterns + else: + del cls._module.urlpatterns diff --git a/tests/test_routers.py b/tests/test_routers.py index 5a1cfe8f4..55ccc647b 100644 --- a/tests/test_routers.py +++ b/tests/test_routers.py @@ -14,7 +14,7 @@ from rest_framework.compat import get_regex_pattern from rest_framework.decorators import detail_route, list_route from rest_framework.response import Response from rest_framework.routers import DefaultRouter, SimpleRouter -from rest_framework.test import APIRequestFactory +from rest_framework.test import APIRequestFactory, URLPatternsTestCase from rest_framework.utils import json factory = APIRequestFactory() @@ -90,23 +90,10 @@ namespaced_router.register(r'example', MockViewSet, base_name='example') empty_prefix_router = SimpleRouter() empty_prefix_router.register(r'', EmptyPrefixViewSet, base_name='empty_prefix') -empty_prefix_urls = [ - url(r'^', include(empty_prefix_router.urls)), -] regex_url_path_router = SimpleRouter() regex_url_path_router.register(r'', RegexUrlPathViewSet, base_name='regex') -urlpatterns = [ - url(r'^non-namespaced/', include(namespaced_router.urls)), - url(r'^namespaced/', include((namespaced_router.urls, 'example'), namespace='example')), - url(r'^example/', include(notes_router.urls)), - url(r'^example2/', include(kwarged_notes_router.urls)), - - url(r'^empty-prefix/', include(empty_prefix_urls)), - url(r'^regex/', include(regex_url_path_router.urls)) -] - class BasicViewSet(viewsets.ViewSet): def list(self, request, *args, **kwargs): @@ -156,8 +143,12 @@ class TestSimpleRouter(TestCase): assert route.mapping[method] == endpoint -@override_settings(ROOT_URLCONF='tests.test_routers') -class TestRootView(TestCase): +class TestRootView(URLPatternsTestCase, TestCase): + urlpatterns = [ + url(r'^non-namespaced/', include(namespaced_router.urls)), + url(r'^namespaced/', include((namespaced_router.urls, 'namespaced'), namespace='namespaced')), + ] + def test_retrieve_namespaced_root(self): response = self.client.get('/namespaced/') assert response.data == {"example": "http://testserver/namespaced/example/"} @@ -167,11 +158,15 @@ class TestRootView(TestCase): assert response.data == {"example": "http://testserver/non-namespaced/example/"} -@override_settings(ROOT_URLCONF='tests.test_routers') -class TestCustomLookupFields(TestCase): +class TestCustomLookupFields(URLPatternsTestCase, TestCase): """ Ensure that custom lookup fields are correctly routed. """ + urlpatterns = [ + url(r'^example/', include(notes_router.urls)), + url(r'^example2/', include(kwarged_notes_router.urls)), + ] + def setUp(self): RouterTestModel.objects.create(uuid='123', text='foo bar') RouterTestModel.objects.create(uuid='a b', text='baz qux') @@ -219,12 +214,17 @@ class TestLookupValueRegex(TestCase): @override_settings(ROOT_URLCONF='tests.test_routers') -class TestLookupUrlKwargs(TestCase): +class TestLookupUrlKwargs(URLPatternsTestCase, TestCase): """ Ensure the router honors lookup_url_kwarg. Setup a deep lookup_field, but map it to a simple URL kwarg. """ + urlpatterns = [ + url(r'^example/', include(notes_router.urls)), + url(r'^example2/', include(kwarged_notes_router.urls)), + ] + def setUp(self): RouterTestModel.objects.create(uuid='123', text='foo bar') @@ -408,8 +408,11 @@ class TestDynamicListAndDetailRouter(TestCase): self._test_list_and_detail_route_decorators(SubDynamicListAndDetailViewSet) -@override_settings(ROOT_URLCONF='tests.test_routers') -class TestEmptyPrefix(TestCase): +class TestEmptyPrefix(URLPatternsTestCase, TestCase): + urlpatterns = [ + url(r'^empty-prefix/', include(empty_prefix_router.urls)), + ] + def test_empty_prefix_list(self): response = self.client.get('/empty-prefix/') assert response.status_code == 200 @@ -422,8 +425,11 @@ class TestEmptyPrefix(TestCase): assert json.loads(response.content.decode('utf-8')) == {'uuid': '111', 'text': 'First'} -@override_settings(ROOT_URLCONF='tests.test_routers') -class TestRegexUrlPath(TestCase): +class TestRegexUrlPath(URLPatternsTestCase, TestCase): + urlpatterns = [ + url(r'^regex/', include(regex_url_path_router.urls)), + ] + def test_regex_url_path_list(self): kwarg = '1234' response = self.client.get('/regex/list/{}/'.format(kwarg)) @@ -438,8 +444,11 @@ class TestRegexUrlPath(TestCase): assert json.loads(response.content.decode('utf-8')) == {'pk': pk, 'kwarg': kwarg} -@override_settings(ROOT_URLCONF='tests.test_routers') -class TestViewInitkwargs(TestCase): +class TestViewInitkwargs(URLPatternsTestCase, TestCase): + urlpatterns = [ + url(r'^example/', include(notes_router.urls)), + ] + def test_suffix(self): match = resolve('/example/notes/') initkwargs = match.func.initkwargs diff --git a/tests/test_testing.py b/tests/test_testing.py index 1af6ef02e..7868f724c 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -12,7 +12,7 @@ from rest_framework import fields, serializers from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.test import ( - APIClient, APIRequestFactory, force_authenticate + APIClient, APIRequestFactory, URLPatternsTestCase, force_authenticate ) @@ -283,3 +283,30 @@ class TestAPIRequestFactory(TestCase): content_type='application/json', ) assert request.META['CONTENT_TYPE'] == 'application/json' + + +class TestUrlPatternTestCase(URLPatternsTestCase): + urlpatterns = [ + url(r'^$', view), + ] + + @classmethod + def setUpClass(cls): + assert urlpatterns is not cls.urlpatterns + super(TestUrlPatternTestCase, cls).setUpClass() + assert urlpatterns is cls.urlpatterns + + @classmethod + def tearDownClass(cls): + assert urlpatterns is cls.urlpatterns + super(TestUrlPatternTestCase, cls).tearDownClass() + assert urlpatterns is not cls.urlpatterns + + def test_urlpatterns(self): + assert self.client.get('/').status_code == 200 + + +class TestExistingPatterns(TestCase): + def test_urlpatterns(self): + # sanity test to ensure that this test module does not have a '/' route + assert self.client.get('/').status_code == 404 diff --git a/tests/test_versioning.py b/tests/test_versioning.py index e73059c7d..7e650e275 100644 --- a/tests/test_versioning.py +++ b/tests/test_versioning.py @@ -7,33 +7,12 @@ from rest_framework.decorators import APIView from rest_framework.relations import PKOnlyObject from rest_framework.response import Response from rest_framework.reverse import reverse -from rest_framework.test import APIRequestFactory, APITestCase +from rest_framework.test import ( + APIRequestFactory, APITestCase, URLPatternsTestCase +) from rest_framework.versioning import NamespaceVersioning -@override_settings(ROOT_URLCONF='tests.test_versioning') -class URLPatternsTestCase(APITestCase): - """ - Isolates URL patterns used during testing on the test class itself. - For example: - - class MyTestCase(URLPatternsTestCase): - urlpatterns = [ - ... - ] - - def test_something(self): - ... - """ - def setUp(self): - global urlpatterns - urlpatterns = self.urlpatterns - - def tearDown(self): - global urlpatterns - urlpatterns = [] - - class RequestVersionView(APIView): def get(self, request, *args, **kwargs): return Response({'version': request.version}) @@ -163,7 +142,7 @@ class TestRequestVersion: assert response.data == {'version': None} -class TestURLReversing(URLPatternsTestCase): +class TestURLReversing(URLPatternsTestCase, APITestCase): included = [ url(r'^namespaced/$', dummy_view, name='another'), url(r'^example/(?P\d+)/$', dummy_pk_view, name='example-detail') @@ -329,7 +308,7 @@ class TestAllowedAndDefaultVersion: assert response.data == {'version': 'v2'} -class TestHyperlinkedRelatedField(URLPatternsTestCase): +class TestHyperlinkedRelatedField(URLPatternsTestCase, APITestCase): included = [ url(r'^namespaced/(?P\d+)/$', dummy_pk_view, name='namespaced'), ] @@ -361,7 +340,7 @@ class TestHyperlinkedRelatedField(URLPatternsTestCase): self.field.to_internal_value('/v2/namespaced/3/') -class TestNamespaceVersioningHyperlinkedRelatedFieldScheme(URLPatternsTestCase): +class TestNamespaceVersioningHyperlinkedRelatedFieldScheme(URLPatternsTestCase, APITestCase): nested = [ url(r'^namespaced/(?P\d+)/$', dummy_pk_view, name='nested'), ] From 351503907ceaf969f07cb61d9bbca320a14f4623 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 2 Jan 2018 05:28:45 -0500 Subject: [PATCH 038/520] Add exception translation test (#5700) --- tests/test_exceptions.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 8b5628ef2..176aeb174 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -1,11 +1,11 @@ from __future__ import unicode_literals from django.test import TestCase -from django.utils import six +from django.utils import six, translation from django.utils.translation import ugettext_lazy as _ from rest_framework.exceptions import ( - ErrorDetail, Throttled, _get_error_details + APIException, ErrorDetail, Throttled, _get_error_details ) @@ -51,3 +51,12 @@ class ExceptionTestCase(TestCase): assert exception.get_full_details() == { 'message': 'Slow down! Expected available in {} seconds.'.format(2 if six.PY3 else 2.), 'code': 'throttled'} + + +class TranslationTests(TestCase): + + @translation.override('fr') + def test_message(self): + # this test largely acts as a sanity test to ensure the translation files are present. + self.assertEqual(_('A server error occurred.'), 'Une erreur du serveur est survenue.') + self.assertEqual(six.text_type(APIException()), 'Une erreur du serveur est survenue.') From 68519c092f62693f161a455621ad89ec15b47a31 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 2 Jan 2018 05:35:56 -0500 Subject: [PATCH 039/520] Test staticfiles (#5701) * Remove 'MIDDLEWARE_CLASSES' compat setting * Remove 'django.setup()' compat import * Move '--no-pkgroot' handling to conftest * Add staticfiles handling to dist build --- runtests.py | 15 ------------- tests/conftest.py | 57 ++++++++++++++++++++++++++++++++++------------- tox.ini | 2 +- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/runtests.py b/runtests.py index a8f818ad7..d0e22a967 100755 --- a/runtests.py +++ b/runtests.py @@ -1,7 +1,6 @@ #! /usr/bin/env python from __future__ import print_function -import os import subprocess import sys @@ -82,20 +81,6 @@ if __name__ == "__main__": run_flake8 = False run_isort = False - try: - # Remove the package root directory from `sys.path`, ensuring that rest_framework - # is imported from the installed site packages. Used for testing the distribution - sys.argv.remove('--no-pkgroot') - except ValueError: - pass - else: - sys.path.pop(0) - - # import rest_framework before pytest re-adds the package root directory. - import rest_framework - package_dir = os.path.join(os.getcwd(), 'rest_framework') - assert not rest_framework.__file__.startswith(package_dir) - if len(sys.argv) > 1: pytest_args = sys.argv[1:] first_arg = pytest_args[0] diff --git a/tests/conftest.py b/tests/conftest.py index 9906935d7..927ddee62 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,12 +1,22 @@ -def pytest_configure(): - from django.conf import settings +import os +import sys - MIDDLEWARE = ( - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - ) +import django +from django.core import management + + +def pytest_addoption(parser): + parser.addoption('--no-pkgroot', action='store_true', default=False, + help='Remove package root directory from sys.path, ensuring that ' + 'rest_framework is imported from the installed site-packages. ' + 'Used for testing the distribution.') + parser.addoption('--staticfiles', action='store_true', default=False, + help='Run tests with static files collection, using manifest ' + 'staticfiles storage. Used for testing the distribution.') + + +def pytest_configure(config): + from django.conf import settings settings.configure( DEBUG_PROPAGATE_EXCEPTIONS=True, @@ -31,8 +41,12 @@ def pytest_configure(): } }, ], - MIDDLEWARE=MIDDLEWARE, - MIDDLEWARE_CLASSES=MIDDLEWARE, + MIDDLEWARE=( + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + ), INSTALLED_APPS=( 'django.contrib.auth', 'django.contrib.contenttypes', @@ -64,8 +78,21 @@ def pytest_configure(): 'guardian', ) - try: - import django - django.setup() - except AttributeError: - pass + if config.getoption('--no-pkgroot'): + sys.path.pop(0) + + # import rest_framework before pytest re-adds the package root directory. + import rest_framework + package_dir = os.path.join(os.getcwd(), 'rest_framework') + assert not rest_framework.__file__.startswith(package_dir) + + # Manifest storage will raise an exception if static files are not present (ie, a packaging failure). + if config.getoption('--staticfiles'): + import rest_framework + settings.STATIC_ROOT = os.path.join(os.path.dirname(rest_framework.__file__), 'static-root') + settings.STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage' + + django.setup() + + if config.getoption('--staticfiles'): + management.call_command('collectstatic', verbosity=0, interactive=False) diff --git a/tox.ini b/tox.ini index f04e6ba93..d48d79be6 100644 --- a/tox.ini +++ b/tox.ini @@ -31,7 +31,7 @@ deps = -rrequirements/requirements-optionals.txt [testenv:dist] -commands = ./runtests.py --fast {posargs} --no-pkgroot -rw +commands = ./runtests.py --fast {posargs} --no-pkgroot --staticfiles -rw deps = django -rrequirements/requirements-testing.txt From 522d45354633f080288f82ebe1535ef4abbf0b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristi=20V=C3=AEjdea?= Date: Tue, 2 Jan 2018 14:51:54 +0100 Subject: [PATCH 040/520] Add drf-yasg to documentation and schema 3rd party packages (#5720) Also fixed broken `swagger` link. --- docs/api-guide/schemas.md | 7 +++++++ docs/img/drf-yasg.png | Bin 0 -> 59949 bytes docs/topics/documenting-your-api.md | 20 +++++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 docs/img/drf-yasg.png diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index 9234212ea..3284c9e1b 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -806,6 +806,12 @@ A short description of the meaning and intended usage of the input field. # Third party packages +## drf-yasg - Yet Another Swagger Generator + +[drf-yasg][drf-yasg] generates [OpenAPI][open-api] documents suitable for code generation - nested schemas, +named models, response bodies, enum/pattern/min/max validators, form parameters, etc. + + ## DRF OpenAPI [DRF OpenAPI][drf-openapi] renders the schema generated by Django Rest Framework @@ -815,6 +821,7 @@ in [OpenAPI][open-api] format. [cite]: https://blog.heroku.com/archives/2014/1/8/json_schema_for_heroku_platform_api [coreapi]: http://www.coreapi.org/ [corejson]: http://www.coreapi.org/specification/encoding/#core-json-encoding +[drf-yasg]: https://github.com/axnsan12/drf-yasg/ [open-api]: https://openapis.org/ [drf-openapi]: https://github.com/limdauto/drf_openapi [json-hyperschema]: http://json-schema.org/latest/json-schema-hypermedia.html diff --git a/docs/img/drf-yasg.png b/docs/img/drf-yasg.png new file mode 100644 index 0000000000000000000000000000000000000000..ed770a386825da2040d9958cc7f60cb3b8fd6c5e GIT binary patch literal 59949 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
l>MqR8Yn04&lC0m{Jf;51eYV=QNzWgoMN7_` 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 Date: Mon, 8 Jan 2018 01:19:08 -0800 Subject: [PATCH 041/520] Remove unused compat._resolve_model() (#5733) Last use removed in c674687782ef96a3bb8466b412e99debd3d04f00. --- rest_framework/compat.py | 29 ------------------- tests/test_utils.py | 62 ---------------------------------------- 2 files changed, 91 deletions(-) diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 9870fe77e..88a76000e 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -5,14 +5,9 @@ versions of Django/Python, and compatibility wrappers around optional packages. from __future__ import unicode_literals -import inspect - import django -from django.apps import apps from django.conf import settings from django.core import validators -from django.core.exceptions import ImproperlyConfigured -from django.db import models from django.utils import six from django.views.generic import View @@ -107,30 +102,6 @@ def distinct(queryset, base): return queryset.distinct() -def _resolve_model(obj): - """ - Resolve supplied `obj` to a Django model class. - - `obj` must be a Django model class itself, or a string - representation of one. Useful in situations like GH #1225 where - Django may not have resolved a string-based reference to a model in - another model's foreign key definition. - - String representations should have the format: - 'appname.ModelName' - """ - if isinstance(obj, six.string_types) and len(obj.split('.')) == 2: - app_name, model_name = obj.split('.') - resolved_model = apps.get_model(app_name, model_name) - if resolved_model is None: - msg = "Django did not return a model for {0}.{1}" - raise ImproperlyConfigured(msg.format(app_name, model_name)) - return resolved_model - elif inspect.isclass(obj) and issubclass(obj, models.Model): - return obj - raise ValueError("{0} is not a Django model".format(obj)) - - # django.contrib.postgres requires psycopg2 try: from django.contrib.postgres import fields as postgres_fields diff --git a/tests/test_utils.py b/tests/test_utils.py index 4aed5ee73..d63f266d6 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -2,12 +2,8 @@ from __future__ import unicode_literals from django.conf.urls import url -from django.core.exceptions import ImproperlyConfigured from django.test import TestCase, override_settings -from django.utils import six -import rest_framework.utils.model_meta -from rest_framework.compat import _resolve_model from rest_framework.routers import SimpleRouter from rest_framework.serializers import ModelSerializer from rest_framework.utils import json @@ -124,64 +120,6 @@ class BreadcrumbTests(TestCase): ] -class ResolveModelTests(TestCase): - """ - `_resolve_model` should return a Django model class given the - provided argument is a Django model class itself, or a properly - formatted string representation of one. - """ - def test_resolve_django_model(self): - resolved_model = _resolve_model(BasicModel) - assert resolved_model == BasicModel - - def test_resolve_string_representation(self): - resolved_model = _resolve_model('tests.BasicModel') - assert resolved_model == BasicModel - - def test_resolve_unicode_representation(self): - resolved_model = _resolve_model(six.text_type('tests.BasicModel')) - assert resolved_model == BasicModel - - def test_resolve_non_django_model(self): - with self.assertRaises(ValueError): - _resolve_model(TestCase) - - def test_resolve_improper_string_representation(self): - with self.assertRaises(ValueError): - _resolve_model('BasicModel') - - -class ResolveModelWithPatchedDjangoTests(TestCase): - """ - Test coverage for when Django's `get_model` returns `None`. - - Under certain circumstances Django may return `None` with `get_model`: - http://git.io/get-model-source - - It usually happens with circular imports so it is important that DRF - excepts early, otherwise fault happens downstream and is much more - difficult to debug. - - """ - - def setUp(self): - """Monkeypatch get_model.""" - self.get_model = rest_framework.compat.apps.get_model - - def get_model(app_label, model_name): - return None - - rest_framework.compat.apps.get_model = get_model - - def tearDown(self): - """Revert monkeypatching.""" - rest_framework.compat.apps.get_model = self.get_model - - def test_blows_up_if_model_does_not_resolve(self): - with self.assertRaises(ImproperlyConfigured): - _resolve_model('tests.BasicModel') - - class JsonFloatTests(TestCase): """ Internaly, wrapped json functions should adhere to strict float handling From c1848d765d284ea66b6137112eeb9163a1679f31 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 8 Jan 2018 01:45:29 -0800 Subject: [PATCH 042/520] Drop compat workaround for unsupported Python 3.2 (#5734) --- rest_framework/compat.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 88a76000e..c81fa6210 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -113,8 +113,7 @@ except ImportError: try: import coreapi import uritemplate -except (ImportError, SyntaxError): - # SyntaxError is possible under python 3.2 +except ImportError: coreapi = None uritemplate = None From ffe3dbb1b15f35295924f5c2f0513fc4c81d5e6e Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 8 Jan 2018 01:49:46 -0800 Subject: [PATCH 043/520] Perfer iter(dict) over iter(dict.keys()) (#5736) Calling dict.keys() is unnecessary. The two are functionally equivalent on modern Pythons. Inspired by Lennart Regebro's talk "Prehistoric Patterns in Python" from PyCon 2017. https://www.youtube.com/watch?v=V5-JH23Vk0I --- docs/api-guide/serializers.md | 2 +- rest_framework/fields.py | 2 +- rest_framework/filters.py | 2 +- rest_framework/relations.py | 2 +- rest_framework/renderers.py | 4 ++-- rest_framework/schemas/generators.py | 2 +- rest_framework/schemas/inspectors.py | 4 ++-- rest_framework/serializers.py | 18 +++++++++--------- rest_framework/test.py | 2 +- rest_framework/utils/html.py | 2 +- rest_framework/utils/mediatypes.py | 4 ++-- tests/test_bound_fields.py | 2 +- tests/test_fields.py | 4 ++-- tests/test_metadata.py | 2 +- tests/test_multitable_inheritance.py | 4 ++-- tests/test_one_to_one_with_inheritance.py | 2 +- tests/test_permissions.py | 6 +++--- tests/test_request.py | 4 ++-- tests/test_serializer_lists.py | 2 +- 19 files changed, 35 insertions(+), 35 deletions(-) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 140de0fe2..3c560d829 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -1083,7 +1083,7 @@ For example, if you wanted to be able to set which fields should be used by a se if fields is not None: # Drop any fields that are not specified in the `fields` argument. allowed = set(fields) - existing = set(self.fields.keys()) + existing = set(self.fields) for field_name in existing - allowed: self.fields.pop(field_name) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 9b88784c8..c8f189ed1 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1420,7 +1420,7 @@ class ChoiceField(Field): # Allows us to deal with eg. integer choices while supporting either # integer or string input, but still get the correct datatype out. self.choice_strings_to_values = { - six.text_type(key): key for key in self.choices.keys() + six.text_type(key): key for key in self.choices } choices = property(_get_choices, _set_choices) diff --git a/rest_framework/filters.py b/rest_framework/filters.py index d30135d2e..830d0a616 100644 --- a/rest_framework/filters.py +++ b/rest_framework/filters.py @@ -218,7 +218,7 @@ class OrderingFilter(BaseFilterBackend): ] valid_fields += [ (key, key.title().split('__')) - for key in queryset.query.annotations.keys() + for key in queryset.query.annotations ] else: valid_fields = [ diff --git a/rest_framework/relations.py b/rest_framework/relations.py index 22078e64a..c87b9299a 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -133,7 +133,7 @@ class RelatedField(Field): return CustomManyRelatedField(*args, **kwargs) """ list_kwargs = {'child_relation': cls(*args, **kwargs)} - for key in kwargs.keys(): + for key in kwargs: if key in MANY_RELATION_KWARGS: list_kwargs[key] = kwargs[key] return ManyRelatedField(**list_kwargs) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index f071e7b4d..a2db9f228 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -805,8 +805,8 @@ class AdminRenderer(BrowsableAPIRenderer): header = results style = 'detail' - columns = [key for key in header.keys() if key != 'url'] - details = [key for key in header.keys() if key != 'url'] + columns = [key for key in header if key != 'url'] + details = [key for key in header if key != 'url'] context['style'] = style context['columns'] = columns diff --git a/rest_framework/schemas/generators.py b/rest_framework/schemas/generators.py index 10af6ee04..880777918 100644 --- a/rest_framework/schemas/generators.py +++ b/rest_framework/schemas/generators.py @@ -228,7 +228,7 @@ class EndpointEnumerator(object): Return a list of the valid HTTP methods for this endpoint. """ if hasattr(callback, 'actions'): - actions = set(callback.actions.keys()) + actions = set(callback.actions) http_method_names = set(callback.cls.http_method_names) methods = [method.upper() for method in actions & http_method_names] else: diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py index b2a5320bd..2afef7a04 100644 --- a/rest_framework/schemas/inspectors.py +++ b/rest_framework/schemas/inspectors.py @@ -54,13 +54,13 @@ def field_to_schema(field): return coreschema.String(title=title, description=description) elif isinstance(field, serializers.MultipleChoiceField): return coreschema.Array( - items=coreschema.Enum(enum=list(field.choices.keys())), + items=coreschema.Enum(enum=list(field.choices)), title=title, description=description ) elif isinstance(field, serializers.ChoiceField): return coreschema.Enum( - enum=list(field.choices.keys()), + enum=list(field.choices), title=title, description=description ) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index e2ea0d744..57f916a17 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -1136,9 +1136,9 @@ class ModelSerializer(Serializer): """ return ( [model_info.pk.name] + - list(declared_fields.keys()) + - list(model_info.fields.keys()) + - list(model_info.forward_relations.keys()) + list(declared_fields) + + list(model_info.fields) + + list(model_info.forward_relations) ) # Methods for constructing serializer fields... @@ -1194,7 +1194,7 @@ class ModelSerializer(Serializer): 'error_messages', 'validators', 'allow_null', 'allow_blank', 'choices' } - for key in list(field_kwargs.keys()): + for key in list(field_kwargs): if key not in valid_kwargs: field_kwargs.pop(key) @@ -1364,7 +1364,7 @@ class ModelSerializer(Serializer): # Include each of the `unique_together` field names, # so long as all the field names are included on the serializer. - for parent_class in [model] + list(model._meta.parents.keys()): + for parent_class in [model] + list(model._meta.parents): for unique_together_list in parent_class._meta.unique_together: if set(field_names).issuperset(set(unique_together_list)): unique_constraint_names |= set(unique_together_list) @@ -1466,7 +1466,7 @@ class ModelSerializer(Serializer): """ model_class_inheritance_tree = ( [self.Meta.model] + - list(self.Meta.model._meta.parents.keys()) + list(self.Meta.model._meta.parents) ) # The field names we're passing though here only include fields @@ -1566,9 +1566,9 @@ class HyperlinkedModelSerializer(ModelSerializer): """ return ( [self.url_field_name] + - list(declared_fields.keys()) + - list(model_info.fields.keys()) + - list(model_info.forward_relations.keys()) + list(declared_fields) + + list(model_info.fields) + + list(model_info.forward_relations) ) def build_nested_field(self, field_name, relation_info, nested_depth): diff --git a/rest_framework/test.py b/rest_framework/test.py index 3b745bd62..c58df34c6 100644 --- a/rest_framework/test.py +++ b/rest_framework/test.py @@ -175,7 +175,7 @@ class APIRequestFactory(DjangoRequestFactory): "Set TEST_REQUEST_RENDERER_CLASSES to enable " "extra request formats.".format( format, - ', '.join(["'" + fmt + "'" for fmt in self.renderer_classes.keys()]) + ', '.join(["'" + fmt + "'" for fmt in self.renderer_classes]) ) ) diff --git a/rest_framework/utils/html.py b/rest_framework/utils/html.py index ca062c9fc..77167e470 100644 --- a/rest_framework/utils/html.py +++ b/rest_framework/utils/html.py @@ -59,7 +59,7 @@ def parse_html_list(dictionary, prefix=''): ret[index][key] = value else: ret[index] = MultiValueDict({key: [value]}) - return [ret[item] for item in sorted(ret.keys())] + return [ret[item] for item in sorted(ret)] def parse_html_dict(dictionary, prefix=''): diff --git a/rest_framework/utils/mediatypes.py b/rest_framework/utils/mediatypes.py index 9fe3da05b..7d9d24f2b 100644 --- a/rest_framework/utils/mediatypes.py +++ b/rest_framework/utils/mediatypes.py @@ -55,7 +55,7 @@ class _MediaType(object): def match(self, other): """Return true if this MediaType satisfies the given MediaType.""" - for key in self.params.keys(): + for key in self.params: if key != 'q' and other.params.get(key, None) != self.params.get(key, None): return False @@ -76,7 +76,7 @@ class _MediaType(object): return 0 elif self.sub_type == '*': return 1 - elif not self.params or list(self.params.keys()) == ['q']: + elif not self.params or list(self.params) == ['q']: return 2 return 3 diff --git a/tests/test_bound_fields.py b/tests/test_bound_fields.py index e90e65edf..4cb75dc2c 100644 --- a/tests/test_bound_fields.py +++ b/tests/test_bound_fields.py @@ -54,7 +54,7 @@ class TestSimpleBoundField: serializer = ExampleSerializer() del serializer.fields['text'] - assert 'text' not in serializer.fields.keys() + assert 'text' not in serializer.fields def test_as_form_fields(self): class ExampleSerializer(serializers.Serializer): diff --git a/tests/test_fields.py b/tests/test_fields.py index bc11cd133..fd12a33f9 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -401,7 +401,7 @@ class TestHTMLInput: serializer = TestSerializer(data=QueryDict('message=')) assert serializer.is_valid() - assert list(serializer.validated_data.keys()) == ['message'] + assert list(serializer.validated_data) == ['message'] def test_empty_html_uuidfield_with_optional(self): class TestSerializer(serializers.Serializer): @@ -409,7 +409,7 @@ class TestHTMLInput: serializer = TestSerializer(data=QueryDict('message=')) assert serializer.is_valid() - assert list(serializer.validated_data.keys()) == [] + assert list(serializer.validated_data) == [] def test_empty_html_charfield_allow_null(self): class TestSerializer(serializers.Serializer): diff --git a/tests/test_metadata.py b/tests/test_metadata.py index b9db36e81..647a30dbd 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -207,7 +207,7 @@ class TestMetadata: view = ExampleView.as_view() response = view(request=request) assert response.status_code == status.HTTP_200_OK - assert list(response.data['actions'].keys()) == ['PUT'] + assert list(response.data['actions']) == ['PUT'] def test_object_permissions(self): """ diff --git a/tests/test_multitable_inheritance.py b/tests/test_multitable_inheritance.py index c406fceda..2ddd37ebb 100644 --- a/tests/test_multitable_inheritance.py +++ b/tests/test_multitable_inheritance.py @@ -44,7 +44,7 @@ class InheritedModelSerializationTests(TestCase): """ child = ChildModel(name1='parent name', name2='child name') serializer = DerivedModelSerializer(child) - assert set(serializer.data.keys()) == {'name1', 'name2', 'id'} + assert set(serializer.data) == {'name1', 'name2', 'id'} def test_onetoone_primary_key_model_fields_as_expected(self): """ @@ -54,7 +54,7 @@ class InheritedModelSerializationTests(TestCase): parent = ParentModel.objects.create(name1='parent name') associate = AssociatedModel.objects.create(name='hello', ref=parent) serializer = AssociatedModelSerializer(associate) - assert set(serializer.data.keys()) == {'name', 'ref'} + assert set(serializer.data) == {'name', 'ref'} def test_data_is_valid_without_parent_ptr(self): """ diff --git a/tests/test_one_to_one_with_inheritance.py b/tests/test_one_to_one_with_inheritance.py index 4bc9cec0b..789c7fcb9 100644 --- a/tests/test_one_to_one_with_inheritance.py +++ b/tests/test_one_to_one_with_inheritance.py @@ -39,5 +39,5 @@ class InheritedModelSerializationTests(TestCase): """ child = ChildModel(name1='parent name', name2='child name') serializer = DerivedModelSerializer(child) - self.assertEqual(set(serializer.data.keys()), + self.assertEqual(set(serializer.data), {'name1', 'name2', 'id', 'childassociatedmodel'}) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 5d7cb20ea..80b666180 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -151,7 +151,7 @@ class ModelPermissionsIntegrationTests(TestCase): response = root_view(request, pk='1') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIn('actions', response.data) - self.assertEqual(list(response.data['actions'].keys()), ['POST']) + self.assertEqual(list(response.data['actions']), ['POST']) request = factory.options( '/1', @@ -160,7 +160,7 @@ class ModelPermissionsIntegrationTests(TestCase): response = instance_view(request, pk='1') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIn('actions', response.data) - self.assertEqual(list(response.data['actions'].keys()), ['PUT']) + self.assertEqual(list(response.data['actions']), ['PUT']) def test_options_disallowed(self): request = factory.options( @@ -195,7 +195,7 @@ class ModelPermissionsIntegrationTests(TestCase): response = instance_view(request, pk='1') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertIn('actions', response.data) - self.assertEqual(list(response.data['actions'].keys()), ['PUT']) + self.assertEqual(list(response.data['actions']), ['PUT']) def test_empty_view_does_not_assert(self): request = factory.get('/1', HTTP_AUTHORIZATION=self.permitted_credentials) diff --git a/tests/test_request.py b/tests/test_request.py index 76589a440..8c680baa0 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -103,8 +103,8 @@ class TestContentParsing(TestCase): upload = SimpleUploadedFile("file.txt", b"file_content") request = Request(factory.post('/', {'upload': upload})) request.parsers = (FormParser(), MultiPartParser()) - assert list(request.POST.keys()) == [] - assert list(request.FILES.keys()) == ['upload'] + assert list(request.POST) == [] + assert list(request.FILES) == ['upload'] def test_standard_behaviour_determines_form_content_PUT(self): """ diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py index a7955d83c..34c3d100b 100644 --- a/tests/test_serializer_lists.py +++ b/tests/test_serializer_lists.py @@ -15,7 +15,7 @@ class BasicObject: def __eq__(self, other): if self._data.keys() != other._data.keys(): return False - for key in self._data.keys(): + for key in self._data: if self._data[key] != other._data[key]: return False return True From b2ec681d8d4c5a4a5ff3febb43449be5eea07883 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Wed, 10 Jan 2018 23:51:34 -0800 Subject: [PATCH 044/520] Pass python_requires argument to setuptools (#5739) Helps pip decide what version of the library to install. https://packaging.python.org/tutorials/distributing-packages/#python-requires > If your project only runs on certain Python versions, setting the > python_requires argument to the appropriate PEP 440 version specifier > string will prevent pip from installing the project on other Python > versions. https://setuptools.readthedocs.io/en/latest/setuptools.html#new-and-changed-setup-keywords > python_requires > > A string corresponding to a version specifier (as defined in PEP 440) > for the Python version, used to specify the Requires-Python defined in > PEP 345. --- docs/topics/project-management.md | 5 +++++ setup.py | 1 + 2 files changed, 6 insertions(+) diff --git a/docs/topics/project-management.md b/docs/topics/project-management.md index cc86c968a..fe8baf774 100644 --- a/docs/topics/project-management.md +++ b/docs/topics/project-management.md @@ -105,6 +105,11 @@ The following template should be used for the description of the issue, and serv Checklist: - [ ] Create pull request for [release notes](https://github.com/encode/django-rest-framework/blob/master/docs/topics/release-notes.md) based on the [*.*.* milestone](https://github.com/encode/django-rest-framework/milestones/***). + - [ ] Update supported versions: + - [ ] `setup.py` `python_requires` list + - [ ] `setup.py` Python & Django version trove classifiers + - [ ] `README` Python & Django versions + - [ ] `docs` Python & Django versions - [ ] Update the translations from [transifex](http://www.django-rest-framework.org/topics/project-management/#translations). - [ ] Ensure the pull request increments the version to `*.*.*` in [`restframework/__init__.py`](https://github.com/encode/django-rest-framework/blob/master/rest_framework/__init__.py). - [ ] Confirm with @tomchristie that release is finalized and ready to go. diff --git a/setup.py b/setup.py index 9223facc9..f2304b9d1 100755 --- a/setup.py +++ b/setup.py @@ -62,6 +62,7 @@ setup( packages=find_packages(exclude=['tests*']), include_package_data=True, install_requires=[], + python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", zip_safe=False, classifiers=[ 'Development Status :: 5 - Production/Stable', From d5c34aa8130164ecf07a786668a1272ddcf483af Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 15 Jan 2018 06:03:44 -0800 Subject: [PATCH 045/520] Remove unused links from docs (#5735) Each removed link has no inline use. --- docs/api-guide/authentication.md | 5 ----- docs/api-guide/caching.md | 2 -- docs/api-guide/fields.md | 2 -- docs/api-guide/filtering.md | 2 -- docs/api-guide/pagination.md | 1 - docs/api-guide/permissions.md | 3 --- docs/api-guide/relations.md | 1 - docs/index.md | 8 -------- docs/topics/2.2-announcement.md | 1 - docs/topics/browsable-api.md | 2 -- docs/topics/internationalization.md | 1 - docs/topics/release-notes.md | 10 ---------- docs/topics/rest-framework-2-announcement.md | 1 - docs/topics/rest-hypermedia-hateoas.md | 1 - docs/tutorial/quickstart.md | 1 - 15 files changed, 41 deletions(-) diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 63a789dfc..d7f2954b6 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -407,7 +407,6 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a [http401]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 [http403]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4 [basicauth]: http://tools.ietf.org/html/rfc2617 -[oauth]: http://oauth.net/2/ [permission]: permissions.md [throttling]: throttling.md [csrf-ajax]: https://docs.djangoproject.com/en/stable/ref/csrf/#ajax @@ -419,10 +418,6 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a [juanriaza]: https://github.com/juanriaza [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth [oauth-1.0a]: http://oauth.net/core/1.0a -[django-oauth-plus]: http://code.larlet.fr/django-oauth-plus -[django-oauth2-provider]: https://github.com/caffeinehit/django-oauth2-provider -[django-oauth2-provider-docs]: https://django-oauth2-provider.readthedocs.io/en/latest/ -[rfc6749]: http://tools.ietf.org/html/rfc6749 [django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit [evonove]: https://github.com/evonove/ [oauthlib]: https://github.com/idan/oauthlib diff --git a/docs/api-guide/caching.md b/docs/api-guide/caching.md index ed3f62c21..ff51aed06 100644 --- a/docs/api-guide/caching.md +++ b/docs/api-guide/caching.md @@ -47,8 +47,6 @@ class PostView(APIView): **NOTE:** The [`cache_page`][page] decorator only caches the `GET` and `HEAD` responses with status 200. - -[django]: https://docs.djangoproject.com/en/dev/topics/cache/ [page]: https://docs.djangoproject.com/en/dev/topics/cache/#the-per-view-cache [cookie]: https://docs.djangoproject.com/en/dev/topics/http/decorators/#django.views.decorators.vary.vary_on_cookie [decorator]: https://docs.djangoproject.com/en/dev/topics/class-based-views/intro/#decorating-the-class diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index a2f10ed19..684ae517d 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -806,9 +806,7 @@ The [django-rest-framework-hstore][django-rest-framework-hstore] package provide [cite]: https://docs.djangoproject.com/en/stable/ref/forms/api/#django.forms.Form.cleaned_data [html-and-forms]: ../topics/html-and-forms.md [FILE_UPLOAD_HANDLERS]: https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-FILE_UPLOAD_HANDLERS -[ecma262]: http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.15 [strftime]: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior -[django-widgets]: https://docs.djangoproject.com/en/stable/ref/forms/widgets/ [iso8601]: http://www.w3.org/TR/NOTE-datetime [drf-compound-fields]: https://drf-compound-fields.readthedocs.io [drf-extra-fields]: https://github.com/Hipo/drf-extra-fields diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 93a142755..83cbe7d1b 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -379,13 +379,11 @@ The [djangorestframework-word-filter][django-rest-framework-word-search-filter] [drf-url-filter][drf-url-filter] is a simple Django app to apply filters on drf `ModelViewSet`'s `Queryset` in a clean, simple and configurable way. It also supports validations on incoming query params and their values. A beautiful python package `Voluptuous` is being used for validations on the incoming query parameters. The best part about voluptuous is you can define your own validations as per your query params requirements. [cite]: https://docs.djangoproject.com/en/stable/topics/db/queries/#retrieving-specific-objects-with-filters -[django-filter]: https://github.com/alex/django-filter [django-filter-docs]: https://django-filter.readthedocs.io/en/latest/index.html [django-filter-drf-docs]: https://django-filter.readthedocs.io/en/latest/guide/rest_framework.html [guardian]: https://django-guardian.readthedocs.io/ [view-permissions]: https://django-guardian.readthedocs.io/en/latest/userguide/assign.html [view-permissions-blogpost]: http://blog.nyaruka.com/adding-a-view-permission-to-django-models -[nullbooleanselect]: https://github.com/django/django/blob/master/django/forms/widgets.py [search-django-admin]: https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields [django-rest-framework-filters]: https://github.com/philipn/django-rest-framework-filters [django-rest-framework-word-search-filter]: https://github.com/trollknurr/django-rest-framework-word-search-filter diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index b28f1616d..0f123cb89 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -314,7 +314,6 @@ The [`drf-proxy-pagination` package][drf-proxy-pagination] includes a `ProxyPagi The [`django-rest-framework-link-header-pagination` package][drf-link-header-pagination] includes a `LinkHeaderPagination` class which provides pagination via an HTTP `Link` header as desribed in [Github's developer documentation](github-link-pagination). [cite]: https://docs.djangoproject.com/en/stable/topics/pagination/ -[github-link-pagination]: https://developer.github.com/guides/traversing-with-pagination/ [link-header]: ../img/link-header-pagination.png [drf-extensions]: http://chibisov.github.io/drf-extensions/docs/ [paginate-by-max-mixin]: http://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 0a3d0ef65..72cbeab91 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -276,10 +276,7 @@ The [Django Rest Framework API Key][django-rest-framework-api-key] package allow [contribauth]: https://docs.djangoproject.com/en/stable/topics/auth/customizing/#custom-permissions [objectpermissions]: https://docs.djangoproject.com/en/stable/topics/auth/customizing/#handling-object-permissions [guardian]: https://github.com/lukaszb/django-guardian -[get_objects_for_user]: http://pythonhosted.org/django-guardian/api/guardian.shortcuts.html#get-objects-for-user -[2.2-announcement]: ../topics/2.2-announcement.md [filtering]: filtering.md -[drf-any-permissions]: https://github.com/kevin-brown/drf-any-permissions [composed-permissions]: https://github.com/niwibe/djangorestframework-composed-permissions [rest-condition]: https://github.com/caxap/rest_condition [dry-rest-permissions]: https://github.com/Helioscene/dry-rest-permissions diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 662fd4809..ce249c32f 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -596,6 +596,5 @@ The [rest-framework-generic-relations][drf-nested-relations] library provides re [reverse-relationships]: https://docs.djangoproject.com/en/stable/topics/db/queries/#following-relationships-backward [routers]: http://www.django-rest-framework.org/api-guide/routers#defaultrouter [generic-relations]: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#id1 -[2.2-announcement]: ../topics/2.2-announcement.md [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers [drf-nested-relations]: https://github.com/Ian-Foote/rest-framework-generic-relations diff --git a/docs/index.md b/docs/index.md index 0b544e5bf..fe0ec3a96 100644 --- a/docs/index.md +++ b/docs/index.md @@ -311,8 +311,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [django-filter]: http://pypi.python.org/pypi/django-filter [django-crispy-forms]: https://github.com/maraujop/django-crispy-forms [django-guardian]: https://github.com/django-guardian/django-guardian -[0.4]: https://github.com/encode/django-rest-framework/tree/0.4.X -[image]: img/quickstart.png [index]: . [oauth1-section]: api-guide/authentication/#django-rest-framework-oauth [oauth2-section]: api-guide/authentication/#django-oauth-toolkit @@ -385,15 +383,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [release-notes]: topics/release-notes.md [jobs]: topics/jobs.md -[tox]: http://testrun.org/tox/latest/ - [group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework [botbot]: https://botbot.me/freenode/restframework/ [stack-overflow]: http://stackoverflow.com/ [django-rest-framework-tag]: http://stackoverflow.com/questions/tagged/django-rest-framework -[django-tag]: http://stackoverflow.com/questions/tagged/django [security-mail]: mailto:rest-framework-security@googlegroups.com -[paid-support]: http://dabapps.com/services/build/api-development/ -[dabapps]: http://dabapps.com -[contact-dabapps]: http://dabapps.com/contact/ [twitter]: https://twitter.com/_tomchristie diff --git a/docs/topics/2.2-announcement.md b/docs/topics/2.2-announcement.md index 2d743af24..e945188b9 100644 --- a/docs/topics/2.2-announcement.md +++ b/docs/topics/2.2-announcement.md @@ -155,5 +155,4 @@ From version 2.2 onwards, serializers with hyperlinked relationships *always* re [mailing-list]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework [django-rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs [marcgibbons]: https://github.com/marcgibbons/ -[issues]: https://github.com/encode/django-rest-framework/issues [564]: https://github.com/encode/django-rest-framework/issues/564 diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md index a0ca6626b..ec4e6b000 100644 --- a/docs/topics/browsable-api.md +++ b/docs/topics/browsable-api.md @@ -155,10 +155,8 @@ There are [a variety of packages for autocomplete widgets][autocomplete-packages [bootstrap]: http://getbootstrap.com [cerulean]: ../img/cerulean.png [slate]: ../img/slate.png -[bcustomize]: http://getbootstrap.com/2.3.2/customize.html [bswatch]: http://bootswatch.com/ [bcomponents]: http://getbootstrap.com/2.3.2/components.html [bcomponentsnav]: http://getbootstrap.com/2.3.2/components.html#navbar [autocomplete-packages]: https://www.djangopackages.com/grids/g/auto-complete/ [django-autocomplete-light]: https://github.com/yourlabs/django-autocomplete-light -[django-autocomplete-light-install]: https://django-autocomplete-light.readthedocs.io/en/master/install.html diff --git a/docs/topics/internationalization.md b/docs/topics/internationalization.md index f7efbf697..fe85c6523 100644 --- a/docs/topics/internationalization.md +++ b/docs/topics/internationalization.md @@ -110,4 +110,3 @@ For API clients the most appropriate of these will typically be to use the `Acce [django-language-preference]: https://docs.djangoproject.com/en/1.7/topics/i18n/translation/#how-django-discovers-language-preference [django-locale-paths]: https://docs.djangoproject.com/en/1.7/ref/settings/#std:setting-LOCALE_PATHS [django-locale-name]: https://docs.djangoproject.com/en/1.7/topics/i18n/#term-locale-name -[contributing]: ../../CONTRIBUTING.md diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 244adef0b..128175ef5 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -892,13 +892,6 @@ For older release notes, [please see the version 2.x documentation][old-release- [cite]: http://www.catb.org/~esr/writings/cathedral-bazaar/cathedral-bazaar/ar01s04.html [deprecation-policy]: #deprecation-policy [django-deprecation-policy]: https://docs.djangoproject.com/en/stable/internals/release-process/#internal-release-deprecation-policy -[defusedxml-announce]: http://blog.python.org/2013/02/announcing-defusedxml-fixes-for-xml.html -[743]: https://github.com/encode/django-rest-framework/pull/743 -[staticfiles14]: https://docs.djangoproject.com/en/1.4/howto/static-files/#with-a-template-tag -[staticfiles13]: https://docs.djangoproject.com/en/1.3/howto/static-files/#with-a-template-tag -[2.1.0-notes]: https://groups.google.com/d/topic/django-rest-framework/Vv2M0CMY9bg/discussion -[ticket-582]: https://github.com/encode/django-rest-framework/issues/582 -[rfc-6266]: http://tools.ietf.org/html/rfc6266#section-4.3 [old-release-notes]: https://github.com/encode/django-rest-framework/blob/version-2.4.x/docs/topics/release-notes.md [3.6-release]: 3.6-announcement.md @@ -1153,7 +1146,6 @@ For older release notes, [please see the version 2.x documentation][old-release- [gh3249]: https://github.com/encode/django-rest-framework/issues/3249 [gh3250]: https://github.com/encode/django-rest-framework/issues/3250 [gh3275]: https://github.com/encode/django-rest-framework/issues/3275 -[gh3288]: https://github.com/encode/django-rest-framework/issues/3288 [gh3290]: https://github.com/encode/django-rest-framework/issues/3290 [gh3303]: https://github.com/encode/django-rest-framework/issues/3303 [gh3313]: https://github.com/encode/django-rest-framework/issues/3313 @@ -1410,7 +1402,6 @@ For older release notes, [please see the version 2.x documentation][old-release- -[gh2829]: https://github.com/encode/django-rest-framework/issues/2829 [gh3329]: https://github.com/encode/django-rest-framework/issues/3329 [gh3330]: https://github.com/encode/django-rest-framework/issues/3330 [gh3365]: https://github.com/encode/django-rest-framework/issues/3365 @@ -1651,7 +1642,6 @@ For older release notes, [please see the version 2.x documentation][old-release- [gh5457]: https://github.com/encode/django-rest-framework/issues/5457 [gh5376]: https://github.com/encode/django-rest-framework/issues/5376 [gh5422]: https://github.com/encode/django-rest-framework/issues/5422 -[gh5408]: https://github.com/encode/django-rest-framework/issues/5408 [gh3732]: https://github.com/encode/django-rest-framework/issues/3732 [djangodocs-set-timezone]: https://docs.djangoproject.com/en/1.11/topics/i18n/timezones/#default-time-zone-and-current-time-zone [gh5273]: https://github.com/encode/django-rest-framework/issues/5273 diff --git a/docs/topics/rest-framework-2-announcement.md b/docs/topics/rest-framework-2-announcement.md index ed41bb486..98194adfa 100644 --- a/docs/topics/rest-framework-2-announcement.md +++ b/docs/topics/rest-framework-2-announcement.md @@ -93,6 +93,5 @@ There's also a [live sandbox version of the tutorial API][sandbox] available for [quote2]: https://groups.google.com/d/msg/django-rest-framework/heRGHzG6BWQ/ooVURgpwVC0J [quote3]: https://groups.google.com/d/msg/django-rest-framework/flsXbvYqRoY/9lSyntOf5cUJ [image]: ../img/quickstart.png -[readthedocs]: https://readthedocs.org/ [tut]: ../tutorial/1-serialization.md [sandbox]: http://restframework.herokuapp.com/ diff --git a/docs/topics/rest-hypermedia-hateoas.md b/docs/topics/rest-hypermedia-hateoas.md index 5517b150c..4481254f4 100644 --- a/docs/topics/rest-hypermedia-hateoas.md +++ b/docs/topics/rest-hypermedia-hateoas.md @@ -40,7 +40,6 @@ What REST framework doesn't do is give you machine readable hypermedia formats s [restful-web-apis]: http://restfulwebapis.org/ [building-hypermedia-apis]: http://www.amazon.com/Building-Hypermedia-APIs-HTML5-Node/dp/1449306578 [designing-hypermedia-apis]: http://designinghypermediaapis.com/ -[restisover]: http://blog.steveklabnik.com/posts/2012-02-23-rest-is-over [readinglist]: http://blog.steveklabnik.com/posts/2012-02-27-hypermedia-api-reading-list [maturitymodel]: http://martinfowler.com/articles/richardsonMaturityModel.html diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index ab789518d..35d5642c7 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -211,7 +211,6 @@ Great, that was easy! If you want to get a more in depth understanding of how REST framework fits together head on over to [the tutorial][tutorial], or start browsing the [API guide][guide]. -[readme-example-api]: ../#example [image]: ../img/quickstart.png [tutorial]: 1-serialization.md [guide]: ../#api-guide From d3f3c3d9c1b91e9fcc72874d33c004f8ed7fa7fe Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 8 Jan 2018 07:22:32 -0800 Subject: [PATCH 046/520] Prefer https protocol for links in docs when available --- CONTRIBUTING.md | 8 ++-- README.md | 8 ++-- docs/api-guide/authentication.md | 22 +++++----- docs/api-guide/content-negotiation.md | 4 +- docs/api-guide/fields.md | 2 +- docs/api-guide/filtering.md | 2 +- docs/api-guide/metadata.md | 2 +- docs/api-guide/pagination.md | 4 +- docs/api-guide/parsers.md | 6 +-- docs/api-guide/relations.md | 2 +- docs/api-guide/renderers.md | 20 ++++----- docs/api-guide/reverse.md | 2 +- docs/api-guide/routers.md | 14 +++---- docs/api-guide/serializers.md | 8 ++-- docs/api-guide/settings.md | 2 +- docs/api-guide/status-codes.md | 6 +-- docs/api-guide/testing.md | 2 +- docs/api-guide/throttling.md | 2 +- docs/api-guide/versioning.md | 8 ++-- docs/api-guide/views.md | 2 +- docs/index.md | 20 ++++----- docs/topics/2.4-announcement.md | 4 +- docs/topics/3.0-announcement.md | 4 +- docs/topics/3.1-announcement.md | 8 ++-- docs/topics/3.5-announcement.md | 8 ++-- docs/topics/ajax-csrf-cors.md | 4 +- docs/topics/browsable-api.md | 12 +++--- docs/topics/browser-enhancements.md | 4 +- docs/topics/contributing.md | 8 ++-- docs/topics/documenting-your-api.md | 6 +-- docs/topics/internationalization.md | 4 +- docs/topics/jobs.md | 4 +- docs/topics/kickstarter-announcement.md | 42 +++++++++---------- docs/topics/mozilla-grant.md | 2 +- docs/topics/project-management.md | 4 +- docs/topics/rest-framework-2-announcement.md | 2 +- docs/topics/rest-hypermedia-hateoas.md | 8 ++-- docs/topics/third-party-packages.md | 4 +- docs/topics/tutorials-and-resources.md | 24 +++++------ docs/tutorial/1-serialization.md | 4 +- docs/tutorial/3-class-based-views.md | 2 +- .../7-schemas-and-client-libraries.md | 2 +- licenses/jquery.json-view.md | 2 +- rest_framework/compat.py | 2 +- rest_framework/parsers.py | 2 +- rest_framework/renderers.py | 2 +- rest_framework/status.py | 4 +- rest_framework/templatetags/rest_framework.py | 2 +- rest_framework/utils/encoders.py | 2 +- rest_framework/utils/mediatypes.py | 2 +- 50 files changed, 162 insertions(+), 162 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ba579568d..29ba53955 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -194,14 +194,14 @@ If you want to draw attention to a note or warning, use a pair of enclosing line --- -[cite]: http://www.w3.org/People/Berners-Lee/FAQ.html +[cite]: https://www.w3.org/People/Berners-Lee/FAQ.html [code-of-conduct]: https://www.djangoproject.com/conduct/ [google-group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework -[so-filter]: http://stackexchange.com/filters/66475/rest-framework +[so-filter]: https://stackexchange.com/filters/66475/rest-framework [issues]: https://github.com/encode/django-rest-framework/issues?state=open -[pep-8]: http://www.python.org/dev/peps/pep-0008/ +[pep-8]: https://www.python.org/dev/peps/pep-0008/ [pull-requests]: https://help.github.com/articles/using-pull-requests [tox]: https://tox.readthedocs.io/en/latest/ -[markdown]: http://daringfireball.net/projects/markdown/basics +[markdown]: https://daringfireball.net/projects/markdown/basics [docs]: https://github.com/encode/django-rest-framework/tree/master/docs [mou]: http://mouapp.com/ diff --git a/README.md b/README.md index 92aad7499..7a5e4f0b7 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ That's it, we're done! You can now open the API in your browser at `http://127.0.0.1:8000/`, and view your new 'users' API. If you use the `Login` control in the top right corner you'll also be able to add, create and delete users from the system. -You can also interact with the API using command line tools such as [`curl`](http://curl.haxx.se/). For example, to list the users endpoint: +You can also interact with the API using command line tools such as [`curl`](https://curl.haxx.se/). For example, to list the users endpoint: $ curl -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/ [ @@ -176,14 +176,14 @@ If you believe you've found something in Django REST framework which has securit Send a description of the issue via email to [rest-framework-security@googlegroups.com][security-mail]. The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure. [build-status-image]: https://secure.travis-ci.org/encode/django-rest-framework.svg?branch=master -[travis]: http://travis-ci.org/encode/django-rest-framework?branch=master +[travis]: https://travis-ci.org/encode/django-rest-framework?branch=master [coverage-status-image]: https://img.shields.io/codecov/c/github/encode/django-rest-framework/master.svg -[codecov]: http://codecov.io/github/encode/django-rest-framework?branch=master +[codecov]: https://codecov.io/github/encode/django-rest-framework?branch=master [pypi-version]: https://img.shields.io/pypi/v/djangorestframework.svg [pypi]: https://pypi.python.org/pypi/djangorestframework [twitter]: https://twitter.com/_tomchristie [group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework -[sandbox]: http://restframework.herokuapp.com/ +[sandbox]: https://restframework.herokuapp.com/ [funding]: https://fund.django-rest-framework.org/topics/funding/ [sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index d7f2954b6..0704118bd 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -403,21 +403,21 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a [drfpasswordless][drfpasswordless] adds (Medium, Square Cash inspired) passwordless support to Django REST Framework's own TokenAuthentication scheme. Users log in and sign up with a token sent to a contact point like an email address or a mobile number. -[cite]: http://jacobian.org/writing/rest-worst-practices/ -[http401]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 -[http403]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4 -[basicauth]: http://tools.ietf.org/html/rfc2617 +[cite]: https://jacobian.org/writing/rest-worst-practices/ +[http401]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 +[http403]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4 +[basicauth]: https://tools.ietf.org/html/rfc2617 [permission]: permissions.md [throttling]: throttling.md [csrf-ajax]: https://docs.djangoproject.com/en/stable/ref/csrf/#ajax -[mod_wsgi_official]: http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIPassAuthorization +[mod_wsgi_official]: https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIPassAuthorization.html [django-oauth-toolkit-getting-started]: https://django-oauth-toolkit.readthedocs.io/en/latest/rest-framework/getting_started.html -[django-rest-framework-oauth]: http://jpadilla.github.io/django-rest-framework-oauth/ -[django-rest-framework-oauth-authentication]: http://jpadilla.github.io/django-rest-framework-oauth/authentication/ -[django-rest-framework-oauth-permissions]: http://jpadilla.github.io/django-rest-framework-oauth/permissions/ +[django-rest-framework-oauth]: https://jpadilla.github.io/django-rest-framework-oauth/ +[django-rest-framework-oauth-authentication]: https://jpadilla.github.io/django-rest-framework-oauth/authentication/ +[django-rest-framework-oauth-permissions]: https://jpadilla.github.io/django-rest-framework-oauth/permissions/ [juanriaza]: https://github.com/juanriaza [djangorestframework-digestauth]: https://github.com/juanriaza/django-rest-framework-digestauth -[oauth-1.0a]: http://oauth.net/core/1.0a +[oauth-1.0a]: https://oauth.net/core/1.0a/ [django-oauth-toolkit]: https://github.com/evonove/django-oauth-toolkit [evonove]: https://github.com/evonove/ [oauthlib]: https://github.com/idan/oauthlib @@ -429,12 +429,12 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a [djangorestframework-simplejwt]: https://github.com/davesque/django-rest-framework-simplejwt [etoccalino]: https://github.com/etoccalino/ [djangorestframework-httpsignature]: https://github.com/etoccalino/django-rest-framework-httpsignature -[amazon-http-signature]: http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html +[amazon-http-signature]: https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html [http-signature-ietf-draft]: https://datatracker.ietf.org/doc/draft-cavage-http-signatures/ [hawkrest]: https://hawkrest.readthedocs.io/en/latest/ [hawk]: https://github.com/hueniverse/hawk [mohawk]: https://mohawk.readthedocs.io/en/latest/ -[mac]: http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05 +[mac]: https://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05 [djoser]: https://github.com/sunscrapers/djoser [django-rest-auth]: https://github.com/Tivix/django-rest-auth [django-rest-framework-social-oauth2]: https://github.com/PhilipGarnero/django-rest-framework-social-oauth2 diff --git a/docs/api-guide/content-negotiation.md b/docs/api-guide/content-negotiation.md index bd408feba..8112a2e80 100644 --- a/docs/api-guide/content-negotiation.md +++ b/docs/api-guide/content-negotiation.md @@ -6,7 +6,7 @@ source: negotiation.py > > — [RFC 2616][cite], Fielding et al. -[cite]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html +[cite]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html Content negotiation is the process of selecting one of multiple possible representations to return to a client, based on client or server preferences. @@ -94,4 +94,4 @@ You can also set the content negotiation used for an individual view, or viewset 'accepted media type': request.accepted_renderer.media_type }) -[accept-header]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html +[accept-header]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 684ae517d..bf5fc0ca7 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -807,7 +807,7 @@ The [django-rest-framework-hstore][django-rest-framework-hstore] package provide [html-and-forms]: ../topics/html-and-forms.md [FILE_UPLOAD_HANDLERS]: https://docs.djangoproject.com/en/stable/ref/settings/#std:setting-FILE_UPLOAD_HANDLERS [strftime]: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior -[iso8601]: http://www.w3.org/TR/NOTE-datetime +[iso8601]: https://www.w3.org/TR/NOTE-datetime [drf-compound-fields]: https://drf-compound-fields.readthedocs.io [drf-extra-fields]: https://github.com/Hipo/drf-extra-fields [djangorestframework-recursive]: https://github.com/heywbj/django-rest-framework-recursive diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 83cbe7d1b..723b2fb35 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -383,7 +383,7 @@ The [djangorestframework-word-filter][django-rest-framework-word-search-filter] [django-filter-drf-docs]: https://django-filter.readthedocs.io/en/latest/guide/rest_framework.html [guardian]: https://django-guardian.readthedocs.io/ [view-permissions]: https://django-guardian.readthedocs.io/en/latest/userguide/assign.html -[view-permissions-blogpost]: http://blog.nyaruka.com/adding-a-view-permission-to-django-models +[view-permissions-blogpost]: https://blog.nyaruka.com/adding-a-view-permission-to-django-models [search-django-admin]: https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields [django-rest-framework-filters]: https://github.com/philipn/django-rest-framework-filters [django-rest-framework-word-search-filter]: https://github.com/trollknurr/django-rest-framework-word-search-filter diff --git a/docs/api-guide/metadata.md b/docs/api-guide/metadata.md index de28ffd8a..d5c3c1a67 100644 --- a/docs/api-guide/metadata.md +++ b/docs/api-guide/metadata.md @@ -115,7 +115,7 @@ The following third party packages provide additional metadata implementations. You can also write your own adapter to work with your specific frontend. If you wish to do so, it also provides an exporter that can export those schema information to json files. -[cite]: http://tools.ietf.org/html/rfc7231#section-4.3.7 +[cite]: https://tools.ietf.org/html/rfc7231#section-4.3.7 [no-options]: https://www.mnot.net/blog/2012/10/29/NO_OPTIONS [json-schema]: http://json-schema.org/ [drf-schema-adapter]: https://github.com/drf-forms/drf-schema-adapter diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index 0f123cb89..658e94d91 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -315,8 +315,8 @@ The [`django-rest-framework-link-header-pagination` package][drf-link-header-pag [cite]: https://docs.djangoproject.com/en/stable/topics/pagination/ [link-header]: ../img/link-header-pagination.png -[drf-extensions]: http://chibisov.github.io/drf-extensions/docs/ -[paginate-by-max-mixin]: http://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin +[drf-extensions]: https://chibisov.github.io/drf-extensions/docs/ +[paginate-by-max-mixin]: https://chibisov.github.io/drf-extensions/docs/#paginatebymaxmixin [drf-proxy-pagination]: https://github.com/tuffnatty/drf-proxy-pagination [drf-link-header-pagination]: https://github.com/tbeadle/django-rest-framework-link-header-pagination [disqus-cursor-api]: http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api diff --git a/docs/api-guide/parsers.md b/docs/api-guide/parsers.md index cd5ef1a04..09ce4556f 100644 --- a/docs/api-guide/parsers.md +++ b/docs/api-guide/parsers.md @@ -223,11 +223,11 @@ Modify your REST framework settings. [djangorestframework-camel-case] provides camel case JSON renderers and parsers for REST framework. This allows serializers to use Python-style underscored field names, but be exposed in the API as Javascript-style camel case field names. It is maintained by [Vitaly Babiy][vbabiy]. -[jquery-ajax]: http://api.jquery.com/jQuery.ajax/ +[jquery-ajax]: https://api.jquery.com/jQuery.ajax/ [cite]: https://groups.google.com/d/topic/django-developers/dxI4qVzrBY4/discussion [upload-handlers]: https://docs.djangoproject.com/en/stable/topics/http/file-uploads/#upload-handlers -[rest-framework-yaml]: http://jpadilla.github.io/django-rest-framework-yaml/ -[rest-framework-xml]: http://jpadilla.github.io/django-rest-framework-xml/ +[rest-framework-yaml]: https://jpadilla.github.io/django-rest-framework-yaml/ +[rest-framework-xml]: https://jpadilla.github.io/django-rest-framework-xml/ [yaml]: http://www.yaml.org/ [messagepack]: https://github.com/juanriaza/django-rest-framework-msgpack [juanriaza]: https://github.com/juanriaza diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index ce249c32f..77649afd6 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -592,7 +592,7 @@ The [drf-nested-routers package][drf-nested-routers] provides routers and relati The [rest-framework-generic-relations][drf-nested-relations] library provides read/write serialization for generic foreign keys. -[cite]: http://lwn.net/Articles/193245/ +[cite]: https://lwn.net/Articles/193245/ [reverse-relationships]: https://docs.djangoproject.com/en/stable/topics/db/queries/#following-relationships-backward [routers]: http://www.django-rest-framework.org/api-guide/routers#defaultrouter [generic-relations]: https://docs.djangoproject.com/en/stable/ref/contrib/contenttypes/#id1 diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index 236504850..d547a7bbf 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -485,21 +485,21 @@ Comma-separated values are a plain-text tabular data format, that can be easily [testing]: testing.md [HATEOAS]: http://timelessrepo.com/haters-gonna-hateoas [quote]: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven -[application/vnd.github+json]: http://developer.github.com/v3/media/ +[application/vnd.github+json]: https://developer.github.com/v3/media/ [application/vnd.collection+json]: http://www.amundsen.com/media-types/collection/ [django-error-views]: https://docs.djangoproject.com/en/stable/topics/http/views/#customizing-error-views -[rest-framework-jsonp]: http://jpadilla.github.io/django-rest-framework-jsonp/ -[cors]: http://www.w3.org/TR/cors/ +[rest-framework-jsonp]: https://jpadilla.github.io/django-rest-framework-jsonp/ +[cors]: https://www.w3.org/TR/cors/ [cors-docs]: http://www.django-rest-framework.org/topics/ajax-csrf-cors/ -[jsonp-security]: http://stackoverflow.com/questions/613962/is-jsonp-safe-to-use -[rest-framework-yaml]: http://jpadilla.github.io/django-rest-framework-yaml/ -[rest-framework-xml]: http://jpadilla.github.io/django-rest-framework-xml/ -[messagepack]: http://msgpack.org/ +[jsonp-security]: https://stackoverflow.com/questions/613962/is-jsonp-safe-to-use +[rest-framework-yaml]: https://jpadilla.github.io/django-rest-framework-yaml/ +[rest-framework-xml]: https://jpadilla.github.io/django-rest-framework-xml/ +[messagepack]: https://msgpack.org/ [juanriaza]: https://github.com/juanriaza [mjumbewu]: https://github.com/mjumbewu [vbabiy]: https://github.com/vbabiy -[rest-framework-yaml]: http://jpadilla.github.io/django-rest-framework-yaml/ -[rest-framework-xml]: http://jpadilla.github.io/django-rest-framework-xml/ +[rest-framework-yaml]: https://jpadilla.github.io/django-rest-framework-yaml/ +[rest-framework-xml]: https://jpadilla.github.io/django-rest-framework-xml/ [yaml]: http://www.yaml.org/ [djangorestframework-msgpack]: https://github.com/juanriaza/django-rest-framework-msgpack [djangorestframework-csv]: https://github.com/mjumbewu/django-rest-framework-csv @@ -508,7 +508,7 @@ Comma-separated values are a plain-text tabular data format, that can be easily [drf-ujson-renderer]: https://github.com/gizmag/drf-ujson-renderer [djangorestframework-camel-case]: https://github.com/vbabiy/djangorestframework-camel-case [Django REST Pandas]: https://github.com/wq/django-rest-pandas -[Pandas]: http://pandas.pydata.org/ +[Pandas]: https://pandas.pydata.org/ [other formats]: https://github.com/wq/django-rest-pandas#supported-formats [sheppard]: https://github.com/sheppard [wq]: https://github.com/wq diff --git a/docs/api-guide/reverse.md b/docs/api-guide/reverse.md index ee0b2054f..00abcf571 100644 --- a/docs/api-guide/reverse.md +++ b/docs/api-guide/reverse.md @@ -50,6 +50,6 @@ As with the `reverse` function, you should **include the request as a keyword ar api_root = reverse_lazy('api-root', request=request) -[cite]: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5 +[cite]: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm#sec_5_1_5 [reverse]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse [reverse-lazy]: https://docs.djangoproject.com/en/stable/topics/http/urls/#reverse-lazy diff --git a/docs/api-guide/routers.md b/docs/api-guide/routers.md index 84ca82a3f..e4415df15 100644 --- a/docs/api-guide/routers.md +++ b/docs/api-guide/routers.md @@ -326,10 +326,10 @@ The [`DRF-extensions` package][drf-extensions] provides [routers][drf-extensions [cite]: http://guides.rubyonrails.org/routing.html [route-decorators]: viewsets.md#marking-extra-actions-for-routing [drf-nested-routers]: https://github.com/alanjds/drf-nested-routers -[wq.db]: http://wq.io/wq.db -[wq.db-router]: http://wq.io/docs/router -[drf-extensions]: http://chibisov.github.io/drf-extensions/docs/ -[drf-extensions-routers]: http://chibisov.github.io/drf-extensions/docs/#routers -[drf-extensions-nested-viewsets]: http://chibisov.github.io/drf-extensions/docs/#nested-routes -[drf-extensions-collection-level-controllers]: http://chibisov.github.io/drf-extensions/docs/#collection-level-controllers -[drf-extensions-customizable-endpoint-names]: http://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name +[wq.db]: https://wq.io/wq.db +[wq.db-router]: https://wq.io/docs/router +[drf-extensions]: https://chibisov.github.io/drf-extensions/docs/ +[drf-extensions-routers]: https://chibisov.github.io/drf-extensions/docs/#routers +[drf-extensions-nested-viewsets]: https://chibisov.github.io/drf-extensions/docs/#nested-routes +[drf-extensions-collection-level-controllers]: https://chibisov.github.io/drf-extensions/docs/#collection-level-controllers +[drf-extensions-customizable-endpoint-names]: https://chibisov.github.io/drf-extensions/docs/#controller-endpoint-name diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 3c560d829..d4f058ebe 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -1172,9 +1172,9 @@ The [drf-writable-nested][drf-writable-nested] package provides writable nested [cite]: https://groups.google.com/d/topic/django-users/sVFaOfQi4wY/discussion [relations]: relations.md [model-managers]: https://docs.djangoproject.com/en/stable/topics/db/managers/ -[encapsulation-blogpost]: http://www.dabapps.com/blog/django-models-and-encapsulation/ +[encapsulation-blogpost]: https://www.dabapps.com/blog/django-models-and-encapsulation/ [thirdparty-writable-nested]: serializers.md#drf-writable-nested -[django-rest-marshmallow]: http://tomchristie.github.io/django-rest-marshmallow/ +[django-rest-marshmallow]: https://tomchristie.github.io/django-rest-marshmallow/ [marshmallow]: https://marshmallow.readthedocs.io/en/latest/ [serpy]: https://github.com/clarkduvall/serpy [mongoengine]: https://github.com/umutbozkurt/django-rest-framework-mongoengine @@ -1188,5 +1188,5 @@ The [drf-writable-nested][drf-writable-nested] package provides writable nested [drf-dynamic-fields]: https://github.com/dbrgn/drf-dynamic-fields [drf-base64]: https://bitbucket.org/levit_scs/drf_base64 [drf-serializer-extensions]: https://github.com/evenicoulddoit/django-rest-framework-serializer-extensions -[djangorestframework-queryfields]: http://djangorestframework-queryfields.readthedocs.io/ -[drf-writable-nested]: http://github.com/beda-software/drf-writable-nested +[djangorestframework-queryfields]: https://djangorestframework-queryfields.readthedocs.io/ +[drf-writable-nested]: https://github.com/beda-software/drf-writable-nested diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index caa065389..ea150e10f 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -473,6 +473,6 @@ An integer of 0 or more, that may be used to specify the number of application p Default: `None` [cite]: https://www.python.org/dev/peps/pep-0020/ -[rfc4627]: http://www.ietf.org/rfc/rfc4627.txt +[rfc4627]: https://www.ietf.org/rfc/rfc4627.txt [heroku-minified-json]: https://github.com/interagent/http-api-design#keep-json-minified-in-all-responses [strftime]: https://docs.python.org/3/library/time.html#time.strftime diff --git a/docs/api-guide/status-codes.md b/docs/api-guide/status-codes.md index 16a0e63c8..1016f3374 100644 --- a/docs/api-guide/status-codes.md +++ b/docs/api-guide/status-codes.md @@ -118,6 +118,6 @@ The following helper functions are available for identifying the category of the is_client_error() # 4xx is_server_error() # 5xx -[rfc2324]: http://www.ietf.org/rfc/rfc2324.txt -[rfc2616]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html -[rfc6585]: http://tools.ietf.org/html/rfc6585 +[rfc2324]: https://www.ietf.org/rfc/rfc2324.txt +[rfc2616]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html +[rfc6585]: https://tools.ietf.org/html/rfc6585 diff --git a/docs/api-guide/testing.md b/docs/api-guide/testing.md index d2ff6e7cb..b31d2c972 100644 --- a/docs/api-guide/testing.md +++ b/docs/api-guide/testing.md @@ -404,7 +404,7 @@ For example, to add support for using `format='html'` in test requests, you migh ) } -[cite]: http://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper +[cite]: https://jacobian.org/writing/django-apps-with-buildout/#s-create-a-test-wrapper [client]: https://docs.djangoproject.com/en/stable/topics/testing/tools/#the-test-client [requestfactory]: https://docs.djangoproject.com/en/stable/topics/testing/advanced/#django.test.client.RequestFactory [configuration]: #configuration diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index 10a0bb087..9657b00eb 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -72,7 +72,7 @@ The `X-Forwarded-For` HTTP header and `REMOTE_ADDR` WSGI variable are used to un If you need to strictly identify unique client IP addresses, you'll need to first configure the number of application proxies that the API runs behind by setting the `NUM_PROXIES` setting. This setting should be an integer of zero or more. If set to non-zero then the client IP will be identified as being the last IP address in the `X-Forwarded-For` header, once any application proxy IP addresses have first been excluded. If set to zero, then the `REMOTE_ADDR` value will always be used as the identifying IP address. -It is important to understand that if you configure the `NUM_PROXIES` setting, then all clients behind a unique [NAT'd](http://en.wikipedia.org/wiki/Network_address_translation) gateway will be treated as a single client. +It is important to understand that if you configure the `NUM_PROXIES` setting, then all clients behind a unique [NAT'd](https://en.wikipedia.org/wiki/Network_address_translation) gateway will be treated as a single client. Further context on how the `X-Forwarded-For` header works, and identifying a remote client IP can be [found here][identifing-clients]. diff --git a/docs/api-guide/versioning.md b/docs/api-guide/versioning.md index 4a875b87e..8e62c70f1 100644 --- a/docs/api-guide/versioning.md +++ b/docs/api-guide/versioning.md @@ -211,10 +211,10 @@ The following example uses a custom `X-API-Version` header to determine the requ If your versioning scheme is based on the request URL, you will also want to alter how versioned URLs are determined. In order to do so you should override the `.reverse()` method on the class. See the source code for examples. -[cite]: http://www.slideshare.net/evolve_conference/201308-fielding-evolve/31 -[roy-fielding-on-versioning]: http://www.infoq.com/articles/roy-fielding-on-versioning +[cite]: https://www.slideshare.net/evolve_conference/201308-fielding-evolve/31 +[roy-fielding-on-versioning]: https://www.infoq.com/articles/roy-fielding-on-versioning [klabnik-guidelines]: http://blog.steveklabnik.com/posts/2011-07-03-nobody-understands-rest-or-http#i_want_my_api_to_be_versioned [heroku-guidelines]: https://github.com/interagent/http-api-design/blob/master/en/foundations/require-versioning-in-the-accepts-header.md -[json-parameters]: http://tools.ietf.org/html/rfc4627#section-6 -[vendor-media-type]: http://en.wikipedia.org/wiki/Internet_media_type#Vendor_tree +[json-parameters]: https://tools.ietf.org/html/rfc4627#section-6 +[vendor-media-type]: https://en.wikipedia.org/wiki/Internet_media_type#Vendor_tree [lvh]: https://reinteractive.net/posts/199-developing-and-testing-rails-applications-with-subdomains diff --git a/docs/api-guide/views.md b/docs/api-guide/views.md index 017bcad0c..7b2c4eff7 100644 --- a/docs/api-guide/views.md +++ b/docs/api-guide/views.md @@ -214,7 +214,7 @@ You may pass `None` in order to exclude the view from schema generation. return Response({"message": "Will not appear in schema!"}) -[cite]: http://reinout.vanrees.org/weblog/2011/08/24/class-based-views-usage.html +[cite]: https://reinout.vanrees.org/weblog/2011/08/24/class-based-views-usage.html [cite2]: http://www.boredomandlaziness.org/2012/05/djangos-cbvs-are-not-mistake-but.html [settings]: settings.md [throttling]: throttling.md diff --git a/docs/index.md b/docs/index.md index fe0ec3a96..1b494fcfb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -18,9 +18,9 @@
  • Rover.com
  • Sentry
  • Stream
  • -
  • Machinalis
  • +
  • Machinalis
  • -*Many thanks to all our [sponsors][sponsors], and in particular to our premium backers, [Rover](http://jobs.rover.com/), [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), and [Machinalis](http://www.machinalis.com/#services).* +*Many thanks to all our [sponsors][sponsors], and in particular to our premium backers, [Rover](http://jobs.rover.com/), [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), and [Machinalis](https://www.machinalis.com/#services).* --- @@ -256,8 +256,8 @@ in version 3.3 and raised a deprecation warning in 3.4. Its usage is now mandato [sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors [funding]: funding.md -[uploads]: http://core-api.github.io/python-client/api-guide/utils/#file -[downloads]: http://core-api.github.io/python-client/api-guide/codecs/#downloadcodec +[uploads]: https://core-api.github.io/python-client/api-guide/utils/#file +[downloads]: https://core-api.github.io/python-client/api-guide/codecs/#downloadcodec [schema-generation-api]: ../api-guide/schemas/#schemagenerator [schema-docs]: ../api-guide/schemas/#schemas-as-documentation [schema-view]: ../api-guide/schemas/#the-get_schema_view-shortcut diff --git a/docs/topics/ajax-csrf-cors.md b/docs/topics/ajax-csrf-cors.md index 4960e0881..646f3f563 100644 --- a/docs/topics/ajax-csrf-cors.md +++ b/docs/topics/ajax-csrf-cors.md @@ -33,9 +33,9 @@ The best way to deal with CORS in REST framework is to add the required response [Otto Yiu][ottoyiu] maintains the [django-cors-headers] package, which is known to work correctly with REST framework APIs. -[cite]: http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html +[cite]: https://blog.codinghorror.com/preventing-csrf-and-xsrf-attacks/ [csrf]: https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) [csrf-ajax]: https://docs.djangoproject.com/en/stable/ref/csrf/#ajax -[cors]: http://www.w3.org/TR/cors/ +[cors]: https://www.w3.org/TR/cors/ [ottoyiu]: https://github.com/ottoyiu/ [django-cors-headers]: https://github.com/ottoyiu/django-cors-headers/ diff --git a/docs/topics/browsable-api.md b/docs/topics/browsable-api.md index ec4e6b000..23ac25bc9 100644 --- a/docs/topics/browsable-api.md +++ b/docs/topics/browsable-api.md @@ -44,7 +44,7 @@ Full example: {% extends "rest_framework/base.html" %} {% block bootstrap_theme %} - + {% endblock %} {% block bootstrap_navbar_variant %}{% endblock %} @@ -148,15 +148,15 @@ There are [a variety of packages for autocomplete widgets][autocomplete-packages --- -[cite]: http://en.wikiquote.org/wiki/Alfred_North_Whitehead +[cite]: https://en.wikiquote.org/wiki/Alfred_North_Whitehead [drfreverse]: ../api-guide/reverse.md [ffjsonview]: https://addons.mozilla.org/en-US/firefox/addon/jsonview/ [chromejsonview]: https://chrome.google.com/webstore/detail/chklaanhfefbnpoihckbnefhakgolnmc -[bootstrap]: http://getbootstrap.com +[bootstrap]: https://getbootstrap.com/ [cerulean]: ../img/cerulean.png [slate]: ../img/slate.png -[bswatch]: http://bootswatch.com/ -[bcomponents]: http://getbootstrap.com/2.3.2/components.html -[bcomponentsnav]: http://getbootstrap.com/2.3.2/components.html#navbar +[bswatch]: https://bootswatch.com/ +[bcomponents]: https://getbootstrap.com/2.3.2/components.html +[bcomponentsnav]: https://getbootstrap.com/2.3.2/components.html#navbar [autocomplete-packages]: https://www.djangopackages.com/grids/g/auto-complete/ [django-autocomplete-light]: https://github.com/yourlabs/django-autocomplete-light diff --git a/docs/topics/browser-enhancements.md b/docs/topics/browser-enhancements.md index 7517ecbc0..32eab43a8 100644 --- a/docs/topics/browser-enhancements.md +++ b/docs/topics/browser-enhancements.md @@ -80,8 +80,8 @@ was later [dropped from the spec][html5]. There remains [ongoing discussion][put_delete] about adding support for `PUT` and `DELETE`, as well as how to support content types other than form-encoded data. -[cite]: http://www.amazon.com/Restful-Web-Services-Leonard-Richardson/dp/0596529260 +[cite]: https://www.amazon.com/RESTful-Web-Services-Leonard-Richardson/dp/0596529260 [ajax-form]: https://github.com/encode/ajax-form [rails]: http://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-put-or-delete-methods-work -[html5]: http://www.w3.org/TR/html5-diff/#changes-2010-06-24 +[html5]: https://www.w3.org/TR/html5-diff/#changes-2010-06-24 [put_delete]: http://amundsen.com/examples/put-delete-forms/ diff --git a/docs/topics/contributing.md b/docs/topics/contributing.md index 9a413832f..19976b00b 100644 --- a/docs/topics/contributing.md +++ b/docs/topics/contributing.md @@ -198,15 +198,15 @@ If you want to draw attention to a note or warning, use a pair of enclosing line --- -[cite]: http://www.w3.org/People/Berners-Lee/FAQ.html +[cite]: https://www.w3.org/People/Berners-Lee/FAQ.html [code-of-conduct]: https://www.djangoproject.com/conduct/ [google-group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework -[so-filter]: http://stackexchange.com/filters/66475/rest-framework +[so-filter]: https://stackexchange.com/filters/66475/rest-framework [issues]: https://github.com/encode/django-rest-framework/issues?state=open -[pep-8]: http://www.python.org/dev/peps/pep-0008/ +[pep-8]: https://www.python.org/dev/peps/pep-0008/ [travis-status]: ../img/travis-status.png [pull-requests]: https://help.github.com/articles/using-pull-requests [tox]: https://tox.readthedocs.io/en/latest/ -[markdown]: http://daringfireball.net/projects/markdown/basics +[markdown]: https://daringfireball.net/projects/markdown/basics [docs]: https://github.com/encode/django-rest-framework/tree/master/docs [mou]: http://mouapp.com/ diff --git a/docs/topics/documenting-your-api.md b/docs/topics/documenting-your-api.md index b8b9b29f9..fff6c4452 100644 --- a/docs/topics/documenting-your-api.md +++ b/docs/topics/documenting-your-api.md @@ -298,15 +298,15 @@ To implement a hypermedia API you'll need to decide on an appropriate media type [drf-openapi]: https://github.com/limdauto/drf_openapi/ [image-drf-openapi]: ../img/drf-openapi.png [drfdocs-repo]: https://github.com/ekonstantinidis/django-rest-framework-docs -[drfdocs-website]: http://www.drfdocs.com/ +[drfdocs-website]: https://www.drfdocs.com/ [drfdocs-demo]: http://demo.drfdocs.com/ [drfautodocs-repo]: https://github.com/iMakedonsky/drf-autodocs [django-rest-swagger]: https://github.com/marcgibbons/django-rest-swagger [swagger]: https://swagger.io/ [open-api]: https://openapis.org/ [rest-framework-docs]: https://github.com/marcgibbons/django-rest-framework-docs -[apiary]: http://apiary.io/ -[markdown]: http://daringfireball.net/projects/markdown/ +[apiary]: https://apiary.io/ +[markdown]: https://daringfireball.net/projects/markdown/ [hypermedia-docs]: rest-hypermedia-hateoas.md [image-drf-docs]: ../img/drfdocs.png [image-django-rest-swagger]: ../img/django-rest-swagger.png diff --git a/docs/topics/internationalization.md b/docs/topics/internationalization.md index fe85c6523..ed8b85836 100644 --- a/docs/topics/internationalization.md +++ b/docs/topics/internationalization.md @@ -102,9 +102,9 @@ You can find more information on how the language preference is determined in th For API clients the most appropriate of these will typically be to use the `Accept-Language` header; Sessions and cookies will not be available unless using session authentication, and generally better practice to prefer an `Accept-Language` header for API clients rather than using language URL prefixes. -[cite]: http://youtu.be/Wa0VfS2q94Y +[cite]: https://youtu.be/Wa0VfS2q94Y [django-translation]: https://docs.djangoproject.com/en/1.7/topics/i18n/translation -[custom-exception-handler]: ../api-guide/exceptions.md#custom-exception-handling +[custom-exception-handler]: ../api-guide/exceptions.md#custom-exception-handling [transifex-project]: https://www.transifex.com/projects/p/django-rest-framework/ [django-po-source]: https://raw.githubusercontent.com/encode/django-rest-framework/master/rest_framework/locale/en_US/LC_MESSAGES/django.po [django-language-preference]: https://docs.djangoproject.com/en/1.7/topics/i18n/translation/#how-django-discovers-language-preference diff --git a/docs/topics/jobs.md b/docs/topics/jobs.md index 8ffe059ad..1012738d2 100644 --- a/docs/topics/jobs.md +++ b/docs/topics/jobs.md @@ -11,7 +11,7 @@ Looking for a new Django REST Framework related role? On this site we provide a * [https://djangojobs.net/jobs/][django-jobs-net] * [http://djangojobbers.com][django-jobbers-com] * [https://www.indeed.com/q-Django-jobs.html][indeed-com] -* [http://stackoverflow.com/jobs/developer-jobs-using-django][stackoverflow-com] +* [https://stackoverflow.com/jobs/developer-jobs-using-django][stackoverflow-com] * [https://www.upwork.com/o/jobs/browse/skill/django-framework/][upwork-com] * [https://www.technojobs.co.uk/django-jobs][technobjobs-co-uk] * [https://remoteok.io/remote-django-jobs][remoteok-io] @@ -29,7 +29,7 @@ Wonder how else you can help? One of the best ways you can help Django REST Fram [django-jobs-net]: https://djangojobs.net/jobs/ [django-jobbers-com]: http://djangojobbers.com [indeed-com]: https://www.indeed.com/q-Django-jobs.html -[stackoverflow-com]: http://stackoverflow.com/jobs/developer-jobs-using-django +[stackoverflow-com]: https://stackoverflow.com/jobs/developer-jobs-using-django [upwork-com]: https://www.upwork.com/o/jobs/browse/skill/django-framework/ [technobjobs-co-uk]: https://www.technojobs.co.uk/django-jobs [remoteok-io]: https://remoteok.io/remote-django-jobs diff --git a/docs/topics/kickstarter-announcement.md b/docs/topics/kickstarter-announcement.md index 6b7b428d1..e2a283e29 100644 --- a/docs/topics/kickstarter-announcement.md +++ b/docs/topics/kickstarter-announcement.md @@ -72,12 +72,12 @@ Our gold sponsors include companies large and small. Many thanks for their signi
  • Schuberg Philis
  • ProReNata AB
  • SGA Websites
  • -
  • Sirono
  • -
  • Vinta Software Studio
  • -
  • Rapasso
  • +
  • Sirono
  • +
  • Vinta Software Studio
  • +
  • Rapasso
  • Mirus Research
  • -
  • Hipo
  • -
  • Byte
  • +
  • Hipo
  • +
  • Byte
  • Lightning Kite
  • Opbeat
  • Koordinates
  • @@ -85,7 +85,7 @@ Our gold sponsors include companies large and small. Many thanks for their signi
  • Singing Horse Studio Ltd.
  • Heroku
  • Rheinwerk Verlag
  • -
  • Security Compass
  • +
  • Security Compass
  • Django Software Foundation
  • Hipflask
  • Crate
  • @@ -105,38 +105,38 @@ Our gold sponsors include companies large and small. Many thanks for their signi The serious financial contribution that our silver sponsors have made is very much appreciated. I'd like to say a particular thank you to individuals who have chosen to privately support the project at this level. From 73203e6b5920dcbe78e3309b7bf2803eb56db536 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Thu, 25 Jan 2018 03:40:49 -0500 Subject: [PATCH 051/520] Rework dynamic list/detail actions (#5705) * Merge list/detail route decorators into 'action' * Merge dynamic routes, add 'detail' attribute * Add 'ViewSet.get_extra_actions()' * Refactor dynamic route checking & collection * Refactor dynamic route generation * Add 'ViewSet.detail' initkwarg * Fixup schema test * Add release notes for dynamic action changes * Replace list/detail route decorators in tests * Convert tabs to spaces in router docs * Update docs * Make 'detail' a required argument of 'action' * Improve router docs --- docs/api-guide/metadata.md | 2 +- docs/api-guide/routers.md | 96 +++++++--------- docs/api-guide/viewsets.md | 46 +++++--- docs/topics/release-notes.md | 29 +++++ docs/tutorial/6-viewsets-and-routers.md | 10 +- rest_framework/decorators.py | 52 ++++++--- rest_framework/routers.py | 146 ++++++++++++------------ rest_framework/viewsets.py | 18 ++- tests/test_decorators.py | 53 ++++++++- tests/test_routers.py | 40 ++++--- tests/test_schemas.py | 27 ++--- tests/test_viewsets.py | 20 +++- 12 files changed, 333 insertions(+), 206 deletions(-) diff --git a/docs/api-guide/metadata.md b/docs/api-guide/metadata.md index d5c3c1a67..affeea61c 100644 --- a/docs/api-guide/metadata.md +++ b/docs/api-guide/metadata.md @@ -67,7 +67,7 @@ If you have specific requirements for creating schema endpoints that are accesse For example, the following additional route could be used on a viewset to provide a linkable schema endpoint. - @list_route(methods=['GET']) + @action(methods=['GET'], detail=False) def schema(self, request): meta = self.metadata_class() data = meta.determine_metadata(request, self) diff --git a/docs/api-guide/routers.md b/docs/api-guide/routers.md index e4415df15..09e06ff1d 100644 --- a/docs/api-guide/routers.md +++ b/docs/api-guide/routers.md @@ -81,81 +81,62 @@ Router URL patterns can also be namespaces. If using namespacing with hyperlinked serializers you'll also need to ensure that any `view_name` parameters on the serializers correctly reflect the namespace. In the example above you'd need to include a parameter such as `view_name='api:user-detail'` for serializer fields hyperlinked to the user detail view. -### Extra link and actions +### Routing for extra actions -Any methods on the viewset decorated with `@detail_route` or `@list_route` will also be routed. -For example, given a method like this on the `UserViewSet` class: +A viewset may [mark extra actions for routing][route-decorators] by decorating a method with the `@action` decorator. These extra actions will be included in the generated routes. For example, given the `set_password` method on the `UserViewSet` class: from myapp.permissions import IsAdminOrIsSelf - from rest_framework.decorators import detail_route + from rest_framework.decorators import action class UserViewSet(ModelViewSet): ... - @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf]) + @action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf]) def set_password(self, request, pk=None): ... -The following URL pattern would additionally be generated: +The following route would be generated: -* URL pattern: `^users/{pk}/set_password/$` Name: `'user-set-password'` +* URL pattern: `^users/{pk}/set_password/$` +* URL name: `'user-set-password'` -If you do not want to use the default URL generated for your custom action, you can instead use the url_path parameter to customize it. +By default, the URL pattern is based on the method name, and the URL name is the combination of the `ViewSet.basename` and the hyphenated method name. +If you don't want to use the defaults for either of these values, you can instead provide the `url_path` and `url_name` arguments to the `@action` decorator. For example, if you want to change the URL for our custom action to `^users/{pk}/change-password/$`, you could write: from myapp.permissions import IsAdminOrIsSelf - from rest_framework.decorators import detail_route + from rest_framework.decorators import action class UserViewSet(ModelViewSet): ... - @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_path='change-password') + @action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf], + url_path='change-password', url_name='change_password') def set_password(self, request, pk=None): ... The above example would now generate the following URL pattern: -* URL pattern: `^users/{pk}/change-password/$` Name: `'user-change-password'` - -In the case you do not want to use the default name generated for your custom action, you can use the url_name parameter to customize it. - -For example, if you want to change the name of our custom action to `'user-change-password'`, you could write: - - from myapp.permissions import IsAdminOrIsSelf - from rest_framework.decorators import detail_route - - class UserViewSet(ModelViewSet): - ... - - @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf], url_name='change-password') - def set_password(self, request, pk=None): - ... - -The above example would now generate the following URL pattern: - -* URL pattern: `^users/{pk}/set_password/$` Name: `'user-change-password'` - -You can also use url_path and url_name parameters together to obtain extra control on URL generation for custom views. - -For more information see the viewset documentation on [marking extra actions for routing][route-decorators]. +* URL path: `^users/{pk}/change-password/$` +* URL name: `'user-change_password'` # API Guide ## SimpleRouter -This router includes routes for the standard set of `list`, `create`, `retrieve`, `update`, `partial_update` and `destroy` actions. The viewset can also mark additional methods to be routed, using the `@detail_route` or `@list_route` decorators. +This router includes routes for the standard set of `list`, `create`, `retrieve`, `update`, `partial_update` and `destroy` actions. The viewset can also mark additional methods to be routed, using the `@action` decorator. - + - +
    URL StyleHTTP MethodActionURL Name
    {prefix}/GETlist{basename}-list
    POSTcreate
    {prefix}/{methodname}/GET, or as specified by `methods` argument`@list_route` decorated method{basename}-{methodname}
    {prefix}/{url_path}/GET, or as specified by `methods` argument`@action(detail=False)` decorated method{basename}-{url_name}
    {prefix}/{lookup}/GETretrieve{basename}-detail
    PUTupdate
    PATCHpartial_update
    DELETEdestroy
    {prefix}/{lookup}/{methodname}/GET, or as specified by `methods` argument`@detail_route` decorated method{basename}-{methodname}
    {prefix}/{lookup}/{url_path}/GET, or as specified by `methods` argument`@action(detail=True)` decorated method{basename}-{url_name}
    By default the URLs created by `SimpleRouter` are appended with a trailing slash. @@ -180,12 +161,12 @@ This router is similar to `SimpleRouter` as above, but additionally includes a d [.format]GETautomatically generated root viewapi-root {prefix}/[.format]GETlist{basename}-list POSTcreate - {prefix}/{methodname}/[.format]GET, or as specified by `methods` argument`@list_route` decorated method{basename}-{methodname} + {prefix}/{url_path}/[.format]GET, or as specified by `methods` argument`@action(detail=False)` decorated method{basename}-{url_name} {prefix}/{lookup}/[.format]GETretrieve{basename}-detail PUTupdate PATCHpartial_update DELETEdestroy - {prefix}/{lookup}/{methodname}/[.format]GET, or as specified by `methods` argument`@detail_route` decorated method{basename}-{methodname} + {prefix}/{lookup}/{url_path}/[.format]GET, or as specified by `methods` argument`@action(detail=True)` decorated method{basename}-{url_name} As with `SimpleRouter` the trailing slashes on the URL routes can be removed by setting the `trailing_slash` argument to `False` when instantiating the router. @@ -212,18 +193,18 @@ The arguments to the `Route` named tuple are: * `{basename}` - The base to use for the URL names that are created. -**initkwargs**: A dictionary of any additional arguments that should be passed when instantiating the view. Note that the `suffix` argument is reserved for identifying the viewset type, used when generating the view name and breadcrumb links. +**initkwargs**: A dictionary of any additional arguments that should be passed when instantiating the view. Note that the `detail`, `basename`, and `suffix` arguments are reserved for viewset introspection and are also used by the browsable API to generate the view name and breadcrumb links. ## Customizing dynamic routes -You can also customize how the `@list_route` and `@detail_route` decorators are routed. -To route either or both of these decorators, include a `DynamicListRoute` and/or `DynamicDetailRoute` named tuple in the `.routes` list. +You can also customize how the `@action` decorator is routed. Include the `DynamicRoute` named tuple in the `.routes` list, setting the `detail` argument as appropriate for the list-based and detail-based routes. In addition to `detail`, the arguments to `DynamicRoute` are: -The arguments to `DynamicListRoute` and `DynamicDetailRoute` are: +**url**: A string representing the URL to be routed. May include the same format strings as `Route`, and additionally accepts the `{url_path}` format string. -**url**: A string representing the URL to be routed. May include the same format strings as `Route`, and additionally accepts the `{methodname}` and `{methodnamehyphen}` format strings. +**name**: The name of the URL as used in `reverse` calls. May include the following format strings: -**name**: The name of the URL as used in `reverse` calls. May include the following format strings: `{basename}`, `{methodname}` and `{methodnamehyphen}`. +* `{basename}` - The base to use for the URL names that are created. +* `{url_name}` - The `url_name` provided to the `@action`. **initkwargs**: A dictionary of any additional arguments that should be passed when instantiating the view. @@ -231,7 +212,7 @@ The arguments to `DynamicListRoute` and `DynamicDetailRoute` are: The following example will only route to the `list` and `retrieve` actions, and does not use the trailing slash convention. - from rest_framework.routers import Route, DynamicDetailRoute, SimpleRouter + from rest_framework.routers import Route, DynamicRoute, SimpleRouter class CustomReadOnlyRouter(SimpleRouter): """ @@ -239,22 +220,23 @@ The following example will only route to the `list` and `retrieve` actions, and """ routes = [ Route( - url=r'^{prefix}$', - mapping={'get': 'list'}, - name='{basename}-list', - initkwargs={'suffix': 'List'} + url=r'^{prefix}$', + mapping={'get': 'list'}, + name='{basename}-list', + initkwargs={'suffix': 'List'} ), Route( - url=r'^{prefix}/{lookup}$', + url=r'^{prefix}/{lookup}$', mapping={'get': 'retrieve'}, name='{basename}-detail', initkwargs={'suffix': 'Detail'} ), - DynamicDetailRoute( - url=r'^{prefix}/{lookup}/{methodnamehyphen}$', - name='{basename}-{methodnamehyphen}', - initkwargs={} - ) + DynamicRoute( + url=r'^{prefix}/{lookup}/{url_path}$', + name='{basename}-{url_name}', + detail=True, + initkwargs={} + ) ] Let's take a look at the routes our `CustomReadOnlyRouter` would generate for a simple viewset. @@ -269,7 +251,7 @@ Let's take a look at the routes our `CustomReadOnlyRouter` would generate for a serializer_class = UserSerializer lookup_field = 'username' - @detail_route() + @action(detail=True) def group_names(self, request, pk=None): """ Returns a list of all the group names that the given @@ -283,7 +265,7 @@ Let's take a look at the routes our `CustomReadOnlyRouter` would generate for a router = CustomReadOnlyRouter() router.register('users', UserViewSet) - urlpatterns = router.urls + urlpatterns = router.urls The following mappings would be generated... diff --git a/docs/api-guide/viewsets.md b/docs/api-guide/viewsets.md index 27fb1d780..503459a96 100644 --- a/docs/api-guide/viewsets.md +++ b/docs/api-guide/viewsets.md @@ -102,10 +102,16 @@ The default routers included with REST framework will provide routes for a stand def destroy(self, request, pk=None): pass -During dispatch the name of the current action is available via the `.action` attribute. -You may inspect `.action` to adjust behaviour based on the current action. +## Introspecting ViewSet actions -For example, you could restrict permissions to everything except the `list` action similar to this: +During dispatch, the following attributes are available on the `ViewSet`. + +* `basename` - the base to use for the URL names that are created. +* `action` - the name of the current action (e.g., `list`, `create`). +* `detail` - boolean indicating if the current action is configured for a list or detail view. +* `suffix` - the display suffix for the viewset type - mirrors the `detail` attribute. + +You may inspect these attributes to adjust behaviour based on the current action. For example, you could restrict permissions to everything except the `list` action similar to this: def get_permissions(self): """ @@ -119,16 +125,13 @@ For example, you could restrict permissions to everything except the `list` acti ## Marking extra actions for routing -If you have ad-hoc methods that you need to be routed to, you can mark them as requiring routing using the `@detail_route` or `@list_route` decorators. +If you have ad-hoc methods that should be routable, you can mark them as such with the `@action` decorator. Like regular actions, extra actions may be intended for either a list of objects, or a single instance. To indicate this, set the `detail` argument to `True` or `False`. The router will configure its URL patterns accordingly. e.g., the `DefaultRouter` will configure detail actions to contain `pk` in their URL patterns. -The `@detail_route` decorator contains `pk` in its URL pattern and is intended for methods which require a single instance. The `@list_route` decorator is intended for methods which operate on a list of objects. - -For example: +A more complete example of extra actions: from django.contrib.auth.models import User - from rest_framework import status - from rest_framework import viewsets - from rest_framework.decorators import detail_route, list_route + from rest_framework import status, viewsets + from rest_framework.decorators import action from rest_framework.response import Response from myapp.serializers import UserSerializer, PasswordSerializer @@ -139,7 +142,7 @@ For example: queryset = User.objects.all() serializer_class = UserSerializer - @detail_route(methods=['post']) + @action(methods=['post'], detail=True) def set_password(self, request, pk=None): user = self.get_object() serializer = PasswordSerializer(data=request.data) @@ -151,7 +154,7 @@ For example: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - @list_route() + @action(detail=False) def recent_users(self, request): recent_users = User.objects.all().order('-last_login') @@ -163,20 +166,22 @@ For example: serializer = self.get_serializer(recent_users, many=True) return Response(serializer.data) -The decorators can additionally take extra arguments that will be set for the routed view only. For example... +The decorator can additionally take extra arguments that will be set for the routed view only. For example: - @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf]) + @action(methods=['post'], detail=True, permission_classes=[IsAdminOrIsSelf]) def set_password(self, request, pk=None): ... -These decorators will route `GET` requests by default, but may also accept other HTTP methods, by using the `methods` argument. For example: +These decorator will route `GET` requests by default, but may also accept other HTTP methods by setting the `methods` argument. For example: - @detail_route(methods=['post', 'delete']) + @action(methods=['post', 'delete'], detail=True) def unset_password(self, request, pk=None): ... The two new actions will then be available at the urls `^users/{pk}/set_password/$` and `^users/{pk}/unset_password/$` +To view all extra actions, call the `.get_extra_actions()` method. + ## Reversing action URLs If you need to get the URL of an action, use the `.reverse_action()` method. This is a convenience wrapper for `reverse()`, automatically passing the view's `request` object and prepending the `url_name` with the `.basename` attribute. @@ -190,7 +195,14 @@ Using the example from the previous section: 'http://localhost:8000/api/users/1/set_password' ``` -The `url_name` argument should match the same argument to the `@list_route` and `@detail_route` decorators. Additionally, this can be used to reverse the default `list` and `detail` routes. +Alternatively, you can use the `url_name` attribute set by the `@action` decorator. + +```python +>>> view.reverse_action(view.set_password.url_name, args=['1']) +'http://localhost:8000/api/users/1/set_password' +``` + +The `url_name` argument for `.reverse_action()` should match the same argument to the `@action` decorator. Additionally, this method can be used to reverse the default actions, such as `list` and `create`. --- diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 128175ef5..2c45b70af 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -38,6 +38,31 @@ You can determine your currently installed version using `pip freeze`: --- +## 3.8.x series + +### 3.8.0 + +**Date**: [unreleased][3.8.0-milestone] + +* Refactor dynamic route generation and improve viewset action introspectibility. [#5705][gh5705] + + `ViewSet`s have been provided with new attributes and methods that allow + it to introspect its set of actions and the details of the current action. + + * Merged `list_route` and `detail_route` into a single `action` decorator. + * Get all extra actions on a `ViewSet` with `.get_extra_actions()`. + * Extra actions now set the `url_name` and `url_path` on the decorated method. + * Enable action url reversing through `.reverse_action()` method (added in 3.7.4) + * Example reverse call: `self.reverse_action(self.custom_action.url_name)` + * Add `detail` initkwarg to indicate if the current action is operating on a + collection or a single instance. + + Additional changes: + + * Deprecated `list_route` & `detail_route` in favor of `action` decorator with `detail` boolean. + * Deprecated dynamic list/detail route variants in favor of `DynamicRoute` with `detail` boolean. + * Refactored the router's dynamic route generation. + ## 3.7.x series ### 3.7.7 @@ -940,6 +965,7 @@ For older release notes, [please see the version 2.x documentation][old-release- [3.7.5-milestone]: https://github.com/encode/django-rest-framework/milestone/63?closed=1 [3.7.6-milestone]: https://github.com/encode/django-rest-framework/milestone/64?closed=1 [3.7.7-milestone]: https://github.com/encode/django-rest-framework/milestone/65?closed=1 +[3.8.0-milestone]: https://github.com/encode/django-rest-framework/milestone/61?closed=1 [gh2013]: https://github.com/encode/django-rest-framework/issues/2013 @@ -1750,3 +1776,6 @@ For older release notes, [please see the version 2.x documentation][old-release- [gh5695]: https://github.com/encode/django-rest-framework/issues/5695 [gh5696]: https://github.com/encode/django-rest-framework/issues/5696 [gh5697]: https://github.com/encode/django-rest-framework/issues/5697 + + +[gh5705]: https://github.com/encode/django-rest-framework/issues/5705 diff --git a/docs/tutorial/6-viewsets-and-routers.md b/docs/tutorial/6-viewsets-and-routers.md index 7d87c0212..9452b4947 100644 --- a/docs/tutorial/6-viewsets-and-routers.md +++ b/docs/tutorial/6-viewsets-and-routers.md @@ -25,7 +25,7 @@ Here we've used the `ReadOnlyModelViewSet` class to automatically provide the de Next we're going to replace the `SnippetList`, `SnippetDetail` and `SnippetHighlight` view classes. We can remove the three views, and again replace them with a single class. - from rest_framework.decorators import detail_route + from rest_framework.decorators import action from rest_framework.response import Response class SnippetViewSet(viewsets.ModelViewSet): @@ -40,7 +40,7 @@ Next we're going to replace the `SnippetList`, `SnippetDetail` and `SnippetHighl permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,) - @detail_route(renderer_classes=[renderers.StaticHTMLRenderer]) + @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer]) def highlight(self, request, *args, **kwargs): snippet = self.get_object() return Response(snippet.highlighted) @@ -50,11 +50,11 @@ Next we're going to replace the `SnippetList`, `SnippetDetail` and `SnippetHighl This time we've used the `ModelViewSet` class in order to get the complete set of default read and write operations. -Notice that we've also used the `@detail_route` decorator to create a custom action, named `highlight`. This decorator can be used to add any custom endpoints that don't fit into the standard `create`/`update`/`delete` style. +Notice that we've also used the `@action` decorator to create a custom action, named `highlight`. This decorator can be used to add any custom endpoints that don't fit into the standard `create`/`update`/`delete` style. -Custom actions which use the `@detail_route` decorator will respond to `GET` requests by default. We can use the `methods` argument if we wanted an action that responded to `POST` requests. +Custom actions which use the `@action` decorator will respond to `GET` requests by default. We can use the `methods` argument if we wanted an action that responded to `POST` requests. -The URLs for custom actions by default depend on the method name itself. If you want to change the way url should be constructed, you can include url_path as a decorator keyword argument. +The URLs for custom actions by default depend on the method name itself. If you want to change the way url should be constructed, you can include `url_path` as a decorator keyword argument. ## Binding ViewSets to URLs explicitly diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py index 2f93fdd97..62afa0597 100644 --- a/rest_framework/decorators.py +++ b/rest_framework/decorators.py @@ -130,29 +130,49 @@ def schema(view_inspector): return decorator +def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs): + """ + Mark a ViewSet method as a routable action. + + Set the `detail` boolean to determine if this action should apply to + instance/detail requests or collection/list requests. + """ + methods = ['get'] if (methods is None) else methods + methods = [method.lower() for method in methods] + + assert detail is not None, ( + "@action() missing required argument: 'detail'" + ) + + def decorator(func): + func.bind_to_methods = methods + func.detail = detail + func.url_path = url_path or func.__name__ + func.url_name = url_name or func.__name__.replace('_', '-') + func.kwargs = kwargs + return func + return decorator + + def detail_route(methods=None, **kwargs): """ Used to mark a method on a ViewSet that should be routed for detail requests. """ - methods = ['get'] if (methods is None) else methods - - def decorator(func): - func.bind_to_methods = methods - func.detail = True - func.kwargs = kwargs - return func - return decorator + warnings.warn( + "`detail_route` is pending deprecation and will be removed in 3.10 in favor of " + "`action`, which accepts a `detail` bool. Use `@action(detail=True)` instead.", + PendingDeprecationWarning, stacklevel=2 + ) + return action(methods, detail=True, **kwargs) def list_route(methods=None, **kwargs): """ Used to mark a method on a ViewSet that should be routed for list requests. """ - methods = ['get'] if (methods is None) else methods - - def decorator(func): - func.bind_to_methods = methods - func.detail = False - func.kwargs = kwargs - return func - return decorator + warnings.warn( + "`list_route` is pending deprecation and will be removed in 3.10 in favor of " + "`action`, which accepts a `detail` bool. Use `@action(detail=False)` instead.", + PendingDeprecationWarning, stacklevel=2 + ) + return action(methods, detail=False, **kwargs) diff --git a/rest_framework/routers.py b/rest_framework/routers.py index f4d2fab38..9007788f8 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -16,6 +16,7 @@ For example, you might have a `urls.py` that looks something like this: from __future__ import unicode_literals import itertools +import warnings from collections import OrderedDict, namedtuple from django.conf.urls import url @@ -30,9 +31,30 @@ from rest_framework.schemas.views import SchemaView from rest_framework.settings import api_settings from rest_framework.urlpatterns import format_suffix_patterns -Route = namedtuple('Route', ['url', 'mapping', 'name', 'initkwargs']) -DynamicDetailRoute = namedtuple('DynamicDetailRoute', ['url', 'name', 'initkwargs']) -DynamicListRoute = namedtuple('DynamicListRoute', ['url', 'name', 'initkwargs']) +Route = namedtuple('Route', ['url', 'mapping', 'name', 'detail', 'initkwargs']) +DynamicRoute = namedtuple('DynamicRoute', ['url', 'name', 'detail', 'initkwargs']) + + +class DynamicDetailRoute(object): + def __new__(cls, url, name, initkwargs): + warnings.warn( + "`DynamicDetailRoute` is pending deprecation and will be removed in 3.10 " + "in favor of `DynamicRoute`, which accepts a `detail` boolean. Use " + "`DynamicRoute(url, name, True, initkwargs)` instead.", + PendingDeprecationWarning, stacklevel=2 + ) + return DynamicRoute(url, name, True, initkwargs) + + +class DynamicListRoute(object): + def __new__(cls, url, name, initkwargs): + warnings.warn( + "`DynamicListRoute` is pending deprecation and will be removed in 3.10 in " + "favor of `DynamicRoute`, which accepts a `detail` boolean. Use " + "`DynamicRoute(url, name, False, initkwargs)` instead.", + PendingDeprecationWarning, stacklevel=2 + ) + return DynamicRoute(url, name, False, initkwargs) def escape_curly_brackets(url_path): @@ -44,18 +66,6 @@ def escape_curly_brackets(url_path): return url_path -def replace_methodname(format_string, methodname): - """ - Partially format a format_string, swapping out any - '{methodname}' or '{methodnamehyphen}' components. - """ - methodnamehyphen = methodname.replace('_', '-') - ret = format_string - ret = ret.replace('{methodname}', methodname) - ret = ret.replace('{methodnamehyphen}', methodnamehyphen) - return ret - - def flatten(list_of_lists): """ Takes an iterable of iterables, returns a single iterable containing all items @@ -103,14 +113,15 @@ class SimpleRouter(BaseRouter): 'post': 'create' }, name='{basename}-list', + detail=False, initkwargs={'suffix': 'List'} ), - # Dynamically generated list routes. - # Generated using @list_route decorator - # on methods of the viewset. - DynamicListRoute( - url=r'^{prefix}/{methodname}{trailing_slash}$', - name='{basename}-{methodnamehyphen}', + # Dynamically generated list routes. Generated using + # @action(detail=False) decorator on methods of the viewset. + DynamicRoute( + url=r'^{prefix}/{url_path}{trailing_slash}$', + name='{basename}-{url_name}', + detail=False, initkwargs={} ), # Detail route. @@ -123,13 +134,15 @@ class SimpleRouter(BaseRouter): 'delete': 'destroy' }, name='{basename}-detail', + detail=True, initkwargs={'suffix': 'Instance'} ), - # Dynamically generated detail routes. - # Generated using @detail_route decorator on methods of the viewset. - DynamicDetailRoute( - url=r'^{prefix}/{lookup}/{methodname}{trailing_slash}$', - name='{basename}-{methodnamehyphen}', + # Dynamically generated detail routes. Generated using + # @action(detail=True) decorator on methods of the viewset. + DynamicRoute( + url=r'^{prefix}/{lookup}/{url_path}{trailing_slash}$', + name='{basename}-{url_name}', + detail=True, initkwargs={} ), ] @@ -160,57 +173,47 @@ class SimpleRouter(BaseRouter): # converting to list as iterables are good for one pass, known host needs to be checked again and again for # different functions. known_actions = list(flatten([route.mapping.values() for route in self.routes if isinstance(route, Route)])) + extra_actions = viewset.get_extra_actions() - # Determine any `@detail_route` or `@list_route` decorated methods on the viewset - detail_routes = [] - list_routes = [] - for methodname in dir(viewset): - attr = getattr(viewset, methodname) - httpmethods = getattr(attr, 'bind_to_methods', None) - detail = getattr(attr, 'detail', True) - if httpmethods: - # checking method names against the known actions list - if methodname in known_actions: - raise ImproperlyConfigured('Cannot use @detail_route or @list_route ' - 'decorators on method "%s" ' - 'as it is an existing route' % methodname) - httpmethods = [method.lower() for method in httpmethods] - if detail: - detail_routes.append((httpmethods, methodname)) - else: - list_routes.append((httpmethods, methodname)) + # checking action names against the known actions list + not_allowed = [ + action.__name__ for action in extra_actions + if action.__name__ in known_actions + ] + if not_allowed: + msg = ('Cannot use the @action decorator on the following ' + 'methods, as they are existing routes: %s') + raise ImproperlyConfigured(msg % ', '.join(not_allowed)) - def _get_dynamic_routes(route, dynamic_routes): - ret = [] - for httpmethods, methodname in dynamic_routes: - method_kwargs = getattr(viewset, methodname).kwargs - initkwargs = route.initkwargs.copy() - initkwargs.update(method_kwargs) - url_path = initkwargs.pop("url_path", None) or methodname - url_path = escape_curly_brackets(url_path) - url_name = initkwargs.pop("url_name", None) or url_path - ret.append(Route( - url=replace_methodname(route.url, url_path), - mapping={httpmethod: methodname for httpmethod in httpmethods}, - name=replace_methodname(route.name, url_name), - initkwargs=initkwargs, - )) + # partition detail and list actions + detail_actions = [action for action in extra_actions if action.detail] + list_actions = [action for action in extra_actions if not action.detail] - return ret - - ret = [] + routes = [] for route in self.routes: - if isinstance(route, DynamicDetailRoute): - # Dynamic detail routes (@detail_route decorator) - ret += _get_dynamic_routes(route, detail_routes) - elif isinstance(route, DynamicListRoute): - # Dynamic list routes (@list_route decorator) - ret += _get_dynamic_routes(route, list_routes) + if isinstance(route, DynamicRoute) and route.detail: + routes += [self._get_dynamic_route(route, action) for action in detail_actions] + elif isinstance(route, DynamicRoute) and not route.detail: + routes += [self._get_dynamic_route(route, action) for action in list_actions] else: - # Standard route - ret.append(route) + routes.append(route) - return ret + return routes + + def _get_dynamic_route(self, route, action): + initkwargs = route.initkwargs.copy() + initkwargs.update(action.kwargs) + + url_path = escape_curly_brackets(action.url_path) + + return Route( + url=route.url.replace('{url_path}', url_path), + mapping={http_method: action.__name__ + for http_method in action.bind_to_methods}, + name=route.name.replace('{url_name}', action.url_name), + detail=route.detail, + initkwargs=initkwargs, + ) def get_method_map(self, viewset, method_map): """ @@ -281,6 +284,7 @@ class SimpleRouter(BaseRouter): initkwargs = route.initkwargs.copy() initkwargs.update({ 'basename': basename, + 'detail': route.detail, }) view = viewset.as_view(mapping, **initkwargs) diff --git a/rest_framework/viewsets.py b/rest_framework/viewsets.py index 4ee7cdaf8..9a85049bc 100644 --- a/rest_framework/viewsets.py +++ b/rest_framework/viewsets.py @@ -19,6 +19,7 @@ automatically. from __future__ import unicode_literals from functools import update_wrapper +from inspect import getmembers from django.utils.decorators import classonlymethod from django.views.decorators.csrf import csrf_exempt @@ -27,6 +28,10 @@ from rest_framework import generics, mixins, views from rest_framework.reverse import reverse +def _is_extra_action(attr): + return hasattr(attr, 'bind_to_methods') + + class ViewSetMixin(object): """ This is the magic. @@ -51,6 +56,9 @@ class ViewSetMixin(object): # eg. 'List' or 'Instance'. cls.suffix = None + # The detail initkwarg is reserved for introspecting the viewset type. + cls.detail = None + # Setting a basename allows a view to reverse its action urls. This # value is provided by the router through the initkwargs. cls.basename = None @@ -112,8 +120,7 @@ class ViewSetMixin(object): def initialize_request(self, request, *args, **kwargs): """ - Set the `.action` attribute on the view, - depending on the request method. + Set the `.action` attribute on the view, depending on the request method. """ request = super(ViewSetMixin, self).initialize_request(request, *args, **kwargs) method = request.method.lower() @@ -135,6 +142,13 @@ class ViewSetMixin(object): return reverse(url_name, *args, **kwargs) + @classmethod + def get_extra_actions(cls): + """ + Get the methods that are marked as an extra ViewSet `@action`. + """ + return [method for _, method in getmembers(cls, _is_extra_action)] + class ViewSet(ViewSetMixin, views.APIView): """ diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 6331742db..674990730 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -1,12 +1,14 @@ from __future__ import unicode_literals +import pytest from django.test import TestCase from rest_framework import status from rest_framework.authentication import BasicAuthentication from rest_framework.decorators import ( - api_view, authentication_classes, parser_classes, permission_classes, - renderer_classes, schema, throttle_classes + action, api_view, authentication_classes, detail_route, list_route, + parser_classes, permission_classes, renderer_classes, schema, + throttle_classes ) from rest_framework.parsers import JSONParser from rest_framework.permissions import IsAuthenticated @@ -166,3 +168,50 @@ class DecoratorTestCase(TestCase): return Response({}) assert isinstance(view.cls.schema, CustomSchema) + + +class ActionDecoratorTestCase(TestCase): + + def test_defaults(self): + @action(detail=True) + def test_action(request): + pass + + assert test_action.bind_to_methods == ['get'] + assert test_action.detail is True + assert test_action.url_path == 'test_action' + assert test_action.url_name == 'test-action' + + def test_detail_required(self): + with pytest.raises(AssertionError) as excinfo: + @action() + def test_action(request): + pass + + assert str(excinfo.value) == "@action() missing required argument: 'detail'" + + def test_detail_route_deprecation(self): + with pytest.warns(PendingDeprecationWarning) as record: + @detail_route() + def view(request): + pass + + assert len(record) == 1 + assert str(record[0].message) == ( + "`detail_route` is pending deprecation and will be removed in " + "3.10 in favor of `action`, which accepts a `detail` bool. Use " + "`@action(detail=True)` instead." + ) + + def test_list_route_deprecation(self): + with pytest.warns(PendingDeprecationWarning) as record: + @list_route() + def view(request): + pass + + assert len(record) == 1 + assert str(record[0].message) == ( + "`list_route` is pending deprecation and will be removed in " + "3.10 in favor of `action`, which accepts a `detail` bool. Use " + "`@action(detail=False)` instead." + ) diff --git a/tests/test_routers.py b/tests/test_routers.py index 55ccc647b..36255f48f 100644 --- a/tests/test_routers.py +++ b/tests/test_routers.py @@ -11,7 +11,7 @@ from django.urls import resolve from rest_framework import permissions, serializers, viewsets from rest_framework.compat import get_regex_pattern -from rest_framework.decorators import detail_route, list_route +from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.routers import DefaultRouter, SimpleRouter from rest_framework.test import APIRequestFactory, URLPatternsTestCase @@ -67,12 +67,12 @@ class EmptyPrefixViewSet(viewsets.ModelViewSet): class RegexUrlPathViewSet(viewsets.ViewSet): - @list_route(url_path='list/(?P[0-9]{4})') + @action(detail=False, url_path='list/(?P[0-9]{4})') def regex_url_path_list(self, request, *args, **kwargs): kwarg = self.kwargs.get('kwarg', '') return Response({'kwarg': kwarg}) - @detail_route(url_path='detail/(?P[0-9]{4})') + @action(detail=True, url_path='detail/(?P[0-9]{4})') def regex_url_path_detail(self, request, *args, **kwargs): pk = self.kwargs.get('pk', '') kwarg = self.kwargs.get('kwarg', '') @@ -99,23 +99,23 @@ class BasicViewSet(viewsets.ViewSet): def list(self, request, *args, **kwargs): return Response({'method': 'list'}) - @detail_route(methods=['post']) + @action(methods=['post'], detail=True) def action1(self, request, *args, **kwargs): return Response({'method': 'action1'}) - @detail_route(methods=['post']) + @action(methods=['post'], detail=True) def action2(self, request, *args, **kwargs): return Response({'method': 'action2'}) - @detail_route(methods=['post', 'delete']) + @action(methods=['post', 'delete'], detail=True) def action3(self, request, *args, **kwargs): return Response({'method': 'action2'}) - @detail_route() + @action(detail=True) def link1(self, request, *args, **kwargs): return Response({'method': 'link1'}) - @detail_route() + @action(detail=True) def link2(self, request, *args, **kwargs): return Response({'method': 'link2'}) @@ -297,7 +297,7 @@ class TestActionKeywordArgs(TestCase): class TestViewSet(viewsets.ModelViewSet): permission_classes = [] - @detail_route(methods=['post'], permission_classes=[permissions.AllowAny]) + @action(methods=['post'], detail=True, permission_classes=[permissions.AllowAny]) def custom(self, request, *args, **kwargs): return Response({ 'permission_classes': self.permission_classes @@ -315,14 +315,14 @@ class TestActionKeywordArgs(TestCase): class TestActionAppliedToExistingRoute(TestCase): """ - Ensure `@detail_route` decorator raises an except when applied + Ensure `@action` decorator raises an except when applied to an existing route """ def test_exception_raised_when_action_applied_to_existing_route(self): class TestViewSet(viewsets.ModelViewSet): - @detail_route(methods=['post']) + @action(methods=['post'], detail=True) def retrieve(self, request, *args, **kwargs): return Response({ 'hello': 'world' @@ -339,27 +339,27 @@ class DynamicListAndDetailViewSet(viewsets.ViewSet): def list(self, request, *args, **kwargs): return Response({'method': 'list'}) - @list_route(methods=['post']) + @action(methods=['post'], detail=False) def list_route_post(self, request, *args, **kwargs): return Response({'method': 'action1'}) - @detail_route(methods=['post']) + @action(methods=['post'], detail=True) def detail_route_post(self, request, *args, **kwargs): return Response({'method': 'action2'}) - @list_route() + @action(detail=False) def list_route_get(self, request, *args, **kwargs): return Response({'method': 'link1'}) - @detail_route() + @action(detail=True) def detail_route_get(self, request, *args, **kwargs): return Response({'method': 'link2'}) - @list_route(url_path="list_custom-route") + @action(detail=False, url_path="list_custom-route") def list_custom_route_get(self, request, *args, **kwargs): return Response({'method': 'link1'}) - @detail_route(url_path="detail_custom-route") + @action(detail=True, url_path="detail_custom-route") def detail_custom_route_get(self, request, *args, **kwargs): return Response({'method': 'link2'}) @@ -455,6 +455,12 @@ class TestViewInitkwargs(URLPatternsTestCase, TestCase): assert initkwargs['suffix'] == 'List' + def test_detail(self): + match = resolve('/example/notes/') + initkwargs = match.func.initkwargs + + assert not initkwargs['detail'] + def test_basename(self): match = resolve('/example/notes/') initkwargs = match.func.initkwargs diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 34cb20798..1cbee0695 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -10,9 +10,7 @@ from rest_framework import ( filters, generics, pagination, permissions, serializers ) from rest_framework.compat import coreapi, coreschema, get_regex_pattern, path -from rest_framework.decorators import ( - api_view, detail_route, list_route, schema -) +from rest_framework.decorators import action, api_view, schema from rest_framework.request import Request from rest_framework.routers import DefaultRouter, SimpleRouter from rest_framework.schemas import ( @@ -67,25 +65,25 @@ class ExampleViewSet(ModelViewSet): filter_backends = [filters.OrderingFilter] serializer_class = ExampleSerializer - @detail_route(methods=['post'], serializer_class=AnotherSerializer) + @action(methods=['post'], detail=True, serializer_class=AnotherSerializer) def custom_action(self, request, pk): """ A description of custom action. """ return super(ExampleSerializer, self).retrieve(self, request) - @detail_route(methods=['post'], serializer_class=AnotherSerializerWithListFields) + @action(methods=['post'], detail=True, serializer_class=AnotherSerializerWithListFields) def custom_action_with_list_fields(self, request, pk): """ A custom action using both list field and list serializer in the serializer. """ return super(ExampleSerializer, self).retrieve(self, request) - @list_route() + @action(detail=False) def custom_list_action(self, request): return super(ExampleViewSet, self).list(self, request) - @list_route(methods=['post', 'get'], serializer_class=EmptySerializer) + @action(methods=['post', 'get'], detail=False, serializer_class=EmptySerializer) def custom_list_action_multiple_methods(self, request): return super(ExampleViewSet, self).list(self, request) @@ -865,11 +863,11 @@ class NamingCollisionViewSet(GenericViewSet): """ permision_class = () - @list_route() + @action(detail=False) def detail(self, request): return {} - @list_route(url_path='detail/export') + @action(detail=False, url_path='detail/export') def detail_export(self, request): return {} @@ -949,7 +947,10 @@ class TestURLNamingCollisions(TestCase): generator = SchemaGenerator(title='Naming Colisions', patterns=patterns) schema = generator.get_schema() - desc = schema['detail_0'].description # not important here + + # not important here + desc_0 = schema['detail']['detail_export'].description + desc_1 = schema['detail_0'].description expected = coreapi.Document( url='', @@ -959,12 +960,12 @@ class TestURLNamingCollisions(TestCase): 'detail_export': coreapi.Link( url='/from-routercollision/detail/export/', action='get', - description=desc) + description=desc_0) }, 'detail_0': coreapi.Link( url='/from-routercollision/detail/', action='get', - description=desc + description=desc_1 ) } ) @@ -1046,7 +1047,7 @@ def test_head_and_options_methods_are_excluded(): class AViewSet(ModelViewSet): - @detail_route(methods=['options', 'get']) + @action(methods=['options', 'get'], detail=True) def custom_action(self, request, pk): pass diff --git a/tests/test_viewsets.py b/tests/test_viewsets.py index beff42cb8..25feb0f37 100644 --- a/tests/test_viewsets.py +++ b/tests/test_viewsets.py @@ -3,7 +3,7 @@ from django.db import models from django.test import TestCase, override_settings from rest_framework import status -from rest_framework.decorators import detail_route, list_route +from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.routers import SimpleRouter from rest_framework.test import APIRequestFactory @@ -39,19 +39,19 @@ class ActionViewSet(GenericViewSet): def retrieve(self, request, *args, **kwargs): pass - @list_route() + @action(detail=False) def list_action(self, request, *args, **kwargs): pass - @list_route(url_name='list-custom') + @action(detail=False, url_name='list-custom') def custom_list_action(self, request, *args, **kwargs): pass - @detail_route() + @action(detail=True) def detail_action(self, request, *args, **kwargs): pass - @detail_route(url_name='detail-custom') + @action(detail=True, url_name='detail-custom') def custom_detail_action(self, request, *args, **kwargs): pass @@ -111,6 +111,16 @@ class InitializeViewSetsTestCase(TestCase): self.assertIn(attribute, dir(view)) +class GetExtraActionTests(TestCase): + + def test_extra_actions(self): + view = ActionViewSet() + actual = [action.__name__ for action in view.get_extra_actions()] + expected = ['custom_detail_action', 'custom_list_action', 'detail_action', 'list_action'] + + self.assertEqual(actual, expected) + + @override_settings(ROOT_URLCONF='tests.test_viewsets') class ReverseActionTests(TestCase): def test_default_basename(self): From 16645885007cf02b9085766185764ab4f95c8142 Mon Sep 17 00:00:00 2001 From: Aseem Shrey Date: Sun, 21 Jan 2018 20:22:21 +0530 Subject: [PATCH 052/520] Updated docs to use `pip show` Show the current DRF version using `pip show` Closes #5757 --- docs/topics/release-notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 2c45b70af..820fa731b 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -32,9 +32,9 @@ To upgrade Django REST framework to the latest version, use pip: pip install -U djangorestframework -You can determine your currently installed version using `pip freeze`: +You can determine your currently installed version using `pip show`: - pip freeze | grep djangorestframework + pip show djangorestframework --- From 052a20cd7b9a8410a147d4ef2ab5291ab0eb1d04 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Thu, 25 Jan 2018 21:43:55 -0800 Subject: [PATCH 053/520] Load 'static' instead of 'staticfiles' in templates (#5773) --- docs/topics/api-clients.md | 2 +- rest_framework/templates/rest_framework/admin.html | 2 +- rest_framework/templates/rest_framework/base.html | 2 +- rest_framework/templates/rest_framework/docs/error.html | 2 +- rest_framework/templates/rest_framework/docs/index.html | 2 +- .../templates/rest_framework/docs/langs/javascript-intro.html | 2 +- rest_framework/templates/rest_framework/login_base.html | 1 - 7 files changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/topics/api-clients.md b/docs/topics/api-clients.md index 019b48b3d..1de669b42 100644 --- a/docs/topics/api-clients.md +++ b/docs/topics/api-clients.md @@ -395,7 +395,7 @@ Once the API documentation URLs are installed, you'll be able to include both th /static/rest_framework/js/coreapi-0.1.1.js /docs/schema.js --> - {% load staticfiles %} + {% load static %} diff --git a/rest_framework/templates/rest_framework/admin.html b/rest_framework/templates/rest_framework/admin.html index de011cd09..0f588c2d7 100644 --- a/rest_framework/templates/rest_framework/admin.html +++ b/rest_framework/templates/rest_framework/admin.html @@ -1,4 +1,4 @@ -{% load staticfiles %} +{% load static %} {% load i18n %} {% load rest_framework %} diff --git a/rest_framework/templates/rest_framework/base.html b/rest_framework/templates/rest_framework/base.html index 14007aa52..5d4d258be 100644 --- a/rest_framework/templates/rest_framework/base.html +++ b/rest_framework/templates/rest_framework/base.html @@ -1,4 +1,4 @@ -{% load staticfiles %} +{% load static %} {% load i18n %} {% load rest_framework %} diff --git a/rest_framework/templates/rest_framework/docs/error.html b/rest_framework/templates/rest_framework/docs/error.html index 8015bd7f0..1155e7ece 100644 --- a/rest_framework/templates/rest_framework/docs/error.html +++ b/rest_framework/templates/rest_framework/docs/error.html @@ -1,4 +1,4 @@ -{% load staticfiles %} +{% load static %} diff --git a/rest_framework/templates/rest_framework/docs/index.html b/rest_framework/templates/rest_framework/docs/index.html index de704ab51..814910344 100644 --- a/rest_framework/templates/rest_framework/docs/index.html +++ b/rest_framework/templates/rest_framework/docs/index.html @@ -1,4 +1,4 @@ -{% load staticfiles %} +{% load static %} diff --git a/rest_framework/templates/rest_framework/docs/langs/javascript-intro.html b/rest_framework/templates/rest_framework/docs/langs/javascript-intro.html index 8ef880cbc..a6938fc45 100644 --- a/rest_framework/templates/rest_framework/docs/langs/javascript-intro.html +++ b/rest_framework/templates/rest_framework/docs/langs/javascript-intro.html @@ -1,5 +1,5 @@ {% load rest_framework %} -{% load staticfiles %} +{% load static %}
    {% code html %}
     
     {% endcode %}
    diff --git a/rest_framework/templates/rest_framework/login_base.html b/rest_framework/templates/rest_framework/login_base.html index 631ad71ba..ba4891708 100644 --- a/rest_framework/templates/rest_framework/login_base.html +++ b/rest_framework/templates/rest_framework/login_base.html @@ -1,5 +1,4 @@ {% extends "rest_framework/base.html" %} -{% load staticfiles %} {% load rest_framework %} {% block body %} From 3e5d3752e77af14acc009743c8648d06f09246e6 Mon Sep 17 00:00:00 2001 From: Max Goodridge Date: Mon, 29 Jan 2018 07:41:55 +0000 Subject: [PATCH 054/520] Fixed a typo (#5783) --- docs/api-guide/fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 403c2b865..78fb3f83e 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -801,7 +801,7 @@ The [drf-compound-fields][drf-compound-fields] package provides "compound" seria The [drf-extra-fields][drf-extra-fields] package provides extra serializer fields for REST framework, including `Base64ImageField` and `PointField` classes. -## djangrestframework-recursive +## djangorestframework-recursive the [djangorestframework-recursive][djangorestframework-recursive] package provides a `RecursiveField` for serializing and deserializing recursive structures From 2677f59d5d1cb1b0170eabb516478180da8aa610 Mon Sep 17 00:00:00 2001 From: Matt Prahl Date: Mon, 29 Jan 2018 09:33:14 -0500 Subject: [PATCH 055/520] Refer to "NamespaceVersioning" instead of "NamespacedVersioning" in the documentation (#5754) --- docs/api-guide/versioning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/versioning.md b/docs/api-guide/versioning.md index 8e62c70f1..c106e536d 100644 --- a/docs/api-guide/versioning.md +++ b/docs/api-guide/versioning.md @@ -37,7 +37,7 @@ The `reverse` function included by REST framework ties in with the versioning sc The above function will apply any URL transformations appropriate to the request version. For example: -* If `NamespacedVersioning` was being used, and the API version was 'v1', then the URL lookup used would be `'v1:bookings-list'`, which might resolve to a URL like `http://example.org/v1/bookings/`. +* If `NamespaceVersioning` was being used, and the API version was 'v1', then the URL lookup used would be `'v1:bookings-list'`, which might resolve to a URL like `http://example.org/v1/bookings/`. * If `QueryParameterVersioning` was being used, and the API version was `1.0`, then the returned URL might be something like `http://example.org/bookings/?version=1.0` #### Versioned APIs and hyperlinked serializers From 769bc1336fd5d6a7fcf10d8be3b374c3e7a21bb3 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Tue, 30 Jan 2018 08:45:09 +0100 Subject: [PATCH 056/520] ErrorDetail: add __eq__/__ne__ and __repr__ (#5787) This adds `__eq__` to handle `code` in comparisons. When comparing an ErrorDetail to a string (missing `code` there) the ErrorDetail's `code` is ignored, but otherwise it is taken into account. --- rest_framework/exceptions.py | 17 +++++++++++++++++ tests/test_exceptions.py | 27 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/rest_framework/exceptions.py b/rest_framework/exceptions.py index d885ba643..492872ae5 100644 --- a/rest_framework/exceptions.py +++ b/rest_framework/exceptions.py @@ -14,6 +14,7 @@ from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext from rest_framework import status +from rest_framework.compat import unicode_to_repr from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList @@ -73,6 +74,22 @@ class ErrorDetail(six.text_type): self.code = code return self + def __eq__(self, other): + r = super(ErrorDetail, self).__eq__(other) + try: + return r and self.code == other.code + except AttributeError: + return r + + def __ne__(self, other): + return not self.__eq__(other) + + def __repr__(self): + return unicode_to_repr('ErrorDetail(string=%r, code=%r)' % ( + six.text_type(self), + self.code, + )) + class APIException(Exception): """ diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 176aeb174..006191a49 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -53,6 +53,33 @@ class ExceptionTestCase(TestCase): 'code': 'throttled'} +class ErrorDetailTests(TestCase): + + def test_eq(self): + assert ErrorDetail('msg') == ErrorDetail('msg') + assert ErrorDetail('msg', 'code') == ErrorDetail('msg', code='code') + + assert ErrorDetail('msg') == 'msg' + assert ErrorDetail('msg', 'code') == 'msg' + + def test_ne(self): + assert ErrorDetail('msg1') != ErrorDetail('msg2') + assert ErrorDetail('msg') != ErrorDetail('msg', code='invalid') + + assert ErrorDetail('msg1') != 'msg2' + assert ErrorDetail('msg1', 'code') != 'msg2' + + def test_repr(self): + assert repr(ErrorDetail('msg1')) == \ + 'ErrorDetail(string={!r}, code=None)'.format('msg1') + assert repr(ErrorDetail('msg1', 'code')) == \ + 'ErrorDetail(string={!r}, code={!r})'.format('msg1', 'code') + + def test_str(self): + assert str(ErrorDetail('msg1')) == 'msg1' + assert str(ErrorDetail('msg1', 'code')) == 'msg1' + + class TranslationTests(TestCase): @translation.override('fr') From ece4171ae40e0956c9d69e317fee1f96c427b113 Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Tue, 30 Jan 2018 03:08:06 -0500 Subject: [PATCH 057/520] Replace `background-attachment: fixed` in docs (#5777) Fixed backgrounds have performance issues on large displays. --- docs_theme/css/default.css | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/docs_theme/css/default.css b/docs_theme/css/default.css index a0a286b22..bb17a3a11 100644 --- a/docs_theme/css/default.css +++ b/docs_theme/css/default.css @@ -160,9 +160,19 @@ body, .navbar .navbar-inner .container-fluid{ margin: 0 auto; } -body{ - background: url("../img/grid.png") repeat-x; - background-attachment: fixed; +/* Replacement for `body { background-attachment: fixed; }`, which + has performance issues when scrolling on large displays. */ +body::before { + content: ' '; + position: fixed; + width: 100%; + height: 100%; + top: 0; + left: 0; + background-color: #f8f8f8; + background: url(../img/grid.png) repeat-x; + will-change: transform; + z-index: -1; } From df77f7bb9d40f83d92848fd0afd5c61e281eeb48 Mon Sep 17 00:00:00 2001 From: Si Feng Date: Tue, 30 Jan 2018 14:10:02 -0800 Subject: [PATCH 058/520] Make 404 & 403 responses consistent with `exceptions.APIException` output (#5763) --- rest_framework/views.py | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/rest_framework/views.py b/rest_framework/views.py index f9ee7fb53..1f51517db 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -8,10 +8,8 @@ from django.core.exceptions import PermissionDenied from django.db import connection, models, transaction from django.http import Http404 from django.http.response import HttpResponseBase -from django.utils import six from django.utils.cache import cc_delim_re, patch_vary_headers from django.utils.encoding import smart_text -from django.utils.translation import ugettext_lazy as _ from django.views.decorators.csrf import csrf_exempt from django.views.generic import View @@ -70,6 +68,11 @@ def exception_handler(exc, context): Any unhandled exceptions may return `None`, which will cause a 500 error to be raised. """ + if isinstance(exc, Http404): + exc = exceptions.NotFound() + elif isinstance(exc, PermissionDenied): + exc = exceptions.PermissionDenied() + if isinstance(exc, exceptions.APIException): headers = {} if getattr(exc, 'auth_header', None): @@ -85,20 +88,6 @@ def exception_handler(exc, context): set_rollback() return Response(data, status=exc.status_code, headers=headers) - elif isinstance(exc, Http404): - msg = _('Not found.') - data = {'detail': six.text_type(msg)} - - set_rollback() - return Response(data, status=status.HTTP_404_NOT_FOUND) - - elif isinstance(exc, PermissionDenied): - msg = _('Permission denied.') - data = {'detail': six.text_type(msg)} - - set_rollback() - return Response(data, status=status.HTTP_403_FORBIDDEN) - return None From 2fa04caf7c2482f7e8bbf69052ad48af304da9a2 Mon Sep 17 00:00:00 2001 From: Veli-Matti Helke Date: Wed, 31 Jan 2018 15:25:57 +0200 Subject: [PATCH 059/520] small fix to API documentation: schemas (#5796) adding missing parameters to get_manual_fields() --- docs/api-guide/schemas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index 3284c9e1b..eb2799859 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -631,7 +631,7 @@ def get_manual_fields(self, path, method): if method=='POST': extra_fields = # ... list of extra fields for POST ... - manual_fields = super().get_manual_fields() + manual_fields = super().get_manual_fields(path, method) return manual_fields + extra_fields ``` From 3c7b3ac6df1deadee57ec9c01ffd58d804559389 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Thu, 1 Feb 2018 16:02:29 +0100 Subject: [PATCH 060/520] Updated step 1 of contributing guide (#5799) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Create a fork, then clone it. * Link to GitHub’s How-To. --- docs/topics/contributing.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/topics/contributing.md b/docs/topics/contributing.md index 19976b00b..9cc6ccee0 100644 --- a/docs/topics/contributing.md +++ b/docs/topics/contributing.md @@ -48,9 +48,15 @@ Getting involved in triaging incoming issues is a good way to start contributing # Development -To start developing on Django REST framework, clone the repo: +To start developing on Django REST framework, first create a Fork from the +[Django REST Framework repo][repo] on GitHub. - git clone git@github.com:encode/django-rest-framework.git +Then clone your fork. The clone command will look like this, with your GitHub +username instead of YOUR-USERNAME: + + git clone https://github.com/YOUR-USERNAME/Spoon-Knife + +See GitHub's [_Fork a Repo_][how-to-fork] Guide for more help. Changes should broadly follow the [PEP 8][pep-8] style conventions, and we recommend you set up your editor to automatically indicate non-conforming styles. @@ -210,3 +216,5 @@ If you want to draw attention to a note or warning, use a pair of enclosing line [markdown]: https://daringfireball.net/projects/markdown/basics [docs]: https://github.com/encode/django-rest-framework/tree/master/docs [mou]: http://mouapp.com/ +[repo]: https://github.com/encode/django-rest-framework +[how-to-fork]: https://help.github.com/articles/fork-a-repo/ From 27f32faee4dd96c5baee920d3a8f42ab4364782b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Thu, 1 Feb 2018 16:14:35 +0100 Subject: [PATCH 061/520] Fix schema generation for PrimaryKeyRelatedField (#5764) By default all subclasses of RelatedField are output as string fields in the schema, which works well for StringRelatedField, SlugRelatedField or HyperlinkedRelatedField. Handle the common case of a PrimaryKeyRelatedField pointing to an AutoField. --- rest_framework/schemas/inspectors.py | 8 +++++ tests/test_schemas.py | 47 +++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py index 413b9c0ac..8ef783683 100644 --- a/rest_framework/schemas/inspectors.py +++ b/rest_framework/schemas/inspectors.py @@ -50,6 +50,14 @@ def field_to_schema(field): title=title, description=description ) + elif isinstance(field, serializers.PrimaryKeyRelatedField): + schema_cls = coreschema.String + model = getattr(field.queryset, 'model', None) + if model is not None: + model_field = model._meta.pk + if isinstance(model_field, models.AutoField): + schema_cls = coreschema.Integer + return schema_cls(title=title, description=description) elif isinstance(field, serializers.RelatedField): return coreschema.String(title=title, description=description) elif isinstance(field, serializers.MultipleChoiceField): diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 1cbee0695..1abe5d2a1 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -23,7 +23,7 @@ from rest_framework.utils import formatting from rest_framework.views import APIView from rest_framework.viewsets import GenericViewSet, ModelViewSet -from .models import BasicModel +from .models import BasicModel, ForeignKeySource factory = APIRequestFactory() @@ -556,6 +556,51 @@ class TestSchemaGeneratorWithRestrictedViewSets(TestCase): assert schema == expected +class ForeignKeySourceSerializer(serializers.ModelSerializer): + class Meta: + model = ForeignKeySource + fields = ('id', 'name', 'target') + + +class ForeignKeySourceView(generics.CreateAPIView): + queryset = ForeignKeySource.objects.all() + serializer_class = ForeignKeySourceSerializer + + +@unittest.skipUnless(coreapi, 'coreapi is not installed') +class TestSchemaGeneratorWithForeignKey(TestCase): + def setUp(self): + self.patterns = [ + url(r'^example/?$', ForeignKeySourceView.as_view()), + ] + + def test_schema_for_regular_views(self): + """ + Ensure that AutoField foreign keys are output as Integer. + """ + generator = SchemaGenerator(title='Example API', patterns=self.patterns) + schema = generator.get_schema() + + expected = coreapi.Document( + url='', + title='Example API', + content={ + 'example': { + 'create': coreapi.Link( + url='/example/', + action='post', + encoding='application/json', + fields=[ + coreapi.Field('name', required=True, location='form', schema=coreschema.String(title='Name')), + coreapi.Field('target', required=True, location='form', schema=coreschema.Integer(description='Target', title='Target')), + ] + ) + } + } + ) + assert schema == expected + + @unittest.skipUnless(coreapi, 'coreapi is not installed') class Test4605Regression(TestCase): def test_4605_regression(self): From a8d129b7da847ab12a1ecaeefa54c0d6d330184e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Tue, 23 Jan 2018 21:06:24 +0100 Subject: [PATCH 062/520] Represent serializer DictField as an Object in schema DictFields were incorrectly being output as String in the schema. This pull request outputs an Object instead and adds a unit test. Update s/detail_route/action/ after rebase --- rest_framework/schemas/inspectors.py | 5 +++++ tests/test_schemas.py | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py index 8ef783683..86c6cb71a 100644 --- a/rest_framework/schemas/inspectors.py +++ b/rest_framework/schemas/inspectors.py @@ -34,6 +34,11 @@ def field_to_schema(field): title=title, description=description ) + elif isinstance(field, serializers.DictField): + return coreschema.Object( + title=title, + description=description + ) elif isinstance(field, serializers.Serializer): return coreschema.Object( properties=OrderedDict([ diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 1abe5d2a1..267c44585 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -49,6 +49,10 @@ class ExampleSerializer(serializers.Serializer): hidden = serializers.HiddenField(default='hello') +class AnotherSerializerWithDictField(serializers.Serializer): + a = serializers.DictField() + + class AnotherSerializerWithListFields(serializers.Serializer): a = serializers.ListField(child=serializers.IntegerField()) b = serializers.ListSerializer(child=serializers.CharField()) @@ -72,6 +76,13 @@ class ExampleViewSet(ModelViewSet): """ return super(ExampleSerializer, self).retrieve(self, request) + @action(methods=['post'], detail=True, serializer_class=AnotherSerializerWithDictField) + def custom_action_with_dict_field(self, request, pk): + """ + A custom action using a dict field in the serializer. + """ + return super(ExampleSerializer, self).retrieve(self, request) + @action(methods=['post'], detail=True, serializer_class=AnotherSerializerWithListFields) def custom_action_with_list_fields(self, request, pk): """ @@ -198,6 +209,16 @@ class TestRouterGeneratedSchema(TestCase): coreapi.Field('d', required=False, location='form', schema=coreschema.String(title='D')), ] ), + 'custom_action_with_dict_field': coreapi.Link( + url='/example/{id}/custom_action_with_dict_field/', + action='post', + encoding='application/json', + description='A custom action using a dict field in the serializer.', + fields=[ + coreapi.Field('id', required=True, location='path', schema=coreschema.String()), + coreapi.Field('a', required=True, location='form', schema=coreschema.Object(title='A')), + ] + ), 'custom_action_with_list_fields': coreapi.Link( url='/example/{id}/custom_action_with_list_fields/', action='post', From 878fe895dcd35297be798083a704ee74dd8709ba Mon Sep 17 00:00:00 2001 From: "Fraire, Santiago" Date: Fri, 5 Jan 2018 13:57:52 +0100 Subject: [PATCH 063/520] Docs: Added example reimplementing ObtainAuthToken Closes #5802 --- docs/api-guide/authentication.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 0704118bd..e33023c40 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -205,11 +205,39 @@ The `obtain_auth_token` view will return a JSON response when valid `username` a { 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' } -Note that the default `obtain_auth_token` view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. If you need a customized version of the `obtain_auth_token` view, you can do so by overriding the `ObtainAuthToken` view class, and using that in your url conf instead. +Note that the default `obtain_auth_token` view explicitly uses JSON requests and responses, rather than using default renderer and parser classes in your settings. By default there are no permissions or throttling applied to the `obtain_auth_token` view. If you do wish to apply throttling you'll need to override the view class, and include them using the `throttle_classes` attribute. +If you need a customized version of the `obtain_auth_token` view, you can do so by subclassing the `ObtainAuthToken` view class, and using that in your url conf instead. + +For example, you may return additional user information beyond the `token` value: + + from rest_framework.authtoken.views import ObtainAuthToken + from rest_framework.authtoken.models import Token + from rest_framework.response import Response + + class CustomAuthToken(ObtainAuthToken): + + def post(self, request, *args, **kwargs): + serializer = self.serializer_class(data=request.data, + context={'request': request}) + serializer.is_valid(raise_exception=True) + user = serializer.validated_data['user'] + token, created = Token.objects.get_or_create(user=user) + return Response({ + 'token': token.key, + 'user_id': user.pk, + 'email': user.email + }) + +And in your `urls.py`: + + urlpatterns += [ + url(r'^api-token-auth/', CustomAuthToken.as_view()) + ] + ##### With Django admin From 0d5a3a00b0465a27ecfa6947478cbd57ac2432f2 Mon Sep 17 00:00:00 2001 From: Paulo Scardine Date: Sun, 17 Dec 2017 02:11:15 -0200 Subject: [PATCH 064/520] Add schema to ObtainAuthToken Add encoding parameter to ManualSchema Closes #5676 * Fixed lint errors * Added docs for ManualSchema encoding parameter --- docs/api-guide/schemas.md | 2 ++ rest_framework/authtoken/views.py | 26 ++++++++++++++++++++++++++ rest_framework/schemas/inspectors.py | 5 +++-- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index eb2799859..aaefe3db8 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -669,6 +669,8 @@ The `ManualSchema` constructor takes two arguments: **`description`**: A string description. Optional. +**`encoding`**: Default `None`. A string encoding, e.g `application/json`. Optional. + --- ## Core API diff --git a/rest_framework/authtoken/views.py b/rest_framework/authtoken/views.py index 6254d2f7f..6eed3782e 100644 --- a/rest_framework/authtoken/views.py +++ b/rest_framework/authtoken/views.py @@ -3,6 +3,9 @@ from rest_framework.authtoken.models import Token from rest_framework.authtoken.serializers import AuthTokenSerializer from rest_framework.response import Response from rest_framework.views import APIView +from rest_framework.schemas import ManualSchema +import coreapi +import coreschema class ObtainAuthToken(APIView): @@ -11,6 +14,29 @@ class ObtainAuthToken(APIView): parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,) renderer_classes = (renderers.JSONRenderer,) serializer_class = AuthTokenSerializer + schema = ManualSchema( + fields=[ + coreapi.Field( + name="username", + required=True, + location='form', + schema=coreschema.String( + title="Username", + description="Valid username for authentication", + ), + ), + coreapi.Field( + name="password", + required=True, + location='form', + schema=coreschema.String( + title="Password", + description="Valid password for authentication", + ), + ), + ], + encoding="application/json", + ) def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data, diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py index 86c6cb71a..171b88b0b 100644 --- a/rest_framework/schemas/inspectors.py +++ b/rest_framework/schemas/inspectors.py @@ -445,7 +445,7 @@ class ManualSchema(ViewInspector): Allows providing a list of coreapi.Fields, plus an optional description. """ - def __init__(self, fields, description=''): + def __init__(self, fields, description='', encoding=None): """ Parameters: @@ -455,6 +455,7 @@ class ManualSchema(ViewInspector): assert all(isinstance(f, coreapi.Field) for f in fields), "`fields` must be a list of coreapi.Field instances" self._fields = fields self._description = description + self._encoding = encoding def get_link(self, path, method, base_url): @@ -464,7 +465,7 @@ class ManualSchema(ViewInspector): return coreapi.Link( url=urlparse.urljoin(base_url, path), action=method.lower(), - encoding=None, + encoding=self._encoding, fields=self._fields, description=self._description ) From c456b3c510870ed8e0117cb69abc2360a7aa0fca Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Mon, 5 Feb 2018 10:24:13 -0500 Subject: [PATCH 065/520] Fix request formdata handling (#5800) * Rename 'wsgi' request test to more accurate 'http' * Test duplicate request stream parsing * Fix setting post/files on the underlying request --- rest_framework/request.py | 9 +++--- tests/test_request.py | 63 ++++++++++++++++++++++++++++++++++----- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/rest_framework/request.py b/rest_framework/request.py index 7e4daf274..9d4f73d30 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -278,10 +278,11 @@ class Request(object): else: self._full_data = self._data - # copy data & files refs to the underlying request so that closable - # objects are handled appropriately. - self._request._post = self.POST - self._request._files = self.FILES + # if a form media type, copy data & files refs to the underlying + # http request so that closable objects are handled appropriately. + if is_form_media_type(self.content_type): + self._request._post = self.POST + self._request._files = self.FILES def _load_stream(self): """ diff --git a/tests/test_request.py b/tests/test_request.py index 8c680baa0..83d295a12 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -13,6 +13,7 @@ from django.contrib.auth.middleware import AuthenticationMiddleware from django.contrib.auth.models import User from django.contrib.sessions.middleware import SessionMiddleware from django.core.files.uploadedfile import SimpleUploadedFile +from django.http.request import RawPostDataException from django.test import TestCase, override_settings from django.utils import six @@ -137,6 +138,11 @@ class MockView(APIView): return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR) +class EchoView(APIView): + def post(self, request): + return Response(status=status.HTTP_200_OK, data=request.data) + + class FileUploadView(APIView): def post(self, request): filenames = [file.temporary_file_path() for file in request.FILES.values()] @@ -149,6 +155,7 @@ class FileUploadView(APIView): urlpatterns = [ url(r'^$', MockView.as_view()), + url(r'^echo/$', EchoView.as_view()), url(r'^upload/$', FileUploadView.as_view()) ] @@ -271,24 +278,64 @@ class TestSecure(TestCase): assert request.scheme == 'https' -class TestWSGIRequestProxy(TestCase): - def test_attribute_access(self): - wsgi_request = factory.get('/') - request = Request(wsgi_request) +class TestHttpRequest(TestCase): + def test_attribute_access_proxy(self): + http_request = factory.get('/') + request = Request(http_request) inner_sentinel = object() - wsgi_request.inner_property = inner_sentinel + http_request.inner_property = inner_sentinel assert request.inner_property is inner_sentinel outer_sentinel = object() request.inner_property = outer_sentinel assert request.inner_property is outer_sentinel - def test_exception(self): + def test_exception_proxy(self): # ensure the exception message is not for the underlying WSGIRequest - wsgi_request = factory.get('/') - request = Request(wsgi_request) + http_request = factory.get('/') + request = Request(http_request) message = "'Request' object has no attribute 'inner_property'" with self.assertRaisesMessage(AttributeError, message): request.inner_property + + @override_settings(ROOT_URLCONF='tests.test_request') + def test_duplicate_request_stream_parsing_exception(self): + """ + Check assumption that duplicate stream parsing will result in a + `RawPostDataException` being raised. + """ + response = APIClient().post('/echo/', data={'a': 'b'}, format='json') + request = response.renderer_context['request'] + + # ensure that request stream was consumed by json parser + assert request.content_type.startswith('application/json') + assert response.data == {'a': 'b'} + + # pass same HttpRequest to view, stream already consumed + with pytest.raises(RawPostDataException): + EchoView.as_view()(request._request) + + @override_settings(ROOT_URLCONF='tests.test_request') + def test_duplicate_request_form_data_access(self): + """ + Form data is copied to the underlying django request for middleware + and file closing reasons. Duplicate processing of a request with form + data is 'safe' in so far as accessing `request.POST` does not trigger + the duplicate stream parse exception. + """ + response = APIClient().post('/echo/', data={'a': 'b'}) + request = response.renderer_context['request'] + + # ensure that request stream was consumed by form parser + assert request.content_type.startswith('multipart/form-data') + assert response.data == {'a': ['b']} + + # pass same HttpRequest to view, form data set on underlying request + response = EchoView.as_view()(request._request) + request = response.renderer_context['request'] + + # ensure that request stream was consumed by form parser + assert request.content_type.startswith('multipart/form-data') + assert response.data == {'a': ['b']} From 1bc826e6fd1c5fc70a3f9af2e89bb0a575e6ce7b Mon Sep 17 00:00:00 2001 From: Ryan P Kilby Date: Wed, 7 Feb 2018 14:46:17 -0500 Subject: [PATCH 066/520] Fix authtoken views imports (#5818) --- rest_framework/authtoken/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rest_framework/authtoken/views.py b/rest_framework/authtoken/views.py index 6eed3782e..ff53c01ba 100644 --- a/rest_framework/authtoken/views.py +++ b/rest_framework/authtoken/views.py @@ -1,11 +1,11 @@ +import coreapi +import coreschema from rest_framework import parsers, renderers from rest_framework.authtoken.models import Token from rest_framework.authtoken.serializers import AuthTokenSerializer from rest_framework.response import Response -from rest_framework.views import APIView from rest_framework.schemas import ManualSchema -import coreapi -import coreschema +from rest_framework.views import APIView class ObtainAuthToken(APIView): From 1438719979c92e9c0895de6f29d557df774eccb3 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Thu, 8 Feb 2018 09:00:44 +0100 Subject: [PATCH 067/520] requirements-testing: update pytest to 3.4.0 (#5815) --- requirements/requirements-testing.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements/requirements-testing.txt b/requirements/requirements-testing.txt index 72ce56d26..e0db14d44 100644 --- a/requirements/requirements-testing.txt +++ b/requirements/requirements-testing.txt @@ -1,4 +1,4 @@ -# PyTest for running the tests. -pytest==3.2.5 +# Pytest for running the tests. +pytest==3.4.0 pytest-django==3.1.2 pytest-cov==2.5.1 From d1c92c81ff86fb8c6e9ccf2b394852595ff52141 Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Thu, 8 Feb 2018 05:04:51 -0300 Subject: [PATCH 068/520] Add Django Rest Framework Role Filters to Third party packages (#5809) --- docs/api-guide/permissions.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 72cbeab91..f5fc214cd 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -269,6 +269,10 @@ The [Django Rest Framework Roles][django-rest-framework-roles] package makes it The [Django Rest Framework API Key][django-rest-framework-api-key] package allows you to ensure that every request made to the server requires an API key header. You can generate one from the django admin interface. +## Django Rest Framework Role Filters + +The [Django Rest Framework Role Filters][django-rest-framework-role-filters] package provides simple filtering over multiple types of roles. + [cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html [authentication]: authentication.md [throttling]: throttling.md @@ -282,3 +286,4 @@ The [Django Rest Framework API Key][django-rest-framework-api-key] package allow [dry-rest-permissions]: https://github.com/Helioscene/dry-rest-permissions [django-rest-framework-roles]: https://github.com/computer-lab/django-rest-framework-roles [django-rest-framework-api-key]: https://github.com/manosim/django-rest-framework-api-key +[django-rest-framework-role-filters]: https://github.com/allisson/django-rest-framework-role-filters From 7d0d22ffaabfcfa57f49fcf086667faf7c2509c5 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Mon, 12 Feb 2018 15:14:44 +0100 Subject: [PATCH 069/520] Use single copy of static assets. Update jQuery (#5823) * Move font-awesome to top level. * Use top-level jQuery & Bootstrap * Update to jQuery v3.3.1 Compatible with Bootstrap v3.3.7 c.f. https://github.com/twbs/bootstrap/issues/16834#issuecomment-251996660 * Re-add bootstrap-theme --- .../{docs => }/css/bootstrap-theme.min.css | 0 .../{docs => }/css/font-awesome-4.0.3.css | 0 .../rest_framework/docs/css/bootstrap.min.css | 6 - .../fonts/glyphicons-halflings-regular.eot | Bin 20127 -> 0 bytes .../fonts/glyphicons-halflings-regular.svg | 288 ------------------ .../fonts/glyphicons-halflings-regular.ttf | Bin 45404 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 23424 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 18028 -> 0 bytes .../rest_framework/docs/js/bootstrap.min.js | 7 - .../docs/js/jquery-1.10.2.min.js | 6 - .../{docs => }/fonts/fontawesome-webfont.eot | Bin .../{docs => }/fonts/fontawesome-webfont.svg | 0 .../{docs => }/fonts/fontawesome-webfont.ttf | Bin .../{docs => }/fonts/fontawesome-webfont.woff | Bin .../rest_framework/js/jquery-1.12.4.min.js | 5 - .../rest_framework/js/jquery-3.3.1.min.js | 2 + .../templates/rest_framework/admin.html | 2 +- .../templates/rest_framework/base.html | 2 +- .../templates/rest_framework/docs/error.html | 2 +- .../templates/rest_framework/docs/index.html | 10 +- 20 files changed, 10 insertions(+), 320 deletions(-) rename rest_framework/static/rest_framework/{docs => }/css/bootstrap-theme.min.css (100%) rename rest_framework/static/rest_framework/{docs => }/css/font-awesome-4.0.3.css (100%) delete mode 100644 rest_framework/static/rest_framework/docs/css/bootstrap.min.css delete mode 100644 rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.eot delete mode 100644 rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.svg delete mode 100644 rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.ttf delete mode 100644 rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.woff delete mode 100644 rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.woff2 delete mode 100644 rest_framework/static/rest_framework/docs/js/bootstrap.min.js delete mode 100644 rest_framework/static/rest_framework/docs/js/jquery-1.10.2.min.js rename rest_framework/static/rest_framework/{docs => }/fonts/fontawesome-webfont.eot (100%) rename rest_framework/static/rest_framework/{docs => }/fonts/fontawesome-webfont.svg (100%) rename rest_framework/static/rest_framework/{docs => }/fonts/fontawesome-webfont.ttf (100%) rename rest_framework/static/rest_framework/{docs => }/fonts/fontawesome-webfont.woff (100%) delete mode 100644 rest_framework/static/rest_framework/js/jquery-1.12.4.min.js create mode 100644 rest_framework/static/rest_framework/js/jquery-3.3.1.min.js diff --git a/rest_framework/static/rest_framework/docs/css/bootstrap-theme.min.css b/rest_framework/static/rest_framework/css/bootstrap-theme.min.css similarity index 100% rename from rest_framework/static/rest_framework/docs/css/bootstrap-theme.min.css rename to rest_framework/static/rest_framework/css/bootstrap-theme.min.css diff --git a/rest_framework/static/rest_framework/docs/css/font-awesome-4.0.3.css b/rest_framework/static/rest_framework/css/font-awesome-4.0.3.css similarity index 100% rename from rest_framework/static/rest_framework/docs/css/font-awesome-4.0.3.css rename to rest_framework/static/rest_framework/css/font-awesome-4.0.3.css diff --git a/rest_framework/static/rest_framework/docs/css/bootstrap.min.css b/rest_framework/static/rest_framework/docs/css/bootstrap.min.css deleted file mode 100644 index 82113bd8a..000000000 --- a/rest_framework/static/rest_framework/docs/css/bootstrap.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\002a"}.glyphicon-plus:before{content:"\002b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:rgba(0,0,0,0);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} -/*# sourceMappingURL=bootstrap.min.css.map */ diff --git a/rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.eot b/rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.eot deleted file mode 100644 index b93a4953fff68df523aa7656497ee339d6026d64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20127 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.ttf b/rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.ttf deleted file mode 100644 index 1413fc609ab6f21774de0cb7e01360095584f65b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45404 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 G`u_lkUM?>H diff --git a/rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.woff2 b/rest_framework/static/rest_framework/docs/fonts/glyphicons-halflings-regular.woff2 deleted file mode 100644 index 64539b54c3751a6d9adb44c8e3a45ba5a73b77f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18028 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 diff --git a/rest_framework/static/rest_framework/docs/js/bootstrap.min.js b/rest_framework/static/rest_framework/docs/js/bootstrap.min.js deleted file mode 100644 index be9574d70..000000000 --- a/rest_framework/static/rest_framework/docs/js/bootstrap.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under the MIT license - */ -if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&jdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth
    ',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-mo.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); diff --git a/rest_framework/static/rest_framework/docs/js/jquery-1.10.2.min.js b/rest_framework/static/rest_framework/docs/js/jquery-1.10.2.min.js deleted file mode 100644 index da4170647..000000000 --- a/rest_framework/static/rest_framework/docs/js/jquery-1.10.2.min.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license -//@ sourceMappingURL=jquery-1.10.2.min.map -*/ -(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="
    ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
    a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
    t
    ",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
    ",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t -}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
    ","
    "],area:[1,"",""],param:[1,"",""],thead:[1,"","
    "],tr:[2,"","
    "],col:[2,"","
    "],td:[3,"","
    "],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
    ","
    "]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); -u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("

    - + - + @@ -31,7 +31,7 @@ --- -**Note**: This is the documentation for the **version 3** of REST framework. Documentation for [version 2](http://tomchristie.github.io/rest-framework-2-docs/) is also available. +**Note**: This is the documentation for the **version 3** of REST framework. Documentation for [version 2](https://tomchristie.github.io/rest-framework-2-docs/) is also available. --- @@ -302,13 +302,13 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -[mozilla]: http://www.mozilla.org/en-US/about/ +[mozilla]: https://www.mozilla.org/en-US/about/ [redhat]: https://www.redhat.com/ [heroku]: https://www.heroku.com/ [eventbrite]: https://www.eventbrite.co.uk/about/ -[coreapi]: http://pypi.python.org/pypi/coreapi/ -[markdown]: http://pypi.python.org/pypi/Markdown/ -[django-filter]: http://pypi.python.org/pypi/django-filter +[coreapi]: https://pypi.python.org/pypi/coreapi/ +[markdown]: https://pypi.python.org/pypi/Markdown/ +[django-filter]: https://pypi.python.org/pypi/django-filter [django-crispy-forms]: https://github.com/maraujop/django-crispy-forms [django-guardian]: https://github.com/django-guardian/django-guardian [index]: . @@ -317,7 +317,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [serializer-section]: api-guide/serializers#serializers [modelserializer-section]: api-guide/serializers#modelserializer [functionview-section]: api-guide/views#function-based-views -[sandbox]: http://restframework.herokuapp.com/ +[sandbox]: https://restframework.herokuapp.com/ [sponsors]: https://fund.django-rest-framework.org/topics/funding/#our-sponsors [quickstart]: tutorial/quickstart.md @@ -385,7 +385,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [group]: https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework [botbot]: https://botbot.me/freenode/restframework/ -[stack-overflow]: http://stackoverflow.com/ -[django-rest-framework-tag]: http://stackoverflow.com/questions/tagged/django-rest-framework +[stack-overflow]: https://stackoverflow.com/ +[django-rest-framework-tag]: https://stackoverflow.com/questions/tagged/django-rest-framework [security-mail]: mailto:rest-framework-security@googlegroups.com [twitter]: https://twitter.com/_tomchristie diff --git a/docs/topics/2.4-announcement.md b/docs/topics/2.4-announcement.md index 8bbe61335..eb1037f17 100644 --- a/docs/topics/2.4-announcement.md +++ b/docs/topics/2.4-announcement.md @@ -29,7 +29,7 @@ The `DEFAULT_MODEL_SERIALIZER_CLASS` API setting is now also deprecated. ## Updated test runner -We now have a new test runner for developing against the project,, that uses the excellent [py.test](http://pytest.org) library. +We now have a new test runner for developing against the project,, that uses the excellent [py.test](https://docs.pytest.org/) library. To use it make sure you have first installed the test requirements. @@ -128,7 +128,7 @@ There are also a number of other features and bugfixes as [listed in the release Smarter [client IP identification for throttling][client-ip-identification], with the addition of the `NUM_PROXIES` setting. -Added the standardized `Retry-After` header to throttled responses, as per [RFC 6585](http://tools.ietf.org/html/rfc6585). This should now be used in preference to the custom `X-Throttle-Wait-Seconds` header which will be fully deprecated in 3.0. +Added the standardized `Retry-After` header to throttled responses, as per [RFC 6585](https://tools.ietf.org/html/rfc6585). This should now be used in preference to the custom `X-Throttle-Wait-Seconds` header which will be fully deprecated in 3.0. ## Deprecations diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 25c36b2ca..03a2c281c 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -32,7 +32,7 @@ Significant new functionality continues to be planned for the 3.1 and 3.2 releas #### REST framework: Under the hood. -This talk from the [Django: Under the Hood](http://www.djangounderthehood.com/) event in Amsterdam, Nov 2014, gives some good background context on the design decisions behind 3.0. +This talk from the [Django: Under the Hood](https://www.djangounderthehood.com/) event in Amsterdam, Nov 2014, gives some good background context on the design decisions behind 3.0. @@ -959,7 +959,7 @@ The 3.2 release is planned to introduce an alternative admin-style interface to You can follow development on the GitHub site, where we use [milestones to indicate planning timescales](https://github.com/encode/django-rest-framework/milestones). -[kickstarter]: http://kickstarter.com/projects/tomchristie/django-rest-framework-3 +[kickstarter]: https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3 [sponsors]: http://www.django-rest-framework.org/topics/kickstarter-announcement/#sponsors [mixins.py]: https://github.com/encode/django-rest-framework/blob/master/rest_framework/mixins.py [django-localization]: https://docs.djangoproject.com/en/stable/topics/i18n/translation/#localization-how-to-create-language-files diff --git a/docs/topics/3.1-announcement.md b/docs/topics/3.1-announcement.md index 6cca40665..a86fa943a 100644 --- a/docs/topics/3.1-announcement.md +++ b/docs/topics/3.1-announcement.md @@ -159,10 +159,10 @@ The change also means we can be more flexible with which external packages we re The following packages are now moved out of core and should be separately installed: -* OAuth - [djangorestframework-oauth](http://jpadilla.github.io/django-rest-framework-oauth/) -* XML - [djangorestframework-xml](http://jpadilla.github.io/django-rest-framework-xml) -* YAML - [djangorestframework-yaml](http://jpadilla.github.io/django-rest-framework-yaml) -* JSONP - [djangorestframework-jsonp](http://jpadilla.github.io/django-rest-framework-jsonp) +* OAuth - [djangorestframework-oauth](https://jpadilla.github.io/django-rest-framework-oauth/) +* XML - [djangorestframework-xml](https://jpadilla.github.io/django-rest-framework-xml) +* YAML - [djangorestframework-yaml](https://jpadilla.github.io/django-rest-framework-yaml) +* JSONP - [djangorestframework-jsonp](https://jpadilla.github.io/django-rest-framework-jsonp) It's worth reiterating that this change in policy shouldn't mean any work in your codebase other than adding a new requirement and modifying some import paths. For example to install XML rendering, you would now do: diff --git a/docs/topics/3.5-announcement.md b/docs/topics/3.5-announcement.md index 701ab48eb..dca371b84 100644 --- a/docs/topics/3.5-announcement.md +++ b/docs/topics/3.5-announcement.md @@ -35,11 +35,11 @@ we strongly encourage you to invest in its continued development by