-
Notifications
You must be signed in to change notification settings - Fork 299
Avoid calling get_serializer during error handling #1051
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -377,8 +377,12 @@ def format_drf_errors(response, context, exc): | |
|
||
has_serializer = isinstance(context["view"], generics.GenericAPIView) | ||
if has_serializer: | ||
serializer = context["view"].get_serializer() | ||
fields = get_serializer_fields(serializer) or dict() | ||
try: | ||
serializer_class = context["view"].get_serializer_class() | ||
serializer = serializer_class() | ||
fields = get_serializer_fields(serializer) or dict() | ||
except Exception: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for raising this issue. I see that this could be a problem. I do not think it is a good idea to use Also catching a generic exception might end up in swallowing exceptions and it might just not be clear why a pointer is missing. So what I suggest instead is to catch the exceptions which are handled by DRF which are APIException, Http404 and PermissionDenied. Also your change will lead to a pointer always rendered as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That logic for creating the serializer instance along with its context is exactly what can fail and failed in many cases when I was transitioning my application to drf-jsonapi 4.3. Maybe there's a way to read these fields from the class without creating the instance? I do not agree about catching only DRF exceptions. The reason is that by calling Calling Calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calling Main issue is that the exception resp. error does not reference back to the serializer field itself which raised the error. If the field would be attached then we could simply use that to determine whether it is an attribute or relationship. So an approach could be to overwrite There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding field information in serializer subclass would indeed be a very clean solution, but it wouldn't properly attribute source for errors manually raised in views. I have code like this in a view that does use serializer later in the execution path:
It's true that serializer class does have a similar issue, but I think it's to a lesser degree. I think the probability of encountering these errors is lower than with serializer instance and its context. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree it is not ideal although in such a case it could at least be fixed within the client code by passing on the field before raising the exception. Anyway when thinking about it some more I am not sure Django REST Framework meant the So as initially stated it might make sense to catch handled exceptions (APIException etc.). Other 500 errors which could be caused when This is of course my opinion and I am very open to discuss this more. For this a PR is not ideal and it would best to open a discussion to get more people involved. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You make good points. I don't think this current situation is good, but I will go back to my app and try to adjust all I've tried that once already and it was very inconvenient when I needed to 404 on a combination of Feel free to close the PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. I guess you could create your own mixin which has a method you can overwrite in your view. This method will then be called before every action in the mixin. Closing this PR. Still feel free to open a discussion if there is a need. |
||
fields = [] | ||
relationship_fields = [ | ||
name for name, field in fields.items() if is_relationship_field(field) | ||
] | ||
|