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)
Django REST API with React BoilerPlate

This is a setup of Authentication and Registration Integrated with React.js inside the Django Templates for web apps

Faisal Nazik 91 Dec 30, 2022
Little Library API REST

Little Library API REST py 3.10 The only one requeriment it's to have Flask installed.

Luis Quiñones Requelme 1 Dec 15, 2021
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 06, 2023
A Django api to display items and their current up-to-date prices from different online retailers in one platform.

A Django api to display items and their current up-to-date prices from different online retailers in one platform. Utilizing scrapy to periodically scrape the latest prices from different online reta

Kennedy Ngugi Mwaura 1 Nov 05, 2021
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
One package to access multiple different data sources through their respective API platforms.

BESTLab Platform One package to access multiple different data sources through their respective API platforms. Usage HOBO Platform See hobo_example.py

Wei 1 Nov 16, 2021
A Django-powered API with various utility apps / endpoints.

A Django-powered API Includes various utility apps / endpoints. Demos These web apps provide a frontend to the APIs in this project. Issue API Explore

Shemar Lindie 0 Sep 13, 2021
FastAPI framework, high performance, easy to learn, fast to code, ready for production

FastAPI framework, high performance, easy to learn, fast to code, ready for production Documentation: https://fastapi.tiangolo.com Source Code: https:

Sebastián Ramírez 53.1k Jan 06, 2023
A small repository of projects built in my course, REST APIs with Flask and Python.

A small repository of projects built in my course, REST APIs with Flask and Python.

Teclado 1k Jan 05, 2023
Scaffold django rest apis like a champion 🚀

scaffold django rest apis like a champion 🚀

Abdenasser Elidrissi 133 Jan 05, 2023
The no-nonsense, minimalist REST and app backend framework for Python developers, with a focus on reliability, correctness, and performance at scale.

The Falcon Web Framework Falcon is a reliable, high-performance Python web framework for building large-scale app backends and microservices. It encou

Falconry 9k Jan 03, 2023
Django queries

Djaq Djaq - pronounced “Jack” - provides an instant remote API to your Django models data with a powerful query language. No server-side code beyond t

Paul Wolf 53 Dec 12, 2022
A minimalistic manga reader for desktop built with React and Django

smanga A minimalistic manga reader/server for serving local manga images on desktop browser. Provides a two-page view layout just as reading a physica

Padam Upreti 13 Sep 24, 2022
Eazytraining - Simple application to show how to query API from webapp

student-list Eazytraining - Simple application to show how to query API from webapp This repo is a simple application to list student with a webserver

⚡Christophe FREIJANES 2 Nov 15, 2021
BreakFastApi 🍣 🍔 🍕 The most delicious API on the web

BreakFastApi 🍣 🍔 🍕 The most delicious API on the web. Just send a request and you'll receive the most mouth watering dish recipe with estimated coo

Mariia Sizova 156 Nov 19, 2022
REST API framework designed for human beings

Eve Eve is an open source Python REST API framework designed for human beings. It allows to effortlessly build and deploy highly customizable, fully f

eve 6.6k Jan 04, 2023
Transparently use webpack with django

Looking for maintainers This repository is unmaintained as I don't have any free time to dedicate to this effort. If you or your organisation are heav

2.4k Dec 24, 2022
Allows simplified Python interaction with Rapid7's InsightIDR REST API.

InsightIDR4Py Allows simplified Python interaction with Rapid7's InsightIDR REST API. InsightIDR4Py allows analysts to query log data from Rapid7 Insi

Micah Babinski 8 Sep 12, 2022
Key-Value база данных на Tarantool и REST API к ней.

KVmail Key-Value база данных на Tarantool и REST API к ней. Документация к API доступна здесь. Requiremrnts ubuntu 16.04+ python3.6+ supervisord nginx

1 Jun 16, 2021