Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit bbeb13a

Browse files
bashlysssliverc
andauthored
Support many related field (#1065)
Co-authored-by: Oliver Sauder <os@esite.ch>
1 parent f9eb277 commit bbeb13a

File tree

5 files changed

+65
-9
lines changed

5 files changed

+65
-9
lines changed

‎AUTHORS‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Adam Wróbel <https://adamwrobel.com>
22
Adam Ziolkowski <adam@adsized.com>
33
Alan Crosswell <alan@columbia.edu>
44
Anton Shutik <shutikanton@gmail.com>
5+
Ashley Loewen <github@ashleycodes.tech>
56
Asif Saif Uddin <auvipy@gmail.com>
67
Beni Keller <beni@matraxi.ch>
78
Boris Pleshakov <koordinator.kun@gmail.com>

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ any parts of the framework not mentioned in the documentation should generally b
1313
### Fixed
1414

1515
* Fixed invalid relationship pointer in error objects when field naming formatting is used.
16+
* Properly resolved related resource type when nested source field is defined.
1617

1718
## [5.0.0] - 2022年01月03日
1819

‎rest_framework_json_api/utils.py‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,15 @@ def get_related_resource_type(relation):
211211
relation_model = relation.model
212212
elif hasattr(relation, "get_queryset") and relation.get_queryset() is not None:
213213
relation_model = relation.get_queryset().model
214-
elif (
215-
getattr(relation, "many", False)
216-
andhasattr(relation.child, "Meta")
217-
andhasattr(relation.child.Meta, "model")
218-
):
219-
# For ManyToMany relationships, get the model from the child
220-
# serializer of the list serializer
221-
relation_model=relation.child.Meta.model
222-
else:
214+
elif hasattr(relation, "child_relation"):
215+
# For ManyRelatedField relationships, get the model from the child relationship
216+
try:
217+
returnget_related_resource_type(relation.child_relation)
218+
exceptAttributeError:
219+
# Some read only relationships fail to get it directly, fall through to
220+
# get via the parent
221+
pass
222+
ifnotrelation_model:
223223
parent_serializer = relation.parent
224224
parent_model = None
225225
if isinstance(parent_serializer, PolymorphicModelSerializer):

‎tests/models.py‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,14 @@ class ForeignKeySource(DJAModel):
3939
target = models.ForeignKey(
4040
ForeignKeyTarget, related_name="sources", on_delete=models.CASCADE
4141
)
42+
43+
44+
class NestedRelatedSource(DJAModel):
45+
m2m_source = models.ManyToManyField(ManyToManySource, related_name="nested_source")
46+
fk_source = models.ForeignKey(
47+
ForeignKeySource, related_name="nested_source", on_delete=models.CASCADE
48+
)
49+
m2m_target = models.ManyToManyField(ManyToManySource, related_name="nested_source")
50+
fk_target = models.ForeignKey(
51+
ForeignKeySource, related_name="nested_source", on_delete=models.CASCADE
52+
)

‎tests/test_utils.py‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
ForeignKeyTarget,
2626
ManyToManySource,
2727
ManyToManyTarget,
28+
NestedRelatedSource,
2829
)
2930
from tests.serializers import BasicModelSerializer
3031

@@ -313,6 +314,48 @@ class Meta:
313314
assert get_related_resource_type(field) == output
314315

315316

317+
@pytest.mark.parametrize(
318+
"field,output,related_field_kwargs",
319+
[
320+
(
321+
"m2m_source.targets",
322+
"ManyToManyTarget",
323+
{"many": True, "queryset": ManyToManyTarget.objects.all()},
324+
),
325+
(
326+
"m2m_target.sources.",
327+
"ManyToManySource",
328+
{"many": True, "queryset": ManyToManySource.objects.all()},
329+
),
330+
(
331+
"fk_source.target",
332+
"ForeignKeyTarget",
333+
{"many": True, "queryset": ForeignKeyTarget.objects.all()},
334+
),
335+
(
336+
"fk_target.source",
337+
"ForeignKeySource",
338+
{"many": True, "queryset": ForeignKeySource.objects.all()},
339+
),
340+
],
341+
)
342+
def test_get_related_resource_type_from_nested_source(
343+
db, field, output, related_field_kwargs
344+
):
345+
class RelatedResourceTypeSerializer(serializers.ModelSerializer):
346+
relation = serializers.ResourceRelatedField(
347+
source=field, **related_field_kwargs
348+
)
349+
350+
class Meta:
351+
model = NestedRelatedSource
352+
fields = ("relation",)
353+
354+
serializer = RelatedResourceTypeSerializer()
355+
field = serializer.fields["relation"]
356+
assert get_related_resource_type(field) == output
357+
358+
316359
@pytest.mark.parametrize(
317360
"related_field_kwargs,output",
318361
[

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /