Let's say I have a url pattern with parameters that will link me to a view in django:
url(
r'^things/(?P<thing_name>\w+)/features/(?P<feature_name>\w+)$',
views.thingFeature,
name='thing_feature'
),
And lets say I have a thing
and a feature
:
thing = Thing.objects.get(.....)
feature = thing.feature_set.first()
t_name = thing.name
f_name = feature.name
Now Django gives me the awesome ability to get a url that brings me to a page dedicated to a specific feature of a specific thing. I can do that like so:
from django.core.urlresolvers import reverse
url = reverse('thing_feature', thing_name=t_name, feature_name=f_name)
# url == '/things/thing2/features/left-arm'
Now I've stumbled into a situation that I need to specifically address. I'm not looking for a workaround - I'm looking to solve the following problem:
Given a url's name
, how do I get the list of kwarg
argument names needed to reverse that url?
I am looking for the function get_kwarg_names_for_url
. It behaves like so:
url_kwarg_names = get_kwarg_names_for_url('thing_feature')
# url_kwarg_names == ['thing_name', 'feature_name']
url_kwarg_names
is now the list of every keyword I need to supply to Django's reverse
function in order to reverse the url named "thing_feature"
.
Any help is appreciated!
Based on knbk's answer I was able to come up with the following solution:
def get_kwarg_names_for_url(url_name):
resolver = get_resolver(get_urlconf())
reverse_data = resolver.reverse_dict[url_name]
pattern_list = reverse_data[0]
'''
Need to specify the 1st pattern because url regexes can
potentially have multiple kwarg arrangments - this function does
not take this possibility into account.
'''
first_pattern = pattern_list[0]
'''
`first_pattern` is now of the form `(url_string, kwarg_list)` -
all we are interested in is the 2nd value.
'''
return first_pattern[1]
I'll start with a fair warning: this isn't possible using the public API. On top of that, I'm actively working to rewrite the URL dispatcher for 1.10, so this method will most likely break by that time.
First, you need to get the right RegexURLResolver
. If the view is not in a namespace, you can use the reverse_dict
to get a list of possibilities, and extract the kwargs:
def get_kwargs(view_name):
resolver = urlresolvers.get_resolver()
patterns = resolver.reverse_dict.getlist(view_name)
kwargs = []
for possibility, pattern, defaults in patterns:
for result, params in possibility:
kwargs.append(params)
return kwargs
Since a view name can have multiple patterns with different kwargs (though you'd want to avoid that for your own sanity), this will return a list of each set of possible kwargs. Usually the different sets would be the required kwargs on one side and required + optional kwargs on the other side.
I haven't tested this, but if it doesn't work you can dig around in resolver.reverse_dict
for a bit to find out the exact specifics. It wasn't exactly designed with usability in mind.
You should be able to do this with a resolve()
From the Docs:
A ResolverMatch object can then be interrogated to provide information about the URL pattern that matches a URL:
func, args, kwargs = resolve('/some/path/')
Specific to your example code:
url = reverse('thing_feature')
func, args, kwargs = resolve(url)
# args == ['thing_name', 'feature_name']
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With