Skip to content
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

Use old url_name behavior in route decorators #5915

Merged
merged 2 commits into from Apr 4, 2018
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/topics/release-notes.md
Expand Up @@ -52,6 +52,8 @@ You can determine your currently installed version using `pip show`:
* Merged `list_route` and `detail_route` into a single `action` decorator.
* Get all extra actions on a `ViewSet` with `.get_extra_actions()`.
* Extra actions now set the `url_name` and `url_path` on the decorated method.
* `url_name` is now based on the function name, instead of the `url_path`,
as the path is not always suitable (e.g., capturing arguments in the path).
* Enable action url reversing through `.reverse_action()` method (added in 3.7.4)
* Example reverse call: `self.reverse_action(self.custom_action.url_name)`
* Add `detail` initkwarg to indicate if the current action is operating on a
Expand All @@ -62,6 +64,8 @@ You can determine your currently installed version using `pip show`:
* Deprecated `list_route` & `detail_route` in favor of `action` decorator with `detail` boolean.
* Deprecated dynamic list/detail route variants in favor of `DynamicRoute` with `detail` boolean.
* Refactored the router's dynamic route generation.
* `list_route` and `detail_route` maintain the old behavior of `url_name`,
basing it on the `url_path` instead of the function name.

## 3.7.x series

Expand Down
20 changes: 16 additions & 4 deletions rest_framework/decorators.py
Expand Up @@ -147,8 +147,8 @@ def action(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
def decorator(func):
func.bind_to_methods = methods
func.detail = detail
func.url_path = url_path or func.__name__
func.url_name = url_name or func.__name__.replace('_', '-')
func.url_path = url_path if url_path else func.__name__
func.url_name = url_name if url_name else func.__name__.replace('_', '-')
func.kwargs = kwargs
return func
return decorator
Expand All @@ -163,7 +163,13 @@ def detail_route(methods=None, **kwargs):
"`action`, which accepts a `detail` bool. Use `@action(detail=True)` instead.",
PendingDeprecationWarning, stacklevel=2
)
return action(methods, detail=True, **kwargs)

def decorator(func):
func = action(methods, detail=True, **kwargs)(func)
if 'url_name' not in kwargs:
func.url_name = func.url_path.replace('_', '-')
return func
return decorator


def list_route(methods=None, **kwargs):
Expand All @@ -175,4 +181,10 @@ def list_route(methods=None, **kwargs):
"`action`, which accepts a `detail` bool. Use `@action(detail=False)` instead.",
PendingDeprecationWarning, stacklevel=2
)
return action(methods, detail=False, **kwargs)

def decorator(func):
func = action(methods, detail=False, **kwargs)(func)
if 'url_name' not in kwargs:
func.url_name = func.url_path.replace('_', '-')
return func
return decorator
10 changes: 10 additions & 0 deletions tests/test_decorators.py
Expand Up @@ -215,3 +215,13 @@ def view(request):
"3.10 in favor of `action`, which accepts a `detail` bool. Use "
"`@action(detail=False)` instead."
)

def test_route_url_name_from_path(self):
# pre-3.8 behavior was to base the `url_name` off of the `url_path`
with pytest.warns(PendingDeprecationWarning):
@list_route(url_path='foo_bar')
def view(request):
pass

assert view.url_path == 'foo_bar'
assert view.url_name == 'foo-bar'