diff --git a/.travis.yml b/.travis.yml index 9a94e31b2..9543cb452 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,6 @@ language: python cache: pip dist: xenial - -sudo: false - matrix: fast_finish: true include: @@ -15,15 +12,17 @@ matrix: - { python: "3.5", env: DJANGO=1.11 } - { python: "3.5", env: DJANGO=2.0 } - { python: "3.5", env: DJANGO=2.1 } - - { python: "3.5", env: DJANGO=master } + - { python: "3.5", env: DJANGO=2.2 } - { python: "3.6", env: DJANGO=1.11 } - { python: "3.6", env: DJANGO=2.0 } - { python: "3.6", env: DJANGO=2.1 } + - { python: "3.6", env: DJANGO=2.2 } - { python: "3.6", env: DJANGO=master } - { python: "3.7", env: DJANGO=2.0 } - { python: "3.7", env: DJANGO=2.1 } + - { python: "3.7", env: DJANGO=2.2 } - { python: "3.7", env: DJANGO=master } - { python: "3.7", env: TOXENV=base } diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 8f2391d29..566bf9543 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -3,7 +3,7 @@ - [ ] I have verified that that issue exists against the `master` branch of Django REST framework. - [ ] I have searched for similar issues in both open and closed tickets and cannot find a duplicate. - [ ] This is not a usage question. (Those should be directed to the [discussion group](https://groups.google.com/forum/#!forum/django-rest-framework) instead.) -- [ ] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](https://www.django-rest-framework.org/topics/third-party-resources/#about-third-party-packages) where possible.) +- [ ] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](https://www.django-rest-framework.org/community/third-party-packages/#about-third-party-packages) where possible.) - [ ] I have reduced the issue to the simplest possible case. - [ ] I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.) diff --git a/README.md b/README.md index 02f8ca275..66079edf0 100644 --- a/README.md +++ b/README.md @@ -19,17 +19,15 @@ continued development by [signing up for a paid plan][funding]. The initial aim is to provide a single full-time position on REST framework. *Every single sign-up makes a significant impact towards making that possible.* -[![][rover-img]][rover-url] [![][sentry-img]][sentry-url] [![][stream-img]][stream-url] [![][rollbar-img]][rollbar-url] [![][cadre-img]][cadre-url] -[![][load-impact-img]][load-impact-url] [![][kloudless-img]][kloudless-url] -[![][auklet-img]][auklet-url] +[![][release-history-img]][release-history-url] [![][lightson-img]][lightson-url] -Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Rover][rover-url], [Sentry][sentry-url], [Stream][stream-url], [Rollbar][rollbar-url], [Cadre][cadre-url], [Load Impact][load-impact-url], [Kloudless][kloudless-url], [Auklet][auklet-url], and [Lights On Software][lightson-url]. +Many thanks to all our [wonderful sponsors][sponsors], and in particular to our premium backers, [Sentry][sentry-url], [Stream][stream-url], [Rollbar][rollbar-url], [Cadre][cadre-url], [Kloudless][kloudless-url], [Release History][release-history-url], and [Lights On Software][lightson-url]. --- @@ -56,7 +54,7 @@ There is a live example API for testing purposes, [available here][sandbox]. # Requirements * Python (2.7, 3.4, 3.5, 3.6, 3.7) -* Django (1.11, 2.0, 2.1) +* Django (1.11, 2.0, 2.1, 2.2) We **highly recommend** and only officially support the latest patch release of each Python and Django series. @@ -201,7 +199,7 @@ Send a description of the issue via email to [rest-framework-security@googlegrou [cadre-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/cadre-readme.png [load-impact-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/load-impact-readme.png [kloudless-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/kloudless-readme.png -[auklet-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/auklet-readme.png +[release-history-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/release-history.png [lightson-img]: https://raw.githubusercontent.com/encode/django-rest-framework/master/docs/img/premium/lightson-readme.png [rover-url]: http://jobs.rover.com/ @@ -211,7 +209,7 @@ Send a description of the issue via email to [rest-framework-security@googlegrou [cadre-url]: https://cadre.com/ [load-impact-url]: https://loadimpact.com/?utm_campaign=Sponsorship%20links&utm_source=drf&utm_medium=drf [kloudless-url]: https://hubs.ly/H0f30Lf0 -[auklet-url]: https://auklet.io/ +[release-history-url]: https://releasehistory.io [lightson-url]: https://lightsonsoftware.com [oauth1-section]: https://www.django-rest-framework.org/api-guide/authentication/#django-rest-framework-oauth diff --git a/docs/api-guide/caching.md b/docs/api-guide/caching.md index ff51aed06..5342345e4 100644 --- a/docs/api-guide/caching.md +++ b/docs/api-guide/caching.md @@ -13,7 +13,7 @@ provided in Django. Django provides a [`method_decorator`][decorator] to use decorators with class based views. This can be used with -with other cache decorators such as [`cache_page`][page] and +other cache decorators such as [`cache_page`][page] and [`vary_on_cookie`][cookie]. ```python diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 8d25d6c78..ede4f15ad 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -124,7 +124,14 @@ 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. +Note that Django 2.1 removed the `blank` kwarg from `models.BooleanField`. +Prior to Django 2.1 `models.BooleanField` fields were always `blank=True`. Thus +since Django 2.1 default `serializers.BooleanField` instances will be generated +without the `required` kwarg (i.e. equivalent to `required=True`) whereas with +previous versions of Django, default `BooleanField` instances will be generated +with a `required=False` option. If you want to control this behaviour manually, +explicitly declare the `BooleanField` on the serializer class, or use the +`extra_kwargs` option to set the `required` flag. Corresponds to `django.db.models.fields.BooleanField`. @@ -299,10 +306,11 @@ A date and time representation. Corresponds to `django.db.models.fields.DateTimeField`. -**Signature:** `DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)` +**Signature:** `DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None, default_timezone=None)` * `format` - A string representing the output format. If not specified, this defaults to the same value as the `DATETIME_FORMAT` settings key, which will be `'iso-8601'` unless set. Setting to a format string indicates that `to_representation` return values should be coerced to string output. Format strings are described below. Setting this value to `None` indicates that Python `datetime` objects should be returned by `to_representation`. In this case the datetime encoding will be determined by the renderer. * `input_formats` - A list of strings representing the input formats which may be used to parse the date. If not specified, the `DATETIME_INPUT_FORMATS` setting will be used, which defaults to `['iso-8601']`. +* `default_timezone` - A `pytz.timezone` representing the timezone. If not specified and the `USE_TZ` setting is enabled, this defaults to the [current timezone][django-current-timezone]. If `USE_TZ` is disabled, then datetime objects will be naive. #### `DateTimeField` format strings. @@ -828,3 +836,4 @@ The [django-rest-framework-hstore][django-rest-framework-hstore] package provide [django-rest-framework-hstore]: https://github.com/djangonauts/django-rest-framework-hstore [django-hstore]: https://github.com/djangonauts/django-hstore [python-decimal-rounding-modes]: https://docs.python.org/3/library/decimal.html#rounding-modes +[django-current-timezone]: https://docs.djangoproject.com/en/stable/topics/i18n/timezones/#default-time-zone-and-current-time-zone diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 84c6d8d63..8a500f386 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -127,7 +127,7 @@ Note that you can use both an overridden `.get_queryset()` and generic filtering """ model = Product serializer_class = ProductSerializer - filter_class = ProductFilter + filterset_class = ProductFilter def get_queryset(self): user = self.request.user @@ -160,13 +160,13 @@ Or add the filter backend to an individual View or ViewSet. ... filter_backends = (DjangoFilterBackend,) -If all you need is simple equality-based filtering, you can set a `filter_fields` attribute on the view, or viewset, listing the set of fields you wish to filter against. +If all you need is simple equality-based filtering, you can set a `filterset_fields` attribute on the view, or viewset, listing the set of fields you wish to filter against. class ProductList(generics.ListAPIView): queryset = Product.objects.all() serializer_class = ProductSerializer filter_backends = (DjangoFilterBackend,) - filter_fields = ('category', 'in_stock') + filterset_fields = ('category', 'in_stock') This will automatically create a `FilterSet` class for the given fields, and will allow you to make requests such as: @@ -188,7 +188,7 @@ When in use, the browsable API will include a `SearchFilter` control: The `SearchFilter` class will only be applied if the view has a `search_fields` attribute set. The `search_fields` attribute should be a list of names of text type fields on the model, such as `CharField` or `TextField`. from rest_framework import filters - + class UserListView(generics.ListAPIView): queryset = User.objects.all() serializer_class = UserSerializer @@ -218,6 +218,16 @@ For example: By default, the search parameter is named `'search`', but this may be overridden with the `SEARCH_PARAM` setting. +To dynamically change search fields based on request content, it's possible to subclass the `SearchFilter` and override the `get_search_fields()` function. For example, the following subclass will only search on `title` if the query parameter `title_only` is in the request: + + from rest_framework import filters + + class CustomSearchFilter(filters.SearchFilter): + def get_search_fields(self, view, request): + if request.query_params.get('title_only'): + return ('title',) + return super(CustomSearchFilter, self).get_search_fields(view, request) + For more details, see the [Django documentation][search-django-admin]. --- @@ -298,9 +308,9 @@ A complete example using both `DjangoObjectPermissionsFilter` and `DjangoObjectP **permissions.py**: class CustomObjectPermissions(permissions.DjangoObjectPermissions): - """ - Similar to `DjangoObjectPermissions`, but adding 'view' permissions. - """ + """ + Similar to `DjangoObjectPermissions`, but adding 'view' permissions. + """ perms_map = { 'GET': ['%(app_label)s.view_%(model_name)s'], 'OPTIONS': ['%(app_label)s.view_%(model_name)s'], @@ -314,11 +324,11 @@ A complete example using both `DjangoObjectPermissionsFilter` and `DjangoObjectP **views.py**: class EventViewSet(viewsets.ModelViewSet): - """ - Viewset that only lists events if user has 'view' permissions, and only - allows operations on individual events if user has appropriate 'view', 'add', - 'change' or 'delete' permissions. - """ + """ + Viewset that only lists events if user has 'view' permissions, and only + allows operations on individual events if user has appropriate 'view', 'add', + 'change' or 'delete' permissions. + """ queryset = Event.objects.all() serializer_class = EventSerializer filter_backends = (filters.DjangoObjectPermissionsFilter,) diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md index 7ae351a7f..99612ef46 100644 --- a/docs/api-guide/pagination.md +++ b/docs/api-guide/pagination.md @@ -311,7 +311,7 @@ The [`drf-proxy-pagination` package][drf-proxy-pagination] includes a `ProxyPagi ## link-header-pagination -The [`django-rest-framework-link-header-pagination` package][drf-link-header-pagination] includes a `LinkHeaderPagination` class which provides pagination via an HTTP `Link` header as desribed in [Github's developer documentation](github-link-pagination). +The [`django-rest-framework-link-header-pagination` package][drf-link-header-pagination] includes a `LinkHeaderPagination` class which provides pagination via an HTTP `Link` header as described in [Github's developer documentation](github-link-pagination). [cite]: https://docs.djangoproject.com/en/stable/topics/pagination/ [link-header]: ../img/link-header-pagination.png diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index a11ad7d2b..901f810c5 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -10,9 +10,9 @@ Together with [authentication] and [throttling], permissions determine whether a Permission checks are always run at the very start of the view, before any other code is allowed to proceed. Permission checks will typically use the authentication information in the `request.user` and `request.auth` properties to determine if the incoming request should be permitted. -Permissions are used to grant or deny access different classes of users to different parts of the API. +Permissions are used to grant or deny access for different classes of users to different parts of the API. -The simplest style of permission would be to allow access to any authenticated user, and deny access to any unauthenticated user. This corresponds the `IsAuthenticated` class in REST framework. +The simplest style of permission would be to allow access to any authenticated user, and deny access to any unauthenticated user. This corresponds to the `IsAuthenticated` class in REST framework. A slightly less strict style of permission would be to allow full access to authenticated users, but allow read-only access to unauthenticated users. This corresponds to the `IsAuthenticatedOrReadOnly` class in REST framework. @@ -48,6 +48,19 @@ For example: self.check_object_permissions(self.request, obj) return obj +--- + +**Note**: With the exception of `DjangoObjectPermissions`, the provided +permission classes in `rest_framework.permissions` **do not** implement the +methods necessary to check object permissions. + +If you wish to use the provided permission classes in order to check object +permissions, **you must** subclass them and implement the +`has_object_permission()` method described in the [_Custom +permissions_](#custom-permissions) section (below). + +--- + #### Limitations of object level permissions For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects. @@ -121,7 +134,7 @@ Provided they inherit from `rest_framework.permissions.BasePermission`, permissi } return Response(content) -__Note:__ it only supports & -and- and | -or-. +__Note:__ it supports & (and), | (or) and ~ (not). --- @@ -284,9 +297,9 @@ The [DRY Rest Permissions][dry-rest-permissions] package provides the ability to The [Django Rest Framework Roles][django-rest-framework-roles] package makes it easier to parameterize your API over multiple types of users. -## Django Rest Framework API Key +## Django REST Framework API Key -The [Django Rest Framework API Key][django-rest-framework-api-key] package allows you to ensure that every request made to the server requires an API key header. You can generate one from the django admin interface. +The [Django REST Framework API Key][djangorestframework-api-key] package provides the ability to authorize clients based on customizable API key headers. This package is targeted at situations in which regular user-based authentication (e.g. `TokenAuthentication`) is not suitable, e.g. allowing non-human clients to safely use your API. API keys are generated and validated through cryptographic methods and can be created and revoked from the Django admin interface at anytime. ## Django Rest Framework Role Filters @@ -304,6 +317,6 @@ The [Django Rest Framework Role Filters][django-rest-framework-role-filters] pac [rest-condition]: https://github.com/caxap/rest_condition [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 +[djangorestframework-api-key]: https://github.com/florimondmanca/djangorestframework-api-key [django-rest-framework-role-filters]: https://github.com/allisson/django-rest-framework-role-filters [django-rest-framework-guardian]: https://github.com/rpkilby/django-rest-framework-guardian diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 8683347cb..8665e80f6 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -46,12 +46,12 @@ In order to explain the various types of relational fields, we'll use a couple o unique_together = ('album', 'order') ordering = ['order'] - def __unicode__(self): + def __str__(self): return '%d: %s' % (self.order, self.title) ## StringRelatedField -`StringRelatedField` may be used to represent the target of the relationship using its `__unicode__` method. +`StringRelatedField` may be used to represent the target of the relationship using its `__str__` method. For example, the following serializer. @@ -510,7 +510,7 @@ For example, given the following model for a tag, which has a generic relationsh object_id = models.PositiveIntegerField() tagged_object = GenericForeignKey('content_type', 'object_id') - def __unicode__(self): + def __str__(self): return self.tag_name And the following two models, which may have associated tags: diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md index a43f4be8a..4ec409681 100644 --- a/docs/api-guide/renderers.md +++ b/docs/api-guide/renderers.md @@ -89,7 +89,7 @@ The default JSON encoding style can be altered using the `UNICODE_JSON` and `COM **.media_type**: `application/json` -**.format**: `'.json'` +**.format**: `'json'` **.charset**: `None` @@ -127,7 +127,7 @@ See the [_HTML & Forms_ Topic Page][html-and-forms] for further examples of `Tem **.media_type**: `text/html` -**.format**: `'.html'` +**.format**: `'html'` **.charset**: `utf-8` @@ -149,7 +149,7 @@ You can use `StaticHTMLRenderer` either to return regular HTML pages using REST **.media_type**: `text/html` -**.format**: `'.html'` +**.format**: `'html'` **.charset**: `utf-8` @@ -165,7 +165,7 @@ This renderer will determine which other renderer would have been given highest **.media_type**: `text/html` -**.format**: `'.api'` +**.format**: `'api'` **.charset**: `utf-8` @@ -200,7 +200,7 @@ Note that views that have nested or list serializers for their input won't work **.media_type**: `text/html` -**.format**: `'.admin'` +**.format**: `'admin'` **.charset**: `utf-8` @@ -224,7 +224,7 @@ For more information see the [HTML & Forms][html-and-forms] documentation. **.media_type**: `text/html` -**.format**: `'.form'` +**.format**: `'form'` **.charset**: `utf-8` @@ -236,7 +236,7 @@ This renderer is used for rendering HTML multipart form data. **It is not suita **.media_type**: `multipart/form-data; boundary=BoUnDaRyStRiNg` -**.format**: `'.multipart'` +**.format**: `'multipart'` **.charset**: `utf-8` diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md index 35b976c66..28450f082 100644 --- a/docs/api-guide/requests.md +++ b/docs/api-guide/requests.md @@ -50,7 +50,7 @@ The request exposes some properties that allow you to determine the result of th ## .accepted_renderer -The renderer instance what was selected by the content negotiation stage. +The renderer instance that was selected by the content negotiation stage. ## .accepted_media_type diff --git a/docs/api-guide/schemas.md b/docs/api-guide/schemas.md index 8a6688378..b09b1606e 100644 --- a/docs/api-guide/schemas.md +++ b/docs/api-guide/schemas.md @@ -20,7 +20,7 @@ can render the schema into the commonly used YAML-based OpenAPI format. ## Quickstart -There are two different ways you can serve a schema description for you API. +There are two different ways you can serve a schema description for your API. ### Generating a schema with the `generateschema` management command @@ -112,8 +112,8 @@ has to be rendered into the actual bytes that are used in the response. REST framework includes a few different renderers that you can use for encoding the API schema. -* `renderers.OpenAPIRenderer` - Renders into YAML-based [OpenAPI][openapi], the most widely used API schema format. -* `renderers.JSONOpenAPIRenderer` - Renders into JSON-based [OpenAPI][openapi]. +* `renderers.OpenAPIRenderer` - Renders into YAML-based [OpenAPI][open-api], the most widely used API schema format. +* `renderers.JSONOpenAPIRenderer` - Renders into JSON-based [OpenAPI][open-api]. * `renderers.CoreJSONRenderer` - Renders into [Core JSON][corejson], a format designed for use with the `coreapi` client library. @@ -827,19 +827,11 @@ A short description of the meaning and intended usage of the input field. [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 -in [OpenAPI][open-api] format. - - [cite]: https://blog.heroku.com/archives/2014/1/8/json_schema_for_heroku_platform_api [coreapi]: https://www.coreapi.org/ [corejson]: https://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]: https://json-schema.org/latest/json-schema-hypermedia.html [api-blueprint]: https://apiblueprint.org/ [static-files]: https://docs.djangoproject.com/en/stable/howto/static-files/ diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 3ef930c64..e25053936 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -152,7 +152,7 @@ When deserializing data, you always need to call `is_valid()` before attempting serializer.is_valid() # False serializer.errors - # {'email': [u'Enter a valid e-mail address.'], 'created': [u'This field is required.']} + # {'email': ['Enter a valid e-mail address.'], 'created': ['This field is required.']} Each key in the dictionary will be the field name, and the values will be lists of strings of any error messages corresponding to that field. The `non_field_errors` key may also be present, and will list any general validation errors. The name of the `non_field_errors` key may be customized using the `NON_FIELD_ERRORS_KEY` REST framework setting. @@ -253,7 +253,7 @@ When passing data to a serializer instance, the unmodified data will be made ava By default, serializers must be passed values for all required fields or they will raise validation errors. You can use the `partial` argument in order to allow partial updates. # Update `comment` with partial data - serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True) + serializer = CommentSerializer(comment, data={'content': 'foo bar'}, partial=True) ## Dealing with nested objects @@ -293,7 +293,7 @@ When dealing with nested representations that support deserializing the data, an serializer.is_valid() # False serializer.errors - # {'user': {'email': [u'Enter a valid e-mail address.']}, 'created': [u'This field is required.']} + # {'user': {'email': ['Enter a valid e-mail address.']}, 'created': ['This field is required.']} Similarly, the `.validated_data` property will include nested data structures. @@ -415,7 +415,7 @@ You can provide arbitrary additional context by passing a `context` argument whe serializer = AccountSerializer(account, context={'request': request}) serializer.data - # {'id': 6, 'owner': u'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'} + # {'id': 6, 'owner': 'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'} The context dictionary can be used within any serializer field logic, such as a custom `.to_representation()` method, by accessing the `self.context` attribute. @@ -1094,10 +1094,10 @@ This would then allow you to do the following: >>> model = User >>> fields = ('id', 'username', 'email') >>> - >>> print UserSerializer(user) + >>> print(UserSerializer(user)) {'id': 2, 'username': 'jonwatts', 'email': 'jon@example.com'} >>> - >>> print UserSerializer(user, fields=('id', 'email')) + >>> print(UserSerializer(user, fields=('id', 'email'))) {'id': 2, 'email': 'jon@example.com'} ## Customizing the default fields diff --git a/docs/api-guide/testing.md b/docs/api-guide/testing.md index 9134bd08e..5ca01b4e7 100644 --- a/docs/api-guide/testing.md +++ b/docs/api-guide/testing.md @@ -209,7 +209,7 @@ directly. Note that the requests client requires you to pass fully qualified URLs. -## `RequestsClient` and working with the database +## RequestsClient and working with the database The `RequestsClient` class is useful if you want to write tests that solely interact with the service interface. This is a little stricter than using the standard Django test client, as it means that all interactions should be via the API. diff --git a/docs/api-guide/throttling.md b/docs/api-guide/throttling.md index de66396a8..dade47460 100644 --- a/docs/api-guide/throttling.md +++ b/docs/api-guide/throttling.md @@ -82,8 +82,10 @@ The throttle classes provided by REST framework use Django's cache backend. You If you need to use a cache other than `'default'`, you can do so by creating a custom throttle class and setting the `cache` attribute. For example: + from django.core.cache import caches + class CustomAnonRateThrottle(AnonRateThrottle): - cache = get_cache('alternate') + cache = caches['alternate'] You'll need to remember to also set your custom throttle class in the `'DEFAULT_THROTTLE_CLASSES'` settings key, or using the `throttle_classes` view attribute. diff --git a/docs/community/3.0-announcement.md b/docs/community/3.0-announcement.md index 83aec9e60..dc118d70c 100644 --- a/docs/community/3.0-announcement.md +++ b/docs/community/3.0-announcement.md @@ -389,7 +389,7 @@ You can include `expiry_date` as a field option on a `ModelSerializer` class. These fields will be mapped to `serializers.ReadOnlyField()` instances. >>> serializer = InvitationSerializer() - >>> print repr(serializer) + >>> print(repr(serializer)) InvitationSerializer(): to_email = EmailField(max_length=75) message = CharField(max_length=1000) @@ -960,6 +960,6 @@ The 3.2 release is planned to introduce an alternative admin-style interface to You can follow development on the GitHub site, where we use [milestones to indicate planning timescales](https://github.com/encode/django-rest-framework/milestones). [kickstarter]: https://www.kickstarter.com/projects/tomchristie/django-rest-framework-3 -[sponsors]: https://www.django-rest-framework.org/topics/kickstarter-announcement/#sponsors +[sponsors]: https://www.django-rest-framework.org/community/kickstarter-announcement/#sponsors [mixins.py]: https://github.com/encode/django-rest-framework/blob/master/rest_framework/mixins.py [django-localization]: https://docs.djangoproject.com/en/stable/topics/i18n/translation/#localization-how-to-create-language-files diff --git a/docs/community/3.1-announcement.md b/docs/community/3.1-announcement.md index 0a2c40c9e..2213c379d 100644 --- a/docs/community/3.1-announcement.md +++ b/docs/community/3.1-announcement.md @@ -30,7 +30,7 @@ Note that as a result of this work a number of settings keys and generic view at Until now, there has only been a single built-in pagination style in REST framework. We now have page, limit/offset and cursor based schemes included by default. -The cursor based pagination scheme is particularly smart, and is a better approach for clients iterating through large or frequently changing result sets. The scheme supports paging against non-unique indexes, by using both cursor and limit/offset information. It also allows for both forward and reverse cursor pagination. Much credit goes to David Cramer for [this blog post](http://cramer.io/2011/03/08/building-cursors-for-the-disqus-api) on the subject. +The cursor based pagination scheme is particularly smart, and is a better approach for clients iterating through large or frequently changing result sets. The scheme supports paging against non-unique indexes, by using both cursor and limit/offset information. It also allows for both forward and reverse cursor pagination. Much credit goes to David Cramer for [this blog post](https://cra.mr/2011/03/08/building-cursors-for-the-disqus-api) on the subject. #### Pagination controls in the browsable API. @@ -114,7 +114,7 @@ Note that the structure of the error responses is still the same. We still have We include built-in translations both for standard exception cases, and for serializer validation errors. -The full list of supported languages can be found on our [Transifex project page](https://www.transifex.com/projects/p/django-rest-framework/). +The full list of supported languages can be found on our [Transifex project page](https://www.transifex.com/django-rest-framework-1/django-rest-framework/). If you only wish to support a subset of the supported languages, use Django's standard `LANGUAGES` setting: @@ -155,14 +155,14 @@ We've now moved a number of packages out of the core of REST framework, and into We're making this change in order to help distribute the maintenance workload, and keep better focus of the core essentials of the framework. -The change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained [Django OAuth toolkit](https://github.com/evonove/django-oauth-toolkit) has now been promoted as our recommended option for integrating OAuth support. +The change also means we can be more flexible with which external packages we recommend. For example, the excellently maintained [Django OAuth toolkit](https://github.com/jazzband/django-oauth-toolkit) has now been promoted as our recommended option for integrating OAuth support. The following packages are now moved out of core and should be separately installed: * 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) +* 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/community/3.2-announcement.md b/docs/community/3.2-announcement.md index a6db0e54b..a66ad5d29 100644 --- a/docs/community/3.2-announcement.md +++ b/docs/community/3.2-announcement.md @@ -10,7 +10,7 @@ We've also fixed a huge number of issues, and made numerous cleanups and improve Over the course of the 3.1.x series we've [resolved nearly 600 tickets](https://github.com/encode/django-rest-framework/issues?utf8=%E2%9C%93&q=closed%3A%3E2015-03-05) on our GitHub issue tracker. This means we're currently running at a rate of **closing around 100 issues or pull requests per month**. -None of this would have been possible without the support of our wonderful Kickstarter backers. If you're looking for a job in Django development we'd strongly recommend taking [a look through our sponsors](https://www.django-rest-framework.org/topics/kickstarter-announcement/#sponsors) and finding out who's hiring. +None of this would have been possible without the support of our wonderful Kickstarter backers. If you're looking for a job in Django development we'd strongly recommend taking [a look through our sponsors](https://www.django-rest-framework.org/community/kickstarter-announcement/#sponsors) and finding out who's hiring. ## AdminRenderer diff --git a/docs/community/3.4-announcement.md b/docs/community/3.4-announcement.md index 44270fd85..67192ecbb 100644 --- a/docs/community/3.4-announcement.md +++ b/docs/community/3.4-announcement.md @@ -36,13 +36,13 @@ Right now we're over 60% of the way towards achieving that. *Every single sign-up makes a significant impact.*
-*Many thanks to all our [awesome sponsors][sponsors], and in particular to our premium backers, [Rover](http://jobs.rover.com/), [Sentry](https://getsentry.com/welcome/), and [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf).* +*Many thanks to all our [awesome sponsors][sponsors], and in particular to our premium backers, [Rover](https://www.rover.com/careers/), [Sentry](https://sentry.io/welcome/), and [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf).* --- diff --git a/docs/community/3.5-announcement.md b/docs/community/3.5-announcement.md index dca371b84..cce2dd050 100644 --- a/docs/community/3.5-announcement.md +++ b/docs/community/3.5-announcement.md @@ -32,14 +32,14 @@ we strongly encourage you to invest in its continued development by **[signing up for a paid plan][funding]**. -*Many thanks to all our [sponsors][sponsors], and in particular to our premium backers, [Rover](http://jobs.rover.com/), [Sentry](https://getsentry.com/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), and [Machinalis](https://www.machinalis.com/#services).* +*Many thanks to all our [sponsors][sponsors], and in particular to our premium backers, [Rover](https://www.rover.com/careers/), [Sentry](https://sentry.io/welcome/), [Stream](https://getstream.io/?utm_source=drf&utm_medium=banner&utm_campaign=drf), and [Machinalis](https://www.machinalis.com/#services).* --- diff --git a/docs/community/3.6-announcement.md b/docs/community/3.6-announcement.md index 04e6a6669..c6e8dfa06 100644 --- a/docs/community/3.6-announcement.md +++ b/docs/community/3.6-announcement.md @@ -39,16 +39,16 @@ we strongly encourage you to invest in its continued development by **[signing up for a paid plan][funding]**.
{{ content|urlize_quoted_links }}