Skip to content

Commit 01e399d

Browse files
authored
Merge pull request #1 from django-json-api/master
Update my fork
2 parents 2033bc5 + 5f19ef0 commit 01e399d

27 files changed

+253
-57
lines changed

.pyup.yml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
search: False
2+
schedule: "every two weeks"
23
requirements:
34
- requirements/requirements-codestyle.txt:
45
update: all

.travis.yml

+39-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
language: python
2+
dist: xenial
23
sudo: required
34
cache: pip
45
# Favor explicit over implicit and use an explicit build matrix.
@@ -12,6 +13,10 @@ matrix:
1213
- env: TOXENV=py35-django22-drfmaster
1314
- env: TOXENV=py36-django22-drfmaster
1415
- env: TOXENV=py37-django22-drfmaster
16+
- env: TOXENV=py38-django22-drfmaster
17+
- env: TOXENV=py36-django30-drfmaster
18+
- env: TOXENV=py37-django30-drfmaster
19+
- env: TOXENV=py38-django30-drfmaster
1520

1621
include:
1722
- python: 3.6
@@ -21,50 +26,72 @@ matrix:
2126

2227
- python: 3.5
2328
env: TOXENV=py35-django111-drf310
29+
- python: 3.5
30+
env: TOXENV=py35-django111-drf311
2431
- python: 3.5
2532
env: TOXENV=py35-django111-drfmaster
2633
- python: 3.5
2734
env: TOXENV=py35-django21-drf310
35+
- python: 3.5
36+
env: TOXENV=py35-django21-drf311
2837
- python: 3.5
2938
env: TOXENV=py35-django21-drfmaster
3039
- python: 3.5
31-
dist: xenial
3240
env: TOXENV=py35-django22-drf310
3341
- python: 3.5
34-
dist: xenial
42+
env: TOXENV=py35-django22-drf311
43+
- python: 3.5
3544
env: TOXENV=py35-django22-drfmaster
3645

3746
- python: 3.6
3847
env: TOXENV=py36-django111-drf310
48+
- python: 3.6
49+
env: TOXENV=py36-django111-drf311
3950
- python: 3.6
4051
env: TOXENV=py36-django111-drfmaster
4152
- python: 3.6
4253
env: TOXENV=py36-django21-drf310
54+
- python: 3.6
55+
env: TOXENV=py36-django21-drf311
4356
- python: 3.6
4457
env: TOXENV=py36-django21-drfmaster
4558
- python: 3.6
46-
dist: xenial
4759
env: TOXENV=py36-django22-drf310
4860
- python: 3.6
49-
dist: xenial
61+
env: TOXENV=py36-django22-drf311
62+
- python: 3.6
5063
env: TOXENV=py36-django22-drfmaster
64+
- python: 3.6
65+
env: TOXENV=py36-django30-drf311
66+
- python: 3.6
67+
env: TOXENV=py36-django30-drfmaster
5168

5269
- python: 3.7
53-
dist: xenial
54-
sudo: required
5570
env: TOXENV=py37-django21-drf310
5671
- python: 3.7
57-
dist: xenial
58-
sudo: required
72+
env: TOXENV=py37-django21-drf311
73+
- python: 3.7
5974
env: TOXENV=py37-django21-drfmaster
6075
- python: 3.7
61-
dist: xenial
62-
sudo: required
6376
env: TOXENV=py37-django22-drf310
6477
- python: 3.7
65-
dist: xenial
66-
sudo: required
78+
env: TOXENV=py37-django22-drf311
79+
- python: 3.7
6780
env: TOXENV=py37-django22-drfmaster
81+
- python: 3.7
82+
env: TOXENV=py37-django30-drf311
83+
- python: 3.7
84+
env: TOXENV=py37-django30-drfmaster
85+
86+
- python: 3.8
87+
env: TOXENV=py38-django22-drf311
88+
- python: 3.8
89+
env: TOXENV=py38-django22-drfmaster
90+
- python: 3.8
91+
env: TOXENV=py38-django30-drf311
92+
- python: 3.8
93+
env: TOXENV=py38-django30-drfmaster
94+
6895
install:
6996
- pip install tox
7097
script:

AUTHORS

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Adam Wróbel <https://adamwrobel.com>
22
Adam Ziolkowski <[email protected]>
33
Alan Crosswell <[email protected]>
44
Anton Shutik <[email protected]>
5+
Boris Pleshakov <[email protected]>
56
Christian Zosel <https://zosel.ch>
67
David Vogt <[email protected]>
78
Greg Aker <[email protected]>
@@ -26,3 +27,4 @@ Stas S. <[email protected]>
2627
Nathanael Gordon <[email protected]>
2728
Charlie Allatson <[email protected]>
2829
Joseba Mendivil <[email protected]>
30+
Felix Viernickel <[email protected]>

