DRF-extensions is a collection of custom extensions for Django REST Framework

Overview

Django REST Framework extensions

DRF-extensions is a collection of custom extensions for Django REST Framework

Full documentation for project is available at http://chibisov.github.io/drf-extensions/docs

Build Status Backers on Open Collective Sponsors on Open Collective PyPI

Sponsor

Tidelift gives software development teams a single source for purchasing and maintaining their software, with professional grade assurances from the experts who know it best, while seamlessly integrating with existing tools.

Requirements

  • Tested for Python 3.6, 3.7 and 3.8
  • Tested for Django Rest Framework 3.12
  • Tested for Django 2.2 to 3.2
  • Tested for django-filter 2.1.0

Installation:

pip3 install drf-extensions

or from github

pip3 install https://github.com/chibisov/drf-extensions/archive/master.zip

Some features

  • DetailSerializerMixin
  • Caching
  • Conditional requests
  • Customizable key construction for caching and conditional requests
  • Nested routes
  • Bulk operations

Read more in documentation

Development

Running the tests:

$ pip3 install tox
$ tox -- tests_app

Running test for exact environment:

$ tox -e py38 -- tests_app

Recreate envs before running tests:

$ tox --recreate -- tests_app

Pass custom arguments:

$ tox -- tests_app --verbosity=3

Run with pdb support:

$ tox -- tests_app --processes=0 --nocapture

Run exact TestCase:

$ tox -- tests_app.tests.unit.mixins.tests:DetailSerializerMixinTest_serializer_detail_class

Run tests from exact module:

$ tox -- tests_app.tests.unit.mixins.tests

Build docs:

$ make build_docs

Automatically build docs by watching changes:

$ pip install watchdog
$ make watch_docs

Developing new features

Every new feature should be:

  • Documented
  • Tested
  • Implemented
  • Pushed to main repository

How to write documentation

When new feature implementation starts you should place it into development version pull. Add Development version section to Release notes and describe every new feature in it. Use #anchors to facilitate navigation.

Every feature should have title and information that it was implemented in current development version.

For example if we've just implemented Usage of the specific cache:

...

#### Usage of the specific cache

*New in DRF-extensions development version*

`@cache_response` can also take...

...

### Release notes

...

#### Development version

