Skip to content

Commit a0ee4a3

Browse files
authored
Merge pull request #326 from AltSchool/ALTOS-23940-django3
Altos 23940 support django3
2 parents cadee24 + 71071b8 commit a0ee4a3

35 files changed

+637
-260
lines changed

.circleci/python-versions.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.7.17 3.5.8 3.6.9 3.7.5 3.8.0
1+
3.6.9 3.7.5 3.8.0

.github/workflows/test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ jobs:
1212
strategy:
1313
fail-fast: false
1414
matrix:
15-
python-version: [3.5, 3.6, 3.7]
16-
dj-version: ["1.11.*", "2.0.*", "2.1.*", "2.2.*"]
17-
drf-version: ["3.8.*", "3.9.*", "3.10.*", "3.11.*"]
15+
python-version: [3.6, 3.7, 3.8]
16+
dj-version: ["2.2.*", "3.0.*", "3.1.*", "3.2.*"]
17+
drf-version: ["3.11.*", "3.12.*"]
1818

1919
steps:
2020
- uses: actions/checkout@v2

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ start: install
115115
# Lint the project
116116
lint: clean_working_directory
117117
$(call header,"Linting code")
118-
@find . -type f -name '*.py' -not -path '$(INSTALL_DIR)/*' -not -path './docs/*' -not -path '$(INSTALL_DIR)/*' | xargs $(INSTALL_DIR)/bin/flake8
118+
@find . -type f -name '*.py' -not -path '$(INSTALL_DIR)/*' -not -path './docs/*' -not -path './env/*' -not -path '$(INSTALL_DIR)/*' | xargs $(INSTALL_DIR)/bin/flake8
119119

120120
# Auto-format the project
121121
format: clean_working_directory

README.md

