reverse_lazy-success_url重定向

时间:2015-06-06 09:16:30

标签: django lazy-evaluation django-urls

TLDR:我希望能够在创建惰性对象之后在slug reverse_lazy('view', kwargs={'slug':'my_page'})中提供reverse_lazy('view').apply(kwargs={'slug':'my_page'})

我有以下url模式,其中包含一个用于标识页面模型实例的slug:

url(r'^(?P<slug>'+settings.SLUG_PATTERN+')/$', views.MyView.as_view(), name='view'),

我有另一个用于编辑页面的视图:

url(r'^(?P<slug>'+settings.SLUG_PATTERN+')/_edit/$',
    views.MyEditView.as_view(success_url=reverse_lazy('view')), name='edit'),

请注意添加success_url,以便在我提交包含新内容的表单时,我会重定向到现在编辑的页面。如果我更改了view网址格式,我不必担心更新我的edit网址的重定向。

在验证并保存表单后,该视图将获取要在HttpResponseRedirect中使用的成功URL。但是,只有名称“视图”不足以识别URL。我还需要知道存储在我的页面模型的slug字段中的slug名称。

类似的问题在这里:success_url in UpdateView, based on passed value

答案建议为每个视图编写自定义get_success_url,但必须有更好的方法。

在django的edit.py的通用视图中,有以下内容:

url = self.success_url.format(**self.object.__dict__)

如果将success_url作为硬编码网址提供,但使用诸如'{slug}/'之类的slug标识符,则会将其替换为模型中的slug字段。这与我想要的非常接近,但我不想硬编码我的URL。这让我想到了我的问题:

如何将参数传递给reverse_lazy对象?我会在我的基本视图get_success_url中使用self.object.__dict__并且它只是工作无处不在。

此外,如果我的slug字符串存储在单独的Slug模型中,我可能希望成功URL为'{slug.name}/'。通过上述方法,我可以提供URL参数和模型属性之间的映射:

redirect_model_mapping = {'slug': '{slug.name}'}
...
def get_success_url(self):
    url = self.success_url
    if is_a_lazy_redirect(url):
        url = url.somehow_apply_parameters(redirect_model_mapping)
    return url.format(**self.object.__dict__)

我希望somehow_apply_parameters等同于最初调用reverse_lazy('blog:view', kwargs=redirect_model_mapping)。但是我不认为这应该在urls.py中,因为它不应该知道映射。

1 个答案:

答案 0 :(得分:1)

这是一个黑客,但做我想要的......

class MyView(FormMixin, ...):

    #this is actually set on child classes
    redirect_model_mapping = {'slug':'{slug.name}'}

    def get_success_url(self):
        url = self.success_url
        if url is not None:
            if hasattr(self.success_url, '_proxy____kw'):
                url_parameters = dict((k, v.format(**self.object.__dict__)) for k, v in six.iteritems(self.redirect_model_mapping))
                url._proxy____kw = {'kwargs': url_parameters}
                url = force_text(url)
            else:
                url = url.format(**self.object.__dict__)
        else:
            raise ImproperlyConfigured("No URL to redirect to.")
        return url

它取代了通常传递给kwards的{​​{1}}参数,但实际上它具有所需的值。由于reverse_lazy也需要字符串匹配正则表达式,我必须首先在url参数和模型中的值之间进行映射。

我非常喜欢不需要写reverse_lazy的方法。