* Added ability to [use a specific cache](#usage-of-the-specific-cache) for `@cache_response` decorator

Publishing new releases

Increment version in rest_framework_extensions/__init__.py. For example:

__version__ = '0.2.2'  # from 0.2.1

Move to new version section all release notes in documentation.

Add date for release note section.

Replace in documentation all New in DRF-extensions development version notes to New in DRF-extensions 0.2.2.

Rebuild documentation.

Run tests.

Commit changes with message "Version 0.2.2"

Add new tag version for commit:

$ git tag 0.2.2

Push to master with tags:

$ git push origin master --tags

Don't forget to merge master to gh-pages branch and push to origin:

$ git co gh-pages
$ git merge --no-ff master
$ git push origin gh-pages

Publish to pypi:

$ python setup.py publish

Contributors

This project exists thanks to all the people who contribute.

Backers

Thank you to all our backers! ­čÖĆ [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

Comments
  • EmptyResultSet removed in Django 3.1

    EmptyResultSet removed in Django 3.1

    Version: drf-extensions 0.6.0 Django 3.1 (python 3.8, but doesn't matter for issue)

    Description: Django has removed EmptyResultSet backward compatibility. django 3.1 commit breaking drf-extensions: https://github.com/django/django/commit/129583a0d3cf69b08d058cd751d777588801b7ad

    Error: from rest_framework_extensions.key_constructor import bits File "/usr/local/lib/python3.8/site-packages/rest_framework_extensions/key_constructor/bits.py", line 3, in <module> from django.db.models.sql.datastructures import EmptyResultSet ImportError: cannot import name 'EmptyResultSet' from 'django.db.models.sql.datastructures' (/usr/local/lib/python3.8/site-packages/django/db/models/sql/datastructures.py)

    Workaround: Stay on Django 3.0.8

    opened by henriklindgren 31
  • NestedViewSetMixin suport for saving

    NestedViewSetMixin suport for saving

    Is looks like using the NestedViewSetMixin auto generates the filter code for nested routers, but does nothing for saving.

    I would recommend something like the following for a URL like companies/company_pk/locations/location_pk:

        def pre_save(self, obj):
            obj.location = Location.objects.get(pk=self.kwargs['location_slug'],
                                        company__pk=self.kwargs['company_pk']
                                        )
    

    to be auto generated so that a user posting to the above URL can omit those fields which are determined by the URL itself.

    Docs Design decision needed 
    opened by cancan101 24
  • Optimistic concurrency control using ETags

    Optimistic concurrency control using ETags

    API resources: Optimistic concurrency control using ETags

    The Problem

    As @mbox already mentioned, the default implementation in drf-extensions does not allow a correct optimistic locking using ETags and conditional requests. The ETag ties each request to a particular HTTP method, view, and response. While this works as expected for server-side caching (correctly returns status 304, and 200), it does not work to identify the requested resources when retrieving an object, altering it and putting it back to the server:

    # Retrieve Request
    GET /books/1/ HTTP/1.1
    Accept: "application/json"
    
    # Response
    HTTP/1.1 200 OK
    Content-Type: "application/json"
    ETag: "591fa57af468db45942e5bf8ebe59378"
    
    {'issn': '9780345531988', 'name': 'The Summons', 'id': 1, 'author': 'Stephen King'}
    
    
    # Update Request
    PUT /books/1/ HTTP/1.1
    Accept: "application/json"
    If-Match: "591fa57af468db45942e5bf8ebe59378"
    
    {'issn': '9780345531988', 'name': 'The Summons', 'id': 1, 'author': 'John Grisham'}
    
    # Response
    HTTP/1.1 412 PRECONDITION FAILED 			# <- THIS SHOULD BE '200 OK'!
    Content-Type: "application/json"
    ETag: "<another_value_that_hashed_the_PUT_view>"
    

    Related discussion in the DRF issues: https://github.com/tomchristie/django-rest-framework/issues/32

    Proposed Changes

    I have implemented the following changes/additions to enable optimistic locking using conditional requests using ETag, If-Match, If-None-Match HTTP headers in DRF-extensions. It is based on the requirement that we need an ETag value to represent the current semantic version of individual model instances rather than using it as caching function for a dynamic page.

    • New KeyBits for retrieving and listing model instances: decoupled from the views and methods, the entries in the QuerySet are tuples represented by their mere field values.
    • New KeyConstructors for API views that use the new KeyBits.
    • New default functions to compute ETags for API views (in settings and utils)
    • New API{method}ETAGMixins: List, Retrieve, Update, Destroy, as well as combined mixins for ReadOnly and APIETAGMixin.

    The new features have been tested in unit tests where applicable and there exists a new functional test app in tests_app/tests/functional/concurrency. It tests a standard APIClient from the rest_framework to query Book models.

    Additional Changes

    Some other changes have been performed to ensure that all tests pass in django 1.10 and 1.9, DRF 3.5.3:

    • added missing fields = '__all__' to serializers (ensures DRF>3.3 compatibility)
    • removed double entry in DRF features dict rest_framework_extensions/utils.py

    I documented the source code. The usage of the new mixins and decorators is identical to the current implementation that exists for @etag.

    opened by pkainz 17
  • version 0.3.1 is not compatible with DRF 3.8 and produces ImportError

    version 0.3.1 is not compatible with DRF 3.8 and produces ImportError

    The version 0.3.1 is not compatible with DRF 3.8. It seems that the master is, but the latest provided release to PyPI apparently not.

    It produces an import error in the 0.3.1 code

    Error:

      ...
      File ".../site-packages/rest_framework_extensions/routers.py", line 7, in <module>
        from rest_framework.routers import (
    ImportError: cannot import name 'replace_methodname'
    

    Culprit code of 0.3.1

    # -*- coding: utf-8 -*-
    from distutils.version import StrictVersion
    from django.core.exceptions import ImproperlyConfigured
    from django.core.urlresolvers import NoReverseMatch
    
    import rest_framework
    from rest_framework.routers import (
        DefaultRouter,
        SimpleRouter,
        Route,
        replace_methodname,
        ^^^^^^^^^^^^^^^^^^^
    )
    
    opened by jberends 15
  • Made compatible with DRF 3.2.2 and django 1.8

    Made compatible with DRF 3.2.2 and django 1.8

    Hi Gennady,

    I have made a few changes to make drf-extensions compatible with the latest Django Rest Framework. The new versions of Django Rest Framework, since 3.1.0, have introduced some breaking changes, such as the new Pagination classes. The tests pass with these recent versions only.

    How about considering to drop the support for earlier versions? We can add some note like:

    For Django Rest Framework 2.4 support check drf-extensions 0.2.7

    Thanks for creating and sharing the extensions.

    opened by pratyushmittal 15
  • Respect parent lookup regex value (sending parent viewset to NestedRegistryItem)

    Respect parent lookup regex value (sending parent viewset to NestedRegistryItem)

    A try for this was made in #63 but it did not lead anywhere and this is really starting to become a problem for me so hopefully this is good enough :)

    Problem

    Say that you have a user route (/users) and you do not want to expose the id value of the user, so you use the users email instead. Making a detailed route look like /users/[email protected]. You test the route and notice that you get a 404 page. This is because the default lookup regex is [^/.]+, and this works fine for most routes, but not when there is a dot (.) in the route. And since dots are valid in a url we this is a shame. The solution to this is to set your lookup_filed to 'email' and write your own lookup_value_regex in your view. In this case we could set it to something fancy such as [^@]+@[^@]+\.[^@/]+. And voil├á, the route now works.

    The problem is that this regex value is not respected in the nested routers that are included in drf-extensions, instead the hard coded value of [^/.]+ is used.

    Solution

    By default we do not have access to the parents regex value as it is stored in the parents viewset, which we don't have access to either. This pull requests lets the viewset of the parent be passed to the ┬┤NestedRegistryItem┬┤ class, exposing all viewset functions and variables, including the regex. The regex is then used when creating the get_parent_prefix(), and falls back on the default value of [^/.]+ if no regex is set.

    Caveat

    There is a second thing here to keep in mind. If using custom lookup_field values in the view, one also needs to set the lookup_url_kwarg value when using nested router, in the example above it would be lookup_url_kwarg = 'parent_lookup_email'. This has to do with the way the NestedViewSetMixin is built, and can probably be fixes as well (just not in this pull request).

    opened by frwickst 12
  • Generated etags stay the same after updating contents

    Generated etags stay the same after updating contents

    I'm having a trouble to get etag decorator working. Generated etags don't change after updating the corresponding contents (responses from drf views are updated too).

    By looking at the code in drf-extensions, the default behaviour of the default_etag_func seems to be calculating etags based on requests. Wouldn't it supposed to be based on responses?

    Before attempting to write a custom etag_func, I would like to make sure that I'm not missing anything.

    I'm testing with following versions.

    • drf-extensions==0.2.2
    • djangorestframework==2.3.13
    opened by ysugiura 12
  • Import error - Django 3.0.1 - ImportError: cannot import name 'available_attrs' from 'django.utils.decorators'

    Import error - Django 3.0.1 - ImportError: cannot import name 'available_attrs' from 'django.utils.decorators'

    Hi, I am using drf-extensions 0.5.0 with Django 3.0.1 and Python 3.7. However, when I try to use the package, I get this error. I believe this has something to do with compatibility if Django 3.0.

    Is this an easy fix?

    File "/sam/Service/venv/lib/python3.7/site-packages/rest_framework_extensions/cache/decorators.py", line 4, in <module>
        from django.utils.decorators import available_attrs
    ImportError: cannot import name 'available_attrs' from 'django.utils.decorators' (/sam/Service/venv/lib/python3.7/site-packages/django/utils/decorators.py)
    
    
    
    opened by SulanthaM 11
  • ExtendedDefaultRouter root view is polluted

    ExtendedDefaultRouter root view is polluted

    I am using ExtendedDefaultRouter with nested routes. Right now my root view is being polluted by the sub items:

    GET /api/
    
    {
        "people": "http://127.0.0.1:8000/api/people/", 
        "people/(?P<parent_lookup_person__uuid>[^/.]+)/tests": "http://127.0.0.1:8000/api/tests/",
        "tests": "http://127.0.0.1:8000/api/tests/"
    }
    
    opened by cancan101 11
  • DetailSerializerMixin returns detail serializer repr. on list URL

    DetailSerializerMixin returns detail serializer repr. on list URL

    We ran into a minor snag with using DetailSerializerMixin. When POST'ing to a list URL, you are returned the detail serializer representation, and therefore you see a weird thing like this: 2014-10-31 16 12 59 So as you see, we are still on the /posts/URL, but we see a post instance and the form on the bottom is also for the post instance. Even more, pressing the POST button would not work, because some fields would obviously be missing from the detail form that are required for list form.

    If you also consider this a bug, then I can probably provide a PR for a more robust solution, because we used an in-house implementation of the same thing, and didn't have this problem, but decided to switch to a packaged solution, but are now kind of holding back because of this.

    Bug 
    opened by maryokhin 11
  • HttpResponse has no 'data' on 0.4.0

    HttpResponse has no 'data' on 0.4.0

    Hey guys, just tried updating to 0.4.0 and it broke all my tests.

    Whenever I do a GET to a filtered cached list, I run the following test to check wether the amount of objects returned is ok:

    self.assertEqual(
        response.data['count'],
        3
    )
    

    But now I get the following error:

    AttributeError: 'HttpResponse' object has no attribute 'data'

    Django is 1.11.15, DRF is 3.8.2 and Python is 3.6 (haven't changed their versions, just drf-extensions).

    Thanks in advance!

    EDIT: Forgot to mention this is a cached list.

    opened by mbaragiola 10
  • [WIP] feat: add parent permission check.

    [WIP] feat: add parent permission check.

    FIX: #271 FIX: #142 FIX: #98

    Notice

    This PR hasn't been completed yet, it already meets what I need so I just mark it as draft.

    It needs to think more about some special cases(i mentioned several in code comments.) and make some tests.

    It's welcome for everyone to update based on those codes.

    you can fork my repo and start a PR to https://github.com/sobadgirl/drf-extensions

    OR

    just copy those codes to your repo and start a PR to https://github.com/chibisov/drf-extensions directly.

    Feature

    Add permission chain check to check parent permissions.

    Think you have those URLs:

    /api/users/1/
    /api/users/1/houses/
    /api/users/1/houses/1/
    /api/users/1/houses/1/tables/
    /api/users/1/houses/1/tables/1
    

    Before

    If you didn't have permission on /api/users/1, then you can't visit it. but you still can visit /api/users/1/houses and other subpaths of /api/users/1/.

    because when we visit /api/users/1/houses/, the request was sent to HouseViewSet directly, so DRF skipped checking the permission of UserViewSet.

    After

    when you visit /api/users/1/houses/ will check permission of UserViewSet.check_object_permissions. when you visit /api/users/1/houses/1/tables/ will check permissions of UserViewSet.check_object_permissions and HouseViewSet.check_object_permissions.

    so if you don't have permission to visit /api/users/1/, then you will be refuse to visit any subpath of /api/users/1/

    opened by sobadgirl 1
  • We are getting AttributeError: 'Response' object has no attribute '_headers'

    We are getting AttributeError: 'Response' object has no attribute '_headers'

    Line: rest_framework_extensions/cache/decorators.py

    We are using Cache Response Decorator, in our APIs _headers are not present since we are using custom Response Class

    opened by ownerni 2
  • distutils has been deprecated in Python 3.10 in favour of setuptools

    distutils has been deprecated in Python 3.10 in favour of setuptools

    https://github.com/chibisov/drf-extensions/blob/2a0bd3b66245a05a58e8e1d3bb62bf900520517e/rest_framework_extensions/utils.py#L2

    Ref : https://www.python.org/dev/peps/pep-0632/#migration-advice

    opened by tirkarthi 1
  • My Cron Job runs twice

    My Cron Job runs twice

    i develop a financial app that gives the customers their monthly income according to the percentages , but when i set up the cron job using the following package , the function runs twice and thats bad ,, is there any solution to this

    opened by macbotxxx 0
Releases(0.7.1)
Country-specific Django helpers, to use in Django Rest Framework

django-rest-localflavor Country-specific serializers fields, to Django Rest Framework Documentation (soon) The full documentation is at https://django

Gilson Filho 19 Aug 30, 2022
Django-rest-auth provides a set of REST API endpoints for Authentication and Registration

This app makes it extremely easy to build Django powered SPA's (Single Page App) or Mobile apps exposing all registration and authentication related functionality as CBV's (Class Base View) and REST (JSON)

Tivix 2.4k Dec 29, 2022
Authentication for Django Rest Framework

Dj-Rest-Auth Drop-in API endpoints for handling authentication securely in Django Rest Framework. Works especially well with SPAs (e.g React, Vue, Ang

Michael 1.1k Dec 28, 2022
A JSON Web Token authentication plugin for the Django REST Framework.

Simple JWT Abstract Simple JWT is a JSON Web Token authentication plugin for the Django REST Framework. For full documentation, visit django-rest-fram

Jazzband 3.3k Jan 4, 2023
Automated generation of real Swagger/OpenAPI 2.0 schemas from Django REST Framework code.

drf-yasg - Yet another Swagger generator Generate real Swagger/OpenAPI 2.0 specifications from a Django Rest Framework API. Compatible with Django Res

Cristi Vîjdea 3k Jan 6, 2023
Introduction to Django Rest Framework

Introduction to Django Rest Framework This is the repository of the video series Introduction to Django Rest Framework published on YouTube. It is a s

Simple is Better Than Complex 20 Jul 14, 2022
JSON:API support for Django REST framework

JSON:API and Django REST framework Overview JSON:API support for Django REST framework Documentation: https://django-rest-framework-json-api.readthedo

null 1k Dec 27, 2022
Generate Views, Serializers, and Urls for your Django Rest Framework application

DRF Generators Writing APIs can be boring and repetitive work. Don't write another CRUDdy view in Django Rest Framework. With DRF Generators, one simp

Tobin Brown 332 Dec 17, 2022
Swagger Documentation Generator for Django REST Framework: deprecated

Django REST Swagger: deprecated (2019-06-04) This project is no longer being maintained. Please consider drf-yasg as an alternative/successor. I haven

Marc Gibbons 2.6k Dec 23, 2022
Document Web APIs made with Django Rest Framework

DRF Docs Document Web APIs made with Django Rest Framework. View Demo Contributors Wanted: Do you like this project? Using it? Let's make it better! S

Manos Konstantinidis 626 Nov 20, 2022
Recursive Serialization for Django REST framework

djangorestframework-recursive Overview Recursive Serialization for Django REST framework This package provides a RecursiveField that enables you to se

null 336 Dec 28, 2022
Dropdown population implementation for Django REST Framework

drf-dropdown Dropdown population implementation for Django REST Framework Usage Add DropdownView to API URL # urls.py import dropdown urlpatterns = [

Preeti Yuankrathok 4 Dec 6, 2022
simple api build with django rest framework

Django Rest API django-rest-framework Employees management simple API in this project wrote test suites for endpoints wrote simple doc string for clas

OMAR.A 1 Mar 31, 2022
Simple Crud Api With Django Rest Framework

SIMPLE CRUD API WITH DJANGO REST FRAMEWORK Django REST framework is a powerful and flexible toolkit for building Web APIs. Requirements Python 3.6 Dja

kibet hillary 1 May 3, 2022
BloodDonors: Built using Django REST Framework for the API backend and React for the frontend

BloodDonors By Daniel Yuan, Alex Tian, Aaron Pan, Jennifer Yuan As the pandemic raged, one of the side effects was an urgent shortage of blood donatio

Daniel Yuan 1 Oct 24, 2021
Built on Django Rest Framework, to provide with command execution on linux terminal

Built on Django Rest Framework, to provide with command execution on linux terminal

null 1 Oct 31, 2021
RESTler is the first stateful REST API fuzzing tool for automatically testing cloud services through their REST APIs and finding security and reliability bugs in these services.

RESTler is the first stateful REST API fuzzing tool for automatically testing cloud services through their REST APIs and finding security and reliability bugs in these services.

Microsoft 1.8k Jan 4, 2023
Mlflow-rest-client - Python client for MLflow REST API

Python Client for MLflow Python client for MLflow REST API. Features: Minimal de

MTS 35 Dec 23, 2022
Django Ninja is a web framework for building APIs with Django and Python 3.6+ type hints.

?? Fast, Async-ready, Openapi, type hints based framework for building APIs

Vitaliy Kucheryaviy 3.8k Jan 4, 2023