Django - 获取反转url所需的参数名称

时间:2015-10-07 21:12:55

标签: python django django-urls

背景

假设我有一个带有参数的url模式,可以将我链接到django中的视图:

url(
    r'^things/(?P<thing_name>\w+)/features/(?P<feature_name>\w+)$',
    views.thingFeature,
    name='thing_feature'
),

让我说我有thingfeature

thing = Thing.objects.get(.....)
feature = thing.feature_set.first()

t_name = thing.name
f_name = feature.name

现在Django给了我很棒的能力来获取一个网址,该网址将我带到一个专门针对特定事物的特定功能的页面。我可以这样做:

from django.core.urlresolvers import reverse
url = reverse('thing_feature', thing_name=t_name, feature_name=f_name)
# url == '/things/thing2/features/left-arm'

问题

现在我偶然发现了一个需要专门解决的问题。我不是在寻找解决方法 - 我正在寻求解决以下问题:

鉴于网址为name,如何获取撤消该网址所需的kwarg参数名称列表?

我正在寻找函数get_kwarg_names_for_url。它的表现如下:

url_kwarg_names = get_kwarg_names_for_url('thing_feature')
# url_kwarg_names == ['thing_name', 'feature_name']

url_kwarg_names现在是我需要提供给Django reverse函数的每个关键字的列表,以便撤消名为"thing_feature"的网址。

感谢任何帮助!

解决方案

根据knbk的回答,我能够提出以下解决方案:

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]

2 个答案:

答案 0 :(得分:2)

我会以公平的警告开始:使用公共API是不可能的。最重要的是,我正在积极地为1.10重写URL调度程序,所以这个方法很可能会在那个时候中断。

首先,您需要获得正确的RegexURLResolver。如果视图不在命名空间中,您可以使用reverse_dict获取可能性列表,并提取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

由于视图名称可以包含多个具有不同kwargs的模式(尽管您希望为了自己的理智避免这种情况),但这将返回每组可能的kwargs的列表。通常,不同的集合将是一侧所需的kwargs,另一侧需要+可选的kwargs。

我还没有对此进行过测试,但是如果它不起作用,你可以在resolver.reverse_dict中挖掘一下,找出确切的细节。它的设计并没有考虑到可用性。

答案 1 :(得分:0)

您应该可以使用resolve()

执行此操作

来自文档:

  

然后可以询问ResolverMatch对象以提供有关与URL匹配的URL模式的信息:

     

func, args, kwargs = resolve('/some/path/')

特定于您的示例代码:

url = reverse('thing_feature')
func, args, kwargs = resolve(url)
# args == ['thing_name', 'feature_name']