Skip to content

Allow get_serializer_class to be overwritten for related urls without defining serializer_class fallback #904

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 5 commits into from
Apr 16, 2021
Merged

Allow get_serializer_class to be overwritten for related urls without defining serializer_class fallback #904

merged 5 commits into from
Apr 16, 2021

Conversation

SafaAlfulaij
Copy link
Contributor

@SafaAlfulaij SafaAlfulaij commented Apr 3, 2021

Description of the Change

This fixes the fact that getting related view's serializer gets it from the super class, rather than the current class.
Bug can be reproduced by using:

    url(
        r"^entries/(?P<pk>[^/.]+)/(?P<related_field>\w+)/$",
        EntryViewSet.as_view({"get": "retrieve_related"}),
        name="entry-related",
    ),

instead of:

    url(
        r"entries/(?P<entry_pk>[^/.]+)/comments$",
        CommentViewSet.as_view({"get": "list"}),
        name="entry-comments",
    ),

Navigating to entries/1/comments/ now will result in an error stating that no get_serializer_class has been defined, even though it exists.

Checklist

  • PR only contains one change (considered splitting up PR)
  • unit-test added updated
  • documentation updated
  • CHANGELOG.md updated (only for user relevant changes)
  • author name in AUTHORS

@codecov
Copy link

codecov bot commented Apr 3, 2021

Codecov Report

Merging #904 (9275ae1) into master (51daed1) will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #904   +/-   ##
=======================================
  Coverage   97.67%   97.67%           
=======================================
  Files          58       58           
  Lines        3101     3101           
=======================================
  Hits         3029     3029           
  Misses         72       72           
Impacted Files Coverage Δ
tests/test_views.py 100.00% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 51daed1...9275ae1. Read the comment docs.

@@ -27,6 +27,7 @@
"related_link_view_name",
"related_link_lookup_field",
"related_link_url_kwarg",
"related_link_related_name",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes the fact that getting related view's serializer gets it from the super class, rather than the current class.

The PR description states that this PR is addressing issue that related view does not properly get parent serializer class (it seems to be another clean up after #860). I guess this change addresses this issue.

So at a quick glance for me it is not quite clear why introducing of a new links parameters is needed to fix this issue. Can you elaborate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explanation 2:
We need to add this parameter to specify the the related link for hyperlink fields (which can, most of the time, have a different related name).
For example in the example serializers, the field_name is comments_hyperlinked:

comments_hyperlinked = relations.HyperlinkedRelatedField(
        related_link_view_name="entry-comments",

And the related view is:

    url(
        r"entries/(?P<entry_pk>[^/.]+)/comments$",
        CommentViewSet.as_view({"get": "list"}),
        name="entry-comments",
    ),

So comments_hyperlinked relates to comments.
But here, we get the field_names, which will create such a url: /entries/1/comments_hyperlinked, which isn't really what we want.

@@ -392,6 +393,9 @@ def _find_related_view(self, view_endpoints, related_serializer, parent_view):

def _field_is_one_or_many(self, field, view):
serializer = view.get_serializer()
if field not in serializer.fields:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explanation 3:
This was found out by testing, and I think it's because of dynamic fields.
For example, here we remove the "featured" field when the serializer is initialized, but it exists in the serializer class itself, and therefore being checked.

@sliverc
Copy link
Member

sliverc commented Apr 16, 2021

Thanks for your explanation. When reading through it seems that you are trying to address 3 different issues in one PR (each explanation 1).

  1. the actual issue of the super class
  2. support of hyperlinked related field
  3. another bug

To ensure that each single issue is properly tested and better way of reviewing could you split up this PR? Out of urgency point number 1 would be high priority as it is a regression (I will see whether I will get to that as well at some point later on if you won't get to it before me).

@sliverc sliverc changed the title Get current serializer class Allow get_serializer_class to be overwritten for related urls without defining serializer_class fallback Apr 16, 2021
@sliverc
Copy link
Member

sliverc commented Apr 16, 2021

I added a test (resp. updated as before the test was invalid) and added changelog entry for the parent super class call issue.

Merging this. For the other two issue feel free to either create another PR or issue. Thanks for your testing effort - really appreciated that you found those hidden away bugs in the latest version.

@sliverc sliverc merged commit 450aa5c into django-json-api:master Apr 16, 2021
@SafaAlfulaij
Copy link
Contributor Author

I checked the issue with openapi schema generation, and it seems to be with related views as well.
I don't know now how to reproduce it, or if it's even valid.
And as for the hyperlinked related field, I'm not using those a lot, and as they are also related to related views, which I don't prefer, I'm not confident enough to work on it.

I'll open to issues about those problems, and let experts handle them :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants