-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Add validation for decorator order with @api_view #9821
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
base: main
Are you sure you want to change the base?
Add validation for decorator order with @api_view #9821
Conversation
Raise TypeError when API policy decorators (@permission_classes, @renderer_classes, etc.) are applied after @api_view instead of before it. Fixes encode#9596
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds validation to ensure API policy decorators are applied in the correct order relative to the @api_view decorator. The feature prevents a common mistake where developers apply policy decorators after @api_view, which silently fails to work as expected.
- Introduced
_check_decorator_order()helper function to detect incorrect decorator ordering - Added order validation to all nine API policy decorators
- Comprehensive test coverage for all affected decorators
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| rest_framework/decorators.py | Added _check_decorator_order() validation function and integrated it into all API policy decorators to raise TypeError when applied after @api_view |
| tests/test_decorators.py | Added nine test cases to verify that each API policy decorator raises TypeError when incorrectly applied after @api_view |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
rest_framework/decorators.py
Outdated
| f" @api_view(['GET'])\n" | ||
| f" @{decorator_name}(...)\n" |
Copilot
AI
Nov 6, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message shows the decorators in the wrong order. When decorators are stacked, they are applied bottom-to-top, so @api_view should be on top and @{decorator_name} should be below it. The example currently shows:
@api_view(['GET'])
@{decorator_name}(...)
def my_view(request):
...But this is the incorrect order being warned against. It should be:
@{decorator_name}(...)
@api_view(['GET'])
def my_view(request):
...| f" @api_view(['GET'])\n" | |
| f" @{decorator_name}(...)\n" | |
| f" @{decorator_name}(...)\n" | |
| f" @api_view(['GET'])\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The decorator needs to go below @api_view, just as the docs show—this way, DRF reads the attribute properly and permissions work.
Our tests confirm the documented order is correct; error is raised only if you swap them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will get back to you on saturday morning
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, Copilot is wrong here, but that might be a symptom that "applied before" is a bit ambiguous in this case. The docs are actually using the term "after":
These must come after (below) the
@api_viewdecorator
The docs refer to the order the decorators appear in the code: as we read top to bottom the order is swapped vs how they are applied by the code (bottom to top).
Understanding how decorators are applied by the language is important, but less experience people might not know it, and therefore won't understand the error message.
I'd rather make the language of the error message closer to what we have in the docs.
rest_framework/decorators.py
Outdated
| f" @api_view(['GET'])\n" | ||
| f" @{decorator_name}(...)\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, Copilot is wrong here, but that might be a symptom that "applied before" is a bit ambiguous in this case. The docs are actually using the term "after":
These must come after (below) the
@api_viewdecorator
The docs refer to the order the decorators appear in the code: as we read top to bottom the order is swapped vs how they are applied by the code (bottom to top).
Understanding how decorators are applied by the language is important, but less experience people might not know it, and therefore won't understand the error message.
I'd rather make the language of the error message closer to what we have in the docs.
rest_framework/decorators.py
Outdated
| if hasattr(func, 'cls') and issubclass(func.cls, APIView): | ||
| raise TypeError( | ||
| f"@{decorator_name} must be applied before @api_view. " | ||
| f"The correct order is:\n\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need the f prefix on lines where there is nothing to interpolate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@browniebroke Thanks for the review! I've updated the error message to address it.
The error message now:
@permission_classes must come after (below) the @api_view decorator. The correct order is:
@api_view(['GET']) @permission_classes(...) def my_view(request): ...
- Change 'must be applied before' to 'must come after (below) the' to match DRF docs language - Fix decorator order in example to show @api_view first, then policy decorator below - Remove unnecessary f-string prefixes from non-interpolated lines - Update all test assertions to match new error message wording Addresses feedback from @browniebroke in PR encode#9821
Fixes #9596
This PR adds validation to detect when API policy decorators (
@permission_classes,@renderer_classes, etc.) are applied in the wrong order with@api_view.Problem
When policy decorators are applied after
@api_view(i.e., placed above it in code), the policy settings are silently ignored. This happens because:@api_view, they set attributes on the already-created view function, not the original functionSolution
Added a
_check_decorator_order()helper that:APIView.as_view())TypeErrorwith the correct decorator orderTests
Added 9 comprehensive tests covering all policy decorators to ensure they properly validate ordering.