diff --git a/.gitignore b/.gitignore index 1207cc48..6b952e8f 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,6 @@ pip-delete-this-directory.txt *.sw* manage.py .DS_Store + +# example database +drf_example diff --git a/CHANGELOG.md b/CHANGELOG.md index fc160067..c2e50c21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,9 @@ * Add sorting configuration to `REST_FRAMEWORK` as defined in [json api spec](http://jsonapi.org/format/#fetching-sorting) * Add `HyperlinkedRelatedField` and `SerializerMethodHyperlinkedRelatedField`. See [usage docs](docs/usage.md#related-fields) * Add related urls support. See [usage docs](docs/usage.md#related-urls) - +* Replaced binary `drf_example` sqlite3 db with a [fixture](example/fixtures/drf_example.yaml). See [usage docs](docs/usage.md#running-the-example-app). +* For naming consistency, renamed new `JsonApi`-prefix pagination classes to `JSONAPI`-prefix. + * Deprecates `JsonApiPageNumberPagination` and `JsonApiLimitOffsetPagination` v2.5.0 - Released July 11, 2018 diff --git a/README.rst b/README.rst index 46813188..283ff640 100644 --- a/README.rst +++ b/README.rst @@ -161,7 +161,7 @@ override ``settings.REST_FRAMEWORK`` 'PAGE_SIZE': 10, 'EXCEPTION_HANDLER': 'rest_framework_json_api.exceptions.exception_handler', 'DEFAULT_PAGINATION_CLASS': - 'rest_framework_json_api.pagination.JsonApiPageNumberPagination', + 'rest_framework_json_api.pagination.JSONAPIPageNumberPagination', 'DEFAULT_PARSER_CLASSES': ( 'rest_framework_json_api.parsers.JSONParser', 'rest_framework.parsers.FormParser', diff --git a/docs/getting-started.md b/docs/getting-started.md index d68bbdd3..26117e0b 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -68,15 +68,16 @@ From Source ## Running the example app - git clone https://github.com/django-json-api/django-rest-framework-json-api.git - cd django-rest-framework-json-api - python -m venv env - source env/bin/activate - pip install -r example/requirements.txt + git clone https://github.com/django-json-api/django-rest-framework-json-api.git + cd django-rest-framework-json-api + python3 -m venv env + source env/bin/activate + pip install -r example/requirements.txt pip install -e . - django-admin.py startproject example . - python manage.py migrate - python manage.py runserver + django-admin migrate --settings=example.settings + django-admin loaddata drf_example --settings=example.settings + django-admin runserver --settings=example.settings + Browse to http://localhost:8000 diff --git a/docs/usage.md b/docs/usage.md index 25bb7310..61ac4fc3 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -15,7 +15,7 @@ REST_FRAMEWORK = { 'PAGE_SIZE': 10, 'EXCEPTION_HANDLER': 'rest_framework_json_api.exceptions.exception_handler', 'DEFAULT_PAGINATION_CLASS': - 'rest_framework_json_api.pagination.JsonApiPageNumberPagination', + 'rest_framework_json_api.pagination.JSONAPIPageNumberPagination', 'DEFAULT_PARSER_CLASSES': ( 'rest_framework_json_api.parsers.JSONParser', 'rest_framework.parsers.FormParser', @@ -58,15 +58,15 @@ You can configure fixed values for the page size or limit -- or allow the client via query parameters. Two pagination classes are available: -- `JsonApiPageNumberPagination` breaks a response up into pages that start at a given page number with a given size - (number of items per page). It can be configured with the following attributes: +- `JSONAPIPageNumberPagination` breaks a response up into pages that start at a given page number + with a given size (number of items per page). It can be configured with the following attributes: - `page_query_param` (default `page[number]`) - `page_size_query_param` (default `page[size]`) Set this to `None` if you don't want to allow the client to specify the size. - `max_page_size` (default `100`) enforces an upper bound on the `page_size_query_param`. Set it to `None` if you don't want to enforce an upper bound. -- `JsonApiLimitOffsetPagination` breaks a response up into pages that start from an item's offset in the viewset for - a given number of items (the limit). +- `JSONAPILimitOffsetPagination` breaks a response up into pages that start from an item's offset + in the viewset for a given number of items (the limit). It can be configured with the following attributes: - `offset_query_param` (default `page[offset]`). - `limit_query_param` (default `page[limit]`). @@ -77,14 +77,14 @@ Two pagination classes are available: These examples show how to configure the parameters to use non-standard names and different limits: ```python -from rest_framework_json_api.pagination import JsonApiPageNumberPagination, JsonApiLimitOffsetPagination +from rest_framework_json_api.pagination import JSONAPIPageNumberPagination, JSONAPILimitOffsetPagination -class MyPagePagination(JsonApiPageNumberPagination): +class MyPagePagination(JSONAPIPageNumberPagination): page_query_param = 'page_number' page_size_query_param = 'page_size' max_page_size = 1000 -class MyLimitPagination(JsonApiLimitOffsetPagination): +class MyLimitPagination(JSONAPILimitOffsetPagination): offset_query_param = 'offset' limit_query_param = 'limit' max_limit = None diff --git a/drf_example b/drf_example deleted file mode 100644 index 2b54190f..00000000 Binary files a/drf_example and /dev/null differ diff --git a/example/fixtures/drf_example.json b/example/fixtures/drf_example.json new file mode 100644 index 00000000..498c0d1c --- /dev/null +++ b/example/fixtures/drf_example.json @@ -0,0 +1,124 @@ +[ +{ + "model": "example.blog", + "pk": 1, + "fields": { + "created_at": "2016-05-02T08:27:16.889", + "modified_at": "2016-05-02T08:27:16.889", + "name": "Personal", + "tagline": "" + } +}, +{ + "model": "example.blog", + "pk": 2, + "fields": { + "created_at": "2016-05-02T08:27:23.871", + "modified_at": "2016-05-02T08:27:23.871", + "name": "Work", + "tagline": "" + } +}, +{ + "model": "example.author", + "pk": 1, + "fields": { + "created_at": "2016-05-02T10:09:48.277", + "modified_at": "2016-05-02T10:09:48.277", + "name": "Alice", + "email": "alice@example.com", + "type": null + } +}, +{ + "model": "example.author", + "pk": 2, + "fields": { + "created_at": "2016-05-02T10:09:57.133", + "modified_at": "2016-05-02T10:09:57.133", + "name": "Bob", + "email": "bob@example.com", + "type": null + } +}, +{ + "model": "example.authorbio", + "pk": 1, + "fields": { + "created_at": "2016-05-02T10:10:23.429", + "modified_at": "2016-05-02T10:10:23.429", + "author": 1, + "body": "I just want to send messages to Bob." + } +}, +{ + "model": "example.authorbio", + "pk": 2, + "fields": { + "created_at": "2016-05-02T10:11:30.327", + "modified_at": "2016-05-02T10:11:30.327", + "author": 2, + "body": "I get messages from Alice and send them to Carol" + } +}, +{ + "model": "example.entry", + "pk": 1, + "fields": { + "created_at": "2016-05-02T10:43:21.271", + "modified_at": "2016-05-02T10:43:21.271", + "blog": 1, + "headline": "This is a test, this is only a test", + "body_text": "And this is the body text for the blog entry. To see comments included in this payload visit: /entries/1?include=comments", + "pub_date": "2015-01-01", + "mod_date": "2015-04-05", + "n_comments": 0, + "n_pingbacks": 0, + "rating": 0, + "authors": [ + 1 + ] + } +}, +{ + "model": "example.entry", + "pk": 2, + "fields": { + "created_at": "2016-05-02T10:44:14.376", + "modified_at": "2016-05-02T10:49:30.150", + "blog": 1, + "headline": "Django, the framework for perfectionists with deadlines", + "body_text": "And this is the body text. Try out includes by using this uri: /entries/2?include=comments,authors,authors.bio", + "pub_date": "2015-05-01", + "mod_date": "2015-09-03", + "n_comments": 0, + "n_pingbacks": 0, + "rating": 0, + "authors": [ + 2 + ] + } +}, +{ + "model": "example.comment", + "pk": 1, + "fields": { + "created_at": "2016-05-02T10:44:35.093", + "modified_at": "2016-05-02T10:44:35.093", + "entry": 1, + "body": "Love this article!", + "author": 2 + } +}, +{ + "model": "example.comment", + "pk": 2, + "fields": { + "created_at": "2016-05-02T10:44:55.482", + "modified_at": "2016-05-02T10:44:55.482", + "entry": 2, + "body": "Frist comment!!!", + "author": null + } +} +] diff --git a/example/requirements.txt b/example/requirements.txt index 0fa77009..fe28eddc 100644 --- a/example/requirements.txt +++ b/example/requirements.txt @@ -11,3 +11,4 @@ pyparsing pytz six sqlparse + diff --git a/example/tests/unit/test_pagination.py b/example/tests/unit/test_pagination.py index f6e95db0..b2cd1621 100644 --- a/example/tests/unit/test_pagination.py +++ b/example/tests/unit/test_pagination.py @@ -13,11 +13,11 @@ class TestLimitOffset: """ - Unit tests for `pagination.JsonApiLimitOffsetPagination`. + Unit tests for `pagination.JSONAPILimitOffsetPagination`. """ def setup(self): - class ExamplePagination(pagination.JsonApiLimitOffsetPagination): + class ExamplePagination(pagination.JSONAPILimitOffsetPagination): default_limit = 10 max_limit = 15 @@ -91,7 +91,7 @@ def test_limit_offset_deprecation(self): reason="python2.7 fails for unknown reason") class TestPageNumber: """ - Unit tests for `pagination.JsonApiPageNumberPagination`. + Unit tests for `pagination.JSONAPIPageNumberPagination`. TODO: add unit tests for changing query parameter names, limits, etc. """ def test_page_number_deprecation(self): diff --git a/example/views.py b/example/views.py index 5dfc3341..a42a80ae 100644 --- a/example/views.py +++ b/example/views.py @@ -34,7 +34,7 @@ def get_object(self): return super(BlogViewSet, self).get_object() -class JsonApiViewSet(ModelViewSet): +class JSONAPIViewSet(ModelViewSet): """ This is an example on how to configure DRF-jsonapi from within a class. It allows using DRF-jsonapi alongside @@ -58,12 +58,12 @@ def handle_exception(self, exc): exc.status_code = HTTP_422_UNPROCESSABLE_ENTITY # exception handler can't be set on class so you have to # override the error response in this method - response = super(JsonApiViewSet, self).handle_exception(exc) + response = super(JSONAPIViewSet, self).handle_exception(exc) context = self.get_exception_handler_context() return format_drf_errors(response, context, exc) -class BlogCustomViewSet(JsonApiViewSet): +class BlogCustomViewSet(JSONAPIViewSet): queryset = Blog.objects.all() serializer_class = BlogSerializer diff --git a/rest_framework_json_api/pagination.py b/rest_framework_json_api/pagination.py index 00873c99..6b1f0fc5 100644 --- a/rest_framework_json_api/pagination.py +++ b/rest_framework_json_api/pagination.py @@ -9,7 +9,7 @@ from rest_framework.views import Response -class JsonApiPageNumberPagination(PageNumberPagination): +class JSONAPIPageNumberPagination(PageNumberPagination): """ A json-api compatible pagination format """ @@ -50,7 +50,7 @@ def get_paginated_response(self, data): }) -class JsonApiLimitOffsetPagination(LimitOffsetPagination): +class JSONAPILimitOffsetPagination(LimitOffsetPagination): """ A limit/offset based style. For example: http://api.example.org/accounts/?page[limit]=100 @@ -100,7 +100,23 @@ def get_paginated_response(self, data): }) -class PageNumberPagination(JsonApiPageNumberPagination): +class JsonApiPageNumberPagination(JSONAPIPageNumberPagination): + """ + Deprecated due to desire to use `JSONAPI` prefix for all classes. + """ + page_query_param = 'page' + page_size_query_param = 'page_size' + + def __init__(self): + warnings.warn( + 'JsonApiPageNumberPagination is deprecated. Use JSONAPIPageNumberPagination ' + 'or create custom pagination. See ' + 'https://django-rest-framework-json-api.readthedocs.io/en/stable/usage.html#pagination', + DeprecationWarning) + super(PageNumberPagination, self).__init__() + + +class PageNumberPagination(JSONAPIPageNumberPagination): """ Deprecated paginator that uses different query parameters """ @@ -109,14 +125,29 @@ class PageNumberPagination(JsonApiPageNumberPagination): def __init__(self): warnings.warn( - 'PageNumberPagination is deprecated. Use JsonApiPageNumberPagination ' + 'PageNumberPagination is deprecated. Use JSONAPIPageNumberPagination ' 'or create custom pagination. See ' 'https://django-rest-framework-json-api.readthedocs.io/en/stable/usage.html#pagination', DeprecationWarning) super(PageNumberPagination, self).__init__() -class LimitOffsetPagination(JsonApiLimitOffsetPagination): +class JsonApiLimitOffsetPagination(JSONAPILimitOffsetPagination): + """ + Deprecated due to desire to use `JSONAPI` prefix for all classes. + """ + max_limit = None + + def __init__(self): + warnings.warn( + 'JsonApiLimitOffsetPagination is deprecated. Use JSONAPILimitOffsetPagination ' + 'or create custom pagination. See ' + 'https://django-rest-framework-json-api.readthedocs.io/en/stable/usage.html#pagination', + DeprecationWarning) + super(LimitOffsetPagination, self).__init__() + + +class LimitOffsetPagination(JSONAPILimitOffsetPagination): """ Deprecated paginator that uses a different max_limit """ @@ -124,7 +155,7 @@ class LimitOffsetPagination(JsonApiLimitOffsetPagination): def __init__(self): warnings.warn( - 'LimitOffsetPagination is deprecated. Use JsonApiLimitOffsetPagination ' + 'LimitOffsetPagination is deprecated. Use JSONAPILimitOffsetPagination ' 'or create custom pagination. See ' 'https://django-rest-framework-json-api.readthedocs.io/en/stable/usage.html#pagination', DeprecationWarning) diff --git a/tox.ini b/tox.ini index d5cca046..24df43e4 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,7 @@ commands = [testenv:flake8] deps = flake8 -commands = flake8 +commands = flake8 --exclude=migrations rest_framework_json_api example skip_install = true [testenv:isort]