Skip to content

Commit

Permalink
Merge pull request #326 from AltSchool/ALTOS-23940-django3
Browse files Browse the repository at this point in the history
Altos 23940 support django3
  • Loading branch information
chdastolfo authored Nov 9, 2021
2 parents cadee24 + 71071b8 commit a0ee4a3
Show file tree
Hide file tree
Showing 35 changed files with 637 additions and 260 deletions.
2 changes: 1 addition & 1 deletion .circleci/python-versions.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.7.17 3.5.8 3.6.9 3.7.5 3.8.0
3.6.9 3.7.5 3.8.0
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.5, 3.6, 3.7]
dj-version: ["1.11.*", "2.0.*", "2.1.*", "2.2.*"]
drf-version: ["3.8.*", "3.9.*", "3.10.*", "3.11.*"]
python-version: [3.6, 3.7, 3.8]
dj-version: ["2.2.*", "3.0.*", "3.1.*", "3.2.*"]
drf-version: ["3.11.*", "3.12.*"]

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ start: install
# Lint the project
lint: clean_working_directory
$(call header,"Linting code")
@find . -type f -name '*.py' -not -path '$(INSTALL_DIR)/*' -not -path './docs/*' -not -path '$(INSTALL_DIR)/*' | xargs $(INSTALL_DIR)/bin/flake8
@find . -type f -name '*.py' -not -path '$(INSTALL_DIR)/*' -not -path './docs/*' -not -path './env/*' -not -path '$(INSTALL_DIR)/*' | xargs $(INSTALL_DIR)/bin/flake8

# Auto-format the project
format: clean_working_directory
Expand Down
148 changes: 76 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# Dynamic REST