Lines changed: 76 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
# Dynamic REST
2-
3-
[![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)
1+
# Django Dynamic REST
42

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

1210
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
1311
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
12+
1413
# Table of Contents
1514

16-
- [Overview](#overview)
17-
- [Maintainers](#maintainers)
18-
- [Requirements](#requirements)
19-
- [Installation](#installation)
20-
- [Demo](#demo)
21-
- [Features](#features)
22-
- [Linked relationships](#linked-relationships)
23-
- [Sideloaded relationships](#sideloaded-relationships)
24-
- [Embedded relationships](#embedded-relationships)
25-
- [Inclusions](#inclusions)
26-
- [Exclusions](#exclusions)
27-
- [Filtering](#filtering)
28-
- [Ordering](#ordering)
29-
- [Directory panel](#directory-panel)
30-
- [Optimizations](#optimizations)
31-
- [Settings](#settings)
32-
- [Compatibility](#compatibility)
33-
- [Contributing](#contributing)
34-
- [License](#license)
15+
- [Overview](#overview)
16+
- [Maintainers](#maintainers)
17+
- [Requirements](#requirements)
18+
- [Installation](#installation)
19+
- [Demo](#demo)
20+
- [Features](#features)
21+
- [Linked relationships](#linked-relationships)
22+
- [Sideloaded relationships](#sideloaded-relationships)
23+
- [Embedded relationships](#embedded-relationships)
24+
- [Inclusions](#inclusions)
25+
- [Exclusions](#exclusions)
26+
- [Filtering](#filtering)
27+
- [Ordering](#ordering)
28+
- [Directory panel](#directory-panel)
29+
- [Optimizations](#optimizations)
30+
- [Settings](#settings)
31+
- [Compatibility](#compatibility)
32+
- [Contributing](#contributing)
33+
- [License](#license)
3534

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

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

4342
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:
4443

45-
* Linked relationships
46-
* Sideloaded relationships
47-
* Embedded relationships
48-
* Inclusions
49-
* Exclusions
50-
* Filtering
51-
* Sorting
52-
* Directory panel for your Browsable API
53-
* Optimizations
44+
- Linked relationships
45+
- Sideloaded relationships
46+
- Embedded relationships
47+
- Inclusions
48+
- Exclusions
49+
- Filtering
50+
- Sorting
51+
- Directory panel for your Browsable API
52+
- Optimizations
5453

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

5858
## Maintainers
5959

60-
* [Anthony Leontiev](mailto:[email protected])
61-
* [Ryo Chijiiwa](mailto:[email protected])
62-
* [Savinay Nangalia](mailto:[email protected])
60+
- [Anthony Leontiev](mailto:[email protected]>)
61+
- [Savinay Nangalia](mailto:[email protected])
62+
- [Christina D'Astolfo](mailto:[email protected])
63+
64+
## Contributors
65+
66+
- [Ernesto González](mailto:[email protected])
6367

6468
# Requirements
6569

66-
* Python (3.5, 3.6, 3.7)
67-
* Django (1.11, 2.0, 2.1, 2.2)
68-
* Django REST Framework (3.8, 3.9, 3.10, 3.11)
70+
- Python (3.6, 3.7, 3.8)
71+
- Django (2.2, 3.1, 3.2)
72+
- Django REST Framework (3.11, 3.12)
6973

7074
# Installation
7175

72-
1) Install using `pip`:
76+
1. Install using `pip`:
7377

7478
```bash
7579
pip install dynamic-rest
7680
```
7781

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

80-
2) Add `rest_framework` and `dynamic_rest` to `INSTALLED_APPS` in `settings.py`:
84+
2. Add `rest_framework` and `dynamic_rest` to `INSTALLED_APPS` in `settings.py`:
8185

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

8993
```
9094

91-
3) If you want to use the [Directory panel](#directory-panel), replace DRF's browsable API renderer with DREST's
92-
in your settings:
93-
95+
3. If you want to use the [Directory panel](#directory-panel), replace DRF's browsable API renderer with DREST's
96+
in your settings:
97+
9498
```python
9599
REST_FRAMEWORK = {
96100
'DEFAULT_RENDERER_CLASSES': [
97101
'rest_framework.renderers.JSONRenderer',
98102
'dynamic_rest.renderers.DynamicBrowsableAPIRenderer',
99103
],
100-
}
104+
}
101105
```
102106

103107
# Demo
104108

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

108-
1) Clone this repository:
112+
1. Clone this repository:
109113

110114
```bash
111115
git clone [email protected]:AltSchool/dynamic-rest.git
112116
cd dynamic-rest
113117
```
114118

115-
2) From within the repository root, start the demo server:
119+
2. From within the repository root, start the demo server:
116120

117121
```bash
118122
make serve
119123
```
120124

121-
3) Visit `localhost:9002` in your browser.
125+
3. Visit `localhost:9002` in your browser.
122126

123-
4) To load sample fixture data, run `make fixtures` and restart the server.
127+
4. To load sample fixture data, run `make fixtures` and restart the server.
124128

125129
# Features
126130

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

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

249253
```
250-
-->
254+
-->
251255
GET /users/1/?include[]=groups.location.*&include[]=location.*
252256
<--
253257
200 OK
@@ -282,7 +286,7 @@ For example, to obtain the user with groups, locations, and groups' locations al
282286

283287
## Embedded relationships
284288

285-
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.
289+
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.
286290

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

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

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

330334
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.
331335

332-
## Inclusions
336+
## Inclusions
333337

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

@@ -346,7 +350,7 @@ class UserSerializer(DynamicModelSerializer):
346350
name = 'user'
347351
fields = ("id", "name", "location", "groups", "personal_statement")
348352
deferred_fields = ("personal_statement", )
349-
353+
350354
location = DynamicRelationField('LocationSerializer')
351355
groups = DynamicRelationField('GroupSerializer', many=True)
352356

@@ -373,7 +377,7 @@ This field will only be returned if requested:
373377
}
374378
```
375379

376-
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.
380+
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.
377381

378382
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.
379383

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

455459
```
456-
-->
460+
-->
457461
GET /users/?filter{name.icontains}=jo
458462
<--
459463
200 OK
@@ -516,13 +520,13 @@ You can filter a user by his name (exact match):
516520

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

519-
* in
520-
* icontains
521-
* istartswith
522-
* range
523-
* lt
524-
* gt
525-
...
523+
- in
524+
- icontains
525+
- istartswith
526+
- range
527+
- lt
528+
- gt
529+
...
526530

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

@@ -558,8 +562,8 @@ DREST adds that in:
558562
## Optimizations
559563

560564
Supporting nested sideloading and filtering is expensive and can lead to very poor query performance if implemented naively.
561-
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.
562-
We also optimize the serializer layer to ensure that the conversion of model objects into JSON is as fast as possible.
565+
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.
566+
We also optimize the serializer layer to ensure that the conversion of model objects into JSON is as fast as possible.
563567

564568
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:
565569

@@ -595,7 +599,7 @@ DYNAMIC_REST = {
595599
# ENABLE_SERIALIZER_OPTIMIZATIONS: enable/disable representation speedups
596600
'ENABLE_SERIALIZER_OPTIMIZATIONS': True,
597601

598-
# DEFER_MANY_RELATIONS: automatically defer many-relations, unless
602+
# DEFER_MANY_RELATIONS: automatically defer many-relations, unless
599603
# `deferred=False` is explicitly set on the field.
600604
'DEFER_MANY_RELATIONS': False,
601605

@@ -626,15 +630,15 @@ DYNAMIC_REST = {
626630
}
627631
```
628632

629-
# Compatibility
633+
# Compatibility
630634

631635
We actively support the following:
632636

633-
* Python: 2.7, 3.5, 3.6, 3.7
634-
* Django: 1.11, 2.0, 2.2
635-
* Django Rest Framework: 3.4 ~ 3.10
637+
- Python: 3.6, 3.7, 3.8
638+
- Django: 2.2, 3.1, 3.2
639+
- Django Rest Framework: 3.11, 3.12
636640

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

639643
# Contributing
640644

README.rst

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Dynamic REST
2-
============
2+
===================
33

44
**Dynamic API extensions for Django REST Framework**
55

@@ -34,12 +34,13 @@ over HTTP.
3434
Maintainers
3535
-----------
3636

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

4041
Requirements
4142
============
4243

43-
- Python (2.7, 3.5, 3.6, 3.7)
44-
- Django (1.11, 2.0, 2.1, 2.2)
45-
- Django REST Framework (3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10)
44+
- Python (3.6, 3.7, 3.8)
45+
- Django (2.2, 3.1, 3.2)
46+
- Django REST Framework (3.10, 3.11, 3.12)

benchmarks.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
verticalAlign: 'middle',
3737
borderWidth: 0
3838
},
39-
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"}]
39+
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]]}]
4040
});
4141
});
4242
</script>
@@ -75,7 +75,7 @@
7575
verticalAlign: 'middle',
7676
borderWidth: 0
7777
},
78-
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"}]
78+
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]]}]
7979
});
8080
});
8181
</script>
@@ -114,7 +114,7 @@
114114
verticalAlign: 'middle',
115115
borderWidth: 0
116116
},
117-
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"}]
117+
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]]}]
118118
});
119119
});
120120
</script>

benchmarks/drest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class UserViewSet(viewsets.DynamicModelViewSet):
5555
queryset = User.objects.all()
5656
serializer_class = UserSerializer
5757

58+
5859
# DREST router
5960

6061
router = routers.DynamicRouter()

benchmarks/drf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class UserWithAllViewSet(viewsets.ModelViewSet):
7171
queryset = User.objects.all()
7272
serializer_class = UserWithAllSerializer
7373

74+
7475
# DRF routing
7576

7677
router = routers.DefaultRouter()

0 commit comments

Comments
 (0)