CHANGELOG.md

+15
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
Note that in line with [Django REST Framework policy](http://www.django-rest-framework.org/topics/release-notes/),
99
any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.
1010

11+
## [3.1.0] - 2020-02-08
12+
13+
### Added
14+
15+
* Added support for Python 3.8
16+
* Added support for Django REST framework 3.11
17+
* Added support for Django 3.0
18+
19+
### Fixed
20+
21+
* Ensured that `409 Conflict` is returned when processing a `PATCH` request in which the resource object’s type and id do not match the server’s endpoint as outlined in [JSON:API](https://jsonapi.org/format/#crud-updating-responses-409) spec.
22+
* Properly return parser error when primary data is of invalid type
23+
* Pass instance to child serializers when using `PolymorphicModelSerializer`
24+
* Properly resolve related resource type when using `PolymorphicModelSerializer`
25+
1126
## [3.0.0] - 2019-10-14
1227

1328
This release is not backwards compatible. For easy migration best upgrade first to version

README.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ As a Django REST Framework JSON API (short DJA) we are trying to address followi
8787
Requirements
8888
------------
8989

90-
1. Python (3.5, 3.6, 3.7)
91-
2. Django (1.11, 2.1, 2.2)
92-
3. Django REST Framework (3.10)
90+
1. Python (3.5, 3.6, 3.7, 3.8)
91+
2. Django (1.11, 2.1, 2.2, 3.0)
92+
3. Django REST Framework (3.10, 3.11)
9393

9494
We **highly** recommend and only officially support the latest patch release of each Python, Django and REST Framework series.
9595

docs/getting-started.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ like the following:
5151

5252
## Requirements
5353

54-
1. Python (3.5, 3.6, 3.7)
55-
2. Django (1.11, 2.1, 2.2)
56-
3. Django REST Framework (3.10)
54+
1. Python (3.5, 3.6, 3.7, 3.8)
55+
2. Django (1.11, 2.1, 2.2, 3.0)
56+
3. Django REST Framework (3.10, 3.11)
5757

5858
We **highly** recommend and only officially support the latest patch release of each Python, Django and REST Framework series.
5959

docs/usage.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -682,11 +682,10 @@ Also we can override `related_field` in the url. Let's say we want the url to be
682682
dict to the class:
683683
```python
684684
field_name_mapping = {
685-
'line_items': 'order_items'
685+
'order_items': 'line_items'
686686
}
687687
```
688688

689-
690689
### Working with polymorphic resources
691690

692691
Polymorphic resources allow you to use specialized subclasses without requiring

example/api/resources/identity.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ def posts(self, request):
2323
posts = [{'id': 1, 'title': 'Test Blog Post'}]
2424

2525
data = {
26-
encoding.force_text('identities'): IdentitySerializer(identities, many=True).data,
27-
encoding.force_text('posts'): PostSerializer(posts, many=True).data,
26+
encoding.force_str('identities'): IdentitySerializer(identities, many=True).data,
27+
encoding.force_str('posts'): PostSerializer(posts, many=True).data,
2828
}
2929
return Response(utils.format_field_names(data, format_type='camelize'))
3030

example/migrations/0008_labresults.py

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 3.0.3 on 2020-02-06 10:24
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('example', '0007_artproject_description'),
11+
]
12+
13+
operations = [
14+
migrations.CreateModel(
15+
name='LabResults',
16+
fields=[
17+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18+
('date', models.DateField()),
19+
('measurements', models.TextField()),
20+
('research_project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lab_results', to='example.ResearchProject')),
21+
],
22+
),
23+
]

example/models.py

+7
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ class ResearchProject(Project):
151151
supervisor = models.CharField(max_length=30)
152152

153153