[![Join the chat at https://gitter.im/dynamic-rest/Lobby](https://badges.gitter.im/dynamic-rest/Lobby.svg)](https://gitter.im/dynamic-rest/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# Django Dynamic REST

[![Circle CI](https://circleci.com/gh/AltSchool/dynamic-rest.svg?style=svg)](https://circleci.com/gh/AltSchool/dynamic-rest)
[![PyPi](https://img.shields.io/pypi/v/dynamic-rest.svg)](https://pypi.python.org/pypi/dynamic-rest)
Expand All @@ -11,27 +9,28 @@ See http://dynamic-rest.readthedocs.org for full documentation.

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

# Table of Contents

- [Overview](#overview)
- [Maintainers](#maintainers)
- [Requirements](#requirements)
- [Installation](#installation)
- [Demo](#demo)
- [Features](#features)
- [Linked relationships](#linked-relationships)
- [Sideloaded relationships](#sideloaded-relationships)
- [Embedded relationships](#embedded-relationships)
- [Inclusions](#inclusions)
- [Exclusions](#exclusions)
- [Filtering](#filtering)
- [Ordering](#ordering)
- [Directory panel](#directory-panel)
- [Optimizations](#optimizations)
- [Settings](#settings)
- [Compatibility](#compatibility)
- [Contributing](#contributing)
- [License](#license)
- [Overview](#overview)
- [Maintainers](#maintainers)
- [Requirements](#requirements)
- [Installation](#installation)
- [Demo](#demo)
- [Features](#features)
- [Linked relationships](#linked-relationships)
- [Sideloaded relationships](#sideloaded-relationships)
- [Embedded relationships](#embedded-relationships)
- [Inclusions](#inclusions)
- [Exclusions](#exclusions)
- [Filtering](#filtering)
- [Ordering](#ordering)
- [Directory panel](#directory-panel)
- [Optimizations](#optimizations)
- [Settings](#settings)
- [Compatibility](#compatibility)
- [Contributing](#contributing)
- [License](#license)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand All @@ -42,42 +41,47 @@ empower simple RESTful APIs with the flexibility of a graph query language.

DREST classes can be used as a drop-in replacement for DRF classes, which offer the following features on top of the standard DRF kit:

* Linked relationships
* Sideloaded relationships
* Embedded relationships
* Inclusions
* Exclusions
* Filtering
* Sorting
* Directory panel for your Browsable API
* Optimizations
- Linked relationships
- Sideloaded relationships
- Embedded relationships
- Inclusions
- Exclusions
- Filtering
- Sorting
- Directory panel for your Browsable API
- Optimizations

DREST was initially written to complement [Ember Data](https://github.com/emberjs/data),
but it can be used to provide fast and flexible CRUD operations to any consumer that supports JSON over HTTP.
DREST was originally written to complement [Ember](https://github.com/emberjs/data)\_\_, but it can be used to provide
fast and flexible CRUD operations to any consumer that supports JSON
over HTTP.

## Maintainers

* [Anthony Leontiev](mailto:[email protected])
* [Ryo Chijiiwa](mailto:[email protected])
* [Savinay Nangalia](mailto:[email protected])
- [Anthony Leontiev](mailto:[email protected]>)
- [Savinay Nangalia](mailto:[email protected])
- [Christina D'Astolfo](mailto:[email protected])

## Contributors

- [Ernesto González](mailto:[email protected])

# Requirements

* Python (3.5, 3.6, 3.7)
* Django (1.11, 2.0, 2.1, 2.2)
* Django REST Framework (3.8, 3.9, 3.10, 3.11)
- Python (3.6, 3.7, 3.8)
- Django (2.2, 3.1, 3.2)
- Django REST Framework (3.11, 3.12)

# Installation

1) Install using `pip`:
1. Install using `pip`:

```bash
pip install dynamic-rest
```

(or add `dynamic-rest` to `requirements.txt` or `setup.py`)

2) Add `rest_framework` and `dynamic_rest` to `INSTALLED_APPS` in `settings.py`:
2. Add `rest_framework` and `dynamic_rest` to `INSTALLED_APPS` in `settings.py`:

```python
INSTALLED_APPS = (
Expand All @@ -88,39 +92,39 @@ but it can be used to provide fast and flexible CRUD operations to any consumer

```

3) If you want to use the [Directory panel](#directory-panel), replace DRF's browsable API renderer with DREST's
in your settings:
3. If you want to use the [Directory panel](#directory-panel), replace DRF's browsable API renderer with DREST's
in your settings:

```python
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'dynamic_rest.renderers.DynamicBrowsableAPIRenderer',
],
}
}
```

# Demo

This repository comes with a `tests` package that also serves as a demo application.
This application is hosted at https://dynamic-rest.herokuapp.com but can also be run locally:

1) Clone this repository:
1. Clone this repository:

```bash
git clone [email protected]:AltSchool/dynamic-rest.git
cd dynamic-rest
```

2) From within the repository root, start the demo server:
2. From within the repository root, start the demo server:

```bash
make serve
```

3) Visit `localhost:9002` in your browser.
3. Visit `localhost:9002` in your browser.

4) To load sample fixture data, run `make fixtures` and restart the server.
4. To load sample fixture data, run `make fixtures` and restart the server.

# Features

Expand Down Expand Up @@ -215,7 +219,7 @@ In DREST, the requirement to eagerly load (or "sideload") relationships can be e
For example, in order to fetch a user and sideload their groups:

```
-->
-->
GET /users/1/?include[]=groups.*
<--
200 OK
Expand Down Expand Up @@ -247,7 +251,7 @@ With DREST, it is possible to sideload as many relationships as you'd like, as d
For example, to obtain the user with groups, locations, and groups' locations all sideloaded in the same response:

```
-->
-->
GET /users/1/?include[]=groups.location.*&include[]=location.*
<--
200 OK
Expand Down Expand Up @@ -282,7 +286,7 @@ For example, to obtain the user with groups, locations, and groups' locations al

## Embedded relationships

If you want your relationships loaded eagerly but don't want them sideloaded in the top-level, you can instruct your serializer to embed relationships instead.
If you want your relationships loaded eagerly but don't want them sideloaded in the top-level, you can instruct your serializer to embed relationships instead.

In that case, the demo serializer above would look like this:

Expand All @@ -303,7 +307,7 @@ class UserSerializer(DynamicModelSerializer):
... and the call above would return a response with relationships embedded in place of the usual ID representation:

```
-->
-->
GET /users/1/?include[]=groups.*
<--
200 OK
Expand All @@ -329,7 +333,7 @@ In DREST, sideloading is the default because it can produce much smaller payload

For example, if you requested a list of 10 users along with their groups, and those users all happened to be in the same groups, the embedded variant would represent each group 10 times. The sideloaded variant would only represent a particular group once, regardless of the number of times that group is referenced.

## Inclusions
## Inclusions

You can use the `include[]` feature not only to sideload relationships, but also to load basic fields that are marked "deferred".

Expand All @@ -346,7 +350,7 @@ class UserSerializer(DynamicModelSerializer):
name = 'user'
fields = ("id", "name", "location", "groups", "personal_statement")
deferred_fields = ("personal_statement", )

location = DynamicRelationField('LocationSerializer')
groups = DynamicRelationField('GroupSerializer', many=True)

Expand All @@ -373,7 +377,7 @@ This field will only be returned if requested:
}
```

Note that `include[]=personal_statement` does not have a `.` following the field name as in the previous examples for embedding and sideloading relationships. This allows us to differentiate between cases where we have a deferred relationship and want to include the relationship IDs as opposed to including and also sideloading the relationship.
Note that `include[]=personal_statement` does not have a `.` following the field name as in the previous examples for embedding and sideloading relationships. This allows us to differentiate between cases where we have a deferred relationship and want to include the relationship IDs as opposed to including and also sideloading the relationship.

For example, if the user had a deferred "events" relationship, passing `include[]=events` would return an "events" field populated by event IDs, passing `include[]=events.` would sideload or embed the events themselves, and by default, only a link to the events would be returned. This can be useful for large has-many relationships.

Expand Down Expand Up @@ -453,7 +457,7 @@ You can filter a user by his name (exact match):
... or a partial match:

```
-->
-->
GET /users/?filter{name.icontains}=jo
<--
200 OK
Expand Down Expand Up @@ -516,13 +520,13 @@ You can filter a user by his name (exact match):

The sky is the limit! DREST supports just about every basic filtering scenario and operator that you can use in Django:

* in
* icontains
* istartswith
* range
* lt
* gt
...
- in
- icontains
- istartswith
- range
- lt
- gt
...

See the [full list here](dynamic_rest/filters.py#L153-L176).

Expand Down Expand Up @@ -558,8 +562,8 @@ DREST adds that in:
## Optimizations

Supporting nested sideloading and filtering is expensive and can lead to very poor query performance if implemented naively.
DREST uses Django's [Prefetch](https://docs.djangoproject.com/en/1.9/ref/models/querysets/#django.db.models.Prefetch) object to prevent N+1 query situations and guarantee that your API is performant.
We also optimize the serializer layer to ensure that the conversion of model objects into JSON is as fast as possible.
DREST uses Django's [Prefetch](https://docs.djangoproject.com/en/1.9/ref/models/querysets/#django.db.models.Prefetch) object to prevent N+1 query situations and guarantee that your API is performant.
We also optimize the serializer layer to ensure that the conversion of model objects into JSON is as fast as possible.

How fast is it? Here are some [benchmarks](benchmarks) that compare DREST response time to DRF response time. DREST out-performs DRF on every benchmark:

Expand Down Expand Up @@ -595,7 +599,7 @@ DYNAMIC_REST = {
# ENABLE_SERIALIZER_OPTIMIZATIONS: enable/disable representation speedups
'ENABLE_SERIALIZER_OPTIMIZATIONS': True,

# DEFER_MANY_RELATIONS: automatically defer many-relations, unless
# DEFER_MANY_RELATIONS: automatically defer many-relations, unless
# `deferred=False` is explicitly set on the field.
'DEFER_MANY_RELATIONS': False,

Expand Down Expand Up @@ -626,15 +630,15 @@ DYNAMIC_REST = {
}
```

# Compatibility
# Compatibility

We actively support the following:

* Python: 2.7, 3.5, 3.6, 3.7
* Django: 1.11, 2.0, 2.2
* Django Rest Framework: 3.4 ~ 3.10
- Python: 3.6, 3.7, 3.8
- Django: 2.2, 3.1, 3.2
- Django Rest Framework: 3.11, 3.12

**Note:** Some combinations are not supported. For up-to-date information on actively supported/tested combinations, see the tox.ini file.
**Note:** Some combinations are not supported. For up-to-date information on actively supported/tested combinations, see the `tox.ini` file.

# Contributing

Expand Down
13 changes: 7 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Dynamic REST
============
===================

**Dynamic API extensions for Django REST Framework**

Expand Down Expand Up @@ -34,12 +34,13 @@ over HTTP.
Maintainers
-----------

- `Anthony Leontiev <mailto:[email protected]>`__
- `Ryo Chijiiwa <mailto:[email protected]>`__
- `Anthony Leontiev <mailto:[email protected]>`__
- `Savinay Nangalia <mailto:[email protected]>`__
- `Christina D'Astolfo <mailto:[email protected]>`__

Requirements
============

- Python (2.7, 3.5, 3.6, 3.7)
- Django (1.11, 2.0, 2.1, 2.2)
- Django REST Framework (3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10)
- Python (3.6, 3.7, 3.8)
- Django (2.2, 3.1, 3.2)
- Django REST Framework (3.10, 3.11, 3.12)
6 changes: 3 additions & 3 deletions benchmarks.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
verticalAlign: 'middle',
borderWidth: 0
},
series: [{"data": [[3, 0.010598], [14, 0.0129435], [39, 0.0169945], [84, 0.0209405], [155, 0.029427500000000002], [258, 0.0405075], [399, 0.048523], [584, 0.0625845], [819, 0.084913], [1110, 0.100662], [1463, 0.12601800000000002], [1884, 0.156378], [2379, 0.19036199999999998], [2954, 0.223039], [3615, 0.29465399999999997], [4368, 0.356249]], "name": "DREST 1.3.9"}, {"data": [[3, 0.004224], [14, 0.0083045], [39, 0.013636], [84, 0.0233625], [155, 0.034529000000000004], [258, 0.052696], [399, 0.06697], [584, 0.091702], [819, 0.127831], [1110, 0.1734345], [1463, 0.21316000000000002], [1884, 0.2423265], [2379, 0.2996175], [2954, 0.39503699999999997], [3615, 0.4300615], [4368, 0.579607]], "name": "DRF 3.3.0"}]
series: [{"name": "DREST 2.0.0", "data": [[3, 0.0037530000000000003], [14, 0.004215], [39, 0.0047805], [84, 0.005736], [155, 0.006875], [258, 0.0083385], [399, 0.010683000000000002], [584, 0.0135645], [819, 0.016668000000000002], [1110, 0.020622], [1463, 0.025916500000000002], [1884, 0.031551499999999996], [2379, 0.0381205], [2954, 0.0471535], [3615, 0.0551515], [4368, 0.0671345]]}, {"name": "DRF 3.12.4", "data": [[3, 0.0016465], [14, 0.0033355], [39, 0.005826], [84, 0.0093875], [155, 0.014127], [258, 0.0199585], [399, 0.027033], [584, 0.035491499999999995], [819, 0.044836], [1110, 0.056142], [1463, 0.0692645], [1884, 0.085964], [2379, 0.10098850000000001], [2954, 0.122303], [3615, 0.1445205], [4368, 0.16253800000000002]]}]
});
});
</script>
Expand Down Expand Up @@ -75,7 +75,7 @@
verticalAlign: 'middle',
borderWidth: 0
},
series: [{"data": [[256, 0.013802499999999999], [512, 0.022781000000000003], [768, 0.0313405], [1024, 0.043452], [1280, 0.053339], [1536, 0.060793], [1792, 0.07044500000000001], [2048, 0.0799765], [2304, 0.09236649999999999], [2560, 0.09833549999999999], [2816, 0.10974600000000001], [3072, 0.1534385], [3328, 0.1260365], [3584, 0.14711249999999998], [3840, 0.15910649999999998], [4096, 0.1562075]], "name": "DREST 1.3.9"}, {"data": [[256, 0.185573], [512, 0.37659200000000004], [768, 0.5544685], [1024, 0.762219], [1280, 0.9522345], [1536, 1.1424555], [1792, 1.3354335], [2048, 1.4902134999999999], [2304, 1.6737704999999998], [2560, 1.9133445], [2816, 1.9982449999999998], [3072, 2.3125815000000003], [3328, 2.449006], [3584, 2.68817], [3840, 2.7430269999999997], [4096, 2.9553125]], "name": "DRF 3.3.0"}]
series: [{"name": "DREST 2.0.0", "data": [[256, 0.004253], [512, 0.007494499999999999], [768, 0.010120500000000001], [1024, 0.0127455], [1280, 0.0157595], [1536, 0.018013], [1792, 0.0212245], [2048, 0.0240905], [2304, 0.02581], [2560, 0.0287565], [2816, 0.0314165], [3072, 0.0506805], [3328, 0.0382505], [3584, 0.042971], [3840, 0.0428355], [4096, 0.0469565]]}, {"name": "DRF 3.12.4", "data": [[256, 0.08546100000000001], [512, 0.171128], [768, 0.2598395], [1024, 0.33919750000000004], [1280, 0.426328], [1536, 0.5128635], [1792, 0.5989595], [2048, 0.684221], [2304, 0.762429], [2560, 0.8562815], [2816, 0.9428665], [3072, 1.0435575], [3328, 1.1402725], [3584, 1.208104], [3840, 1.29737], [4096, 1.403646]]}]
});
});
</script>
Expand Down Expand Up @@ -114,7 +114,7 @@
verticalAlign: 'middle',
borderWidth: 0
},
series: [{"data": [[20, 0.008997], [72, 0.013781999999999999], [156, 0.018541500000000002], [272, 0.0260965], [420, 0.034469], [600, 0.041933], [812, 0.053789000000000003], [1056, 0.069213], [1332, 0.081873], [1640, 0.097342], [1980, 0.135785], [2352, 0.1346085], [2756, 0.18510549999999998], [3192, 0.175554], [3660, 0.2170925], [4160, 0.2353975]], "name": "DREST 1.3.9"}, {"data": [[20, 0.007074], [72, 0.0140755], [156, 0.0215725], [272, 0.032983], [420, 0.0472835], [600, 0.062189], [812, 0.0772765], [1056, 0.105318], [1332, 0.12905250000000001], [1640, 0.1433465], [1980, 0.1805545], [2352, 0.222216], [2756, 0.25613400000000003], [3192, 0.3107965], [3660, 0.34135099999999996], [4160, 0.38530699999999996]], "name": "DRF 3.3.0"}]
series: [{"name": "DREST 2.0.0", "data": [[20, 0.003006], [72, 0.004069], [156, 0.005076], [272, 0.006527], [420, 0.0086305], [600, 0.010717], [812, 0.013677], [1056, 0.016252], [1332, 0.020575], [1640, 0.024105500000000002], [1980, 0.0269815], [2352, 0.032959], [2756, 0.036424], [3192, 0.043724], [3660, 0.047021], [4160, 0.0538335]]}, {"name": "DRF 3.12.4", "data": [[20, 0.0027085], [72, 0.004940999999999999], [156, 0.0076405], [272, 0.0109555], [420, 0.0148125], [600, 0.018860000000000002], [812, 0.0231945], [1056, 0.0287305], [1332, 0.0355045], [1640, 0.041485], [1980, 0.047808], [2352, 0.056248], [2756, 0.062773], [3192, 0.071774], [3660, 0.07946], [4160, 0.0885375]]}]
});
});
</script>
Expand Down
1 change: 1 addition & 0 deletions benchmarks/drest.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class UserViewSet(viewsets.DynamicModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer


# DREST router

router = routers.DynamicRouter()
Expand Down
1 change: 1 addition & 0 deletions benchmarks/drf.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class UserWithAllViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserWithAllSerializer


# DRF routing

router = routers.DefaultRouter()
Expand Down
Loading

0 comments on commit a0ee4a3

Please sign in to comment.