Skip to content

Fixed invalid relationship pointer in error object #1070

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Note that in line with [Django REST framework policy](https://www.django-rest-framework.org/topics/release-notes/),
any parts of the framework not mentioned in the documentation should generally be considered private API, and may be subject to change.

## [Unreleased]

### Fixed

* Fixed invalid relationship pointer in error objects when field naming formatting is used.

## [5.0.0] - 2022-01-03

This release is not backwards compatible. For easy migration best upgrade first to version
Expand Down
56 changes: 54 additions & 2 deletions example/tests/__snapshots__/test_errors.ambr
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,66 @@
]),
})
# ---
# name: test_relationship_errors_has_correct_pointers
# name: test_relationship_errors_has_correct_pointers_with_camelize
dict({
'errors': list([
dict({
'code': 'incorrect_type',
'detail': 'Incorrect type. Expected resource identifier object, received str.',
'source': dict({
'pointer': '/data/relationships/author',
'pointer': '/data/relationships/authors',
}),
'status': '400',
}),
dict({
'code': 'incorrect_type',
'detail': 'Incorrect type. Expected resource identifier object, received str.',
'source': dict({
'pointer': '/data/relationships/mainAuthor',
}),
'status': '400',
}),
]),
})
# ---
# name: test_relationship_errors_has_correct_pointers_with_dasherize
dict({
'errors': list([
dict({
'code': 'incorrect_type',
'detail': 'Incorrect type. Expected resource identifier object, received str.',
'source': dict({
'pointer': '/data/relationships/authors',
}),
'status': '400',
}),
dict({
'code': 'incorrect_type',
'detail': 'Incorrect type. Expected resource identifier object, received str.',
'source': dict({
'pointer': '/data/relationships/main-author',
}),
'status': '400',
}),
]),
})
# ---
# name: test_relationship_errors_has_correct_pointers_with_no_formatting
dict({
'errors': list([
dict({
'code': 'incorrect_type',
'detail': 'Incorrect type. Expected resource identifier object, received str.',
'source': dict({
'pointer': '/data/relationships/authors',
}),
'status': '400',
}),
dict({
'code': 'incorrect_type',
'detail': 'Incorrect type. Expected resource identifier object, received str.',
'source': dict({
'pointer': '/data/relationships/main_author',
}),
'status': '400',
}),
Expand Down
56 changes: 53 additions & 3 deletions example/tests/test_errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ class EntrySerializer(serializers.Serializer):
comment = CommentSerializer(required=False)
headline = serializers.CharField(allow_null=True, required=True)
body_text = serializers.CharField()
author = serializers.ResourceRelatedField(
main_author = serializers.ResourceRelatedField(
queryset=Author.objects.all(), required=False
)
authors = serializers.ResourceRelatedField(
queryset=Author.objects.all(), required=False, many=True
)

def validate(self, attrs):
body_text = attrs["body_text"]
Expand Down Expand Up @@ -195,7 +198,31 @@ def test_many_third_level_dict_errors(client, some_blog, snapshot):
assert snapshot == perform_error_test(client, data)


def test_relationship_errors_has_correct_pointers(client, some_blog, snapshot):
def test_relationship_errors_has_correct_pointers_with_camelize(
client, some_blog, snapshot
):
data = {
"data": {
"type": "entries",
"attributes": {
"blog": some_blog.pk,
"bodyText": "body_text",
"headline": "headline",
},
"relationships": {
"mainAuthor": {"data": {"id": "INVALID_ID", "type": "authors"}},
"authors": {"data": [{"id": "INVALID_ID", "type": "authors"}]},
},
}
}

assert snapshot == perform_error_test(client, data)


@override_settings(JSON_API_FORMAT_FIELD_NAMES="dasherize")
def test_relationship_errors_has_correct_pointers_with_dasherize(
client, some_blog, snapshot
):
data = {
"data": {
"type": "entries",
Expand All @@ -205,7 +232,30 @@ def test_relationship_errors_has_correct_pointers(client, some_blog, snapshot):
"headline": "headline",
},
"relationships": {
"author": {"data": {"id": "INVALID_ID", "type": "authors"}}
"main-author": {"data": {"id": "INVALID_ID", "type": "authors"}},
"authors": {"data": [{"id": "INVALID_ID", "type": "authors"}]},
},
}
}

assert snapshot == perform_error_test(client, data)


@override_settings(JSON_API_FORMAT_FIELD_NAMES=None)
def test_relationship_errors_has_correct_pointers_with_no_formatting(
client, some_blog, snapshot
):
data = {
"data": {
"type": "entries",
"attributes": {
"blog": some_blog.pk,
"body_text": "body_text",
"headline": "headline",
},
"relationships": {
"main_author": {"data": {"id": "INVALID_ID", "type": "authors"}},
"authors": {"data": [{"id": "INVALID_ID", "type": "authors"}]},
},
}
}
Expand Down
4 changes: 3 additions & 1 deletion rest_framework_json_api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,9 @@ def format_drf_errors(response, context, exc):
serializer = context["view"].get_serializer()
fields = get_serializer_fields(serializer) or dict()
relationship_fields = [
name for name, field in fields.items() if is_relationship_field(field)
format_field_name(name)
for name, field in fields.items()
if is_relationship_field(field)
]

for field, error in response.data.items():
Expand Down