154+
class LabResults(models.Model):
155+
research_project = models.ForeignKey(
156+
ResearchProject, related_name='lab_results', on_delete=models.CASCADE)
157+
date = models.DateField()
158+
measurements = models.TextField()
159+
160+
154161
class Company(models.Model):
155162
name = models.CharField(max_length=100)
156163
current_project = models.ForeignKey(

example/serializers.py

+10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
Comment,
1616
Company,
1717
Entry,
18+
LabResults,
1819
Project,
1920
ProjectType,
2021
ResearchProject,
@@ -303,11 +304,20 @@ class Meta:
303304

304305

305306
class ResearchProjectSerializer(BaseProjectSerializer):
307+
# testing exclusive related field on inherited polymorphic model
308+
lab_results = relations.ResourceRelatedField(many=True, read_only=True)
309+
306310
class Meta:
307311
model = ResearchProject
308312
exclude = ('polymorphic_ctype',)
309313

310314

315+
class LabResultsSerializer(serializers.ModelSerializer):
316+
class Meta:
317+
model = LabResults
318+
fields = ('date', 'measurements')
319+
320+
311321
class ProjectSerializer(serializers.PolymorphicModelSerializer):
312322
included_serializers = {
313323
'project_type': ProjectTypeSerializer,

example/tests/test_format_keys.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_camelization(self):
2828
'data': [
2929
{
3030
'type': 'users',
31-
'id': encoding.force_text(user.pk),
31+
'id': encoding.force_str(user.pk),
3232
'attributes': {
3333
'firstName': user.first_name,
3434
'lastName': user.last_name,

example/tests/test_model_viewsets.py

+24-6
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def test_key_in_list_result(self):
3434
'data': [
3535
{
3636
'type': 'users',
37-
'id': encoding.force_text(user.pk),
37+
'id': encoding.force_str(user.pk),
3838
'attributes': {
3939
'first-name': user.first_name,
4040
'last-name': user.last_name,
@@ -72,7 +72,7 @@ def test_page_two_in_list_result(self):
7272
'data': [
7373
{
7474
'type': 'users',
75-
'id': encoding.force_text(user.pk),
75+
'id': encoding.force_str(user.pk),
7676
'attributes': {
7777
'first-name': user.first_name,
7878
'last-name': user.last_name,
@@ -112,7 +112,7 @@ def test_page_range_in_list_result(self):
112112
'data': [
113113
{
114114
'type': 'users',
115-
'id': encoding.force_text(users[0].pk),
115+
'id': encoding.force_str(users[0].pk),
116116
'attributes': {
117117
'first-name': users[0].first_name,
118118
'last-name': users[0].last_name,
@@ -121,7 +121,7 @@ def test_page_range_in_list_result(self):
121121
},
122122
{
123123
'type': 'users',
124-
'id': encoding.force_text(users[1].pk),
124+
'id': encoding.force_str(users[1].pk),
125125
'attributes': {
126126
'first-name': users[1].first_name,
127127
'last-name': users[1].last_name,
@@ -157,7 +157,7 @@ def test_key_in_detail_result(self):
157157
expected = {
158158
'data': {
159159
'type': 'users',
160-
'id': encoding.force_text(self.miles.pk),
160+
'id': encoding.force_str(self.miles.pk),
161161
'attributes': {
162162
'first-name': self.miles.first_name,
163163
'last-name': self.miles.last_name,
@@ -185,6 +185,24 @@ def test_patch_requires_id(self):
185185

186186
self.assertEqual(response.status_code, 400)
187187

188+
def test_patch_requires_correct_id(self):
189+
"""
190+
Verify that 'id' is the same then in url
191+
"""
192+
data = {
193+
'data': {
194+
'type': 'users',
195+
'id': self.miles.pk + 1,
196+
'attributes': {
197+
'first-name': 'DifferentName'
198+
}
199+
}
200+
}
201+
202+
response = self.client.patch(self.detail_url, data=data)
203+
204+
self.assertEqual(response.status_code, 409)
205+
188206
def test_key_in_post(self):
189207
"""
190208
Ensure a key is in the post.
@@ -193,7 +211,7 @@ def test_key_in_post(self):
193211
data = {
194212
'data': {
195213
'type': 'users',
196-
'id': encoding.force_text(self.miles.pk),
214+
'id': encoding.force_str(self.miles.pk),
197215
'attributes': {
198216
'first-name': self.miles.first_name,
199217
'last-name': self.miles.last_name,

example/tests/test_parsers.py

+17
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,20 @@ def test_parse_invalid_data(self):
5252

5353
with self.assertRaises(ParseError):
5454
parser.parse(stream, None, self.parser_context)
55+
56+
def test_parse_invalid_data_key(self):
57+
parser = JSONParser()
58+
59+
string = json.dumps({
60+
'data': [{
61+
'id': 123,
62+
'type': 'Blog',
63+
'attributes': {
64+
'json-value': {'JsonKey': 'JsonValue'}
65+
},
66+
}]
67+
})
68+
stream = BytesIO(string.encode('utf-8'))
69+
70+
with self.assertRaises(ParseError):
71+
parser.parse(stream, None, self.parser_context)

0 commit comments

Comments
 (0)