Django 基于类的视图上的 success_url 的反向抱怨循环导入

Posted

技术标签:

【中文标题】Django 基于类的视图上的 success_url 的反向抱怨循环导入【英文标题】:reverse for success_url on Django Class Based View complain about circular import 【发布时间】:2015-09-25 08:30:35 【问题描述】:

当使用基于方法的视图时,使用reverse 重定向并没有抱怨这一点,仍然可以找到根 url conf。但是,在基于类的视图中,它抱怨:

ImproperlyConfigured at /blog/new-post/

The included urlconf 'blog.urls' does not appear to have any
patterns in it. If you see valid patterns in the file then the
issue is probably caused by a circular import.

我的班级是这样定义的:

class BlogCreateView(generic.CreateView):
    form_class = Blog
    template_name = 'blog/new-post.html'
    success_url = reverse('blog:list-post')

如何在基于类的视图中正确地将reverse 用于success_url?谢谢。

PS:我很感兴趣为什么它需要在这个错误之后重启runserver(不像TemplateDoesNotExists这样的错误,不需要重启runserver

【问题讨论】:

【参考方案1】:

在您的方法中使用reverse 是可行的,因为在运行视图时会调用reverse

def my_view(request):
    url = reverse('blog:list-post')
    ...

如果您覆盖get_success_url,那么您仍然可以使用reverse,因为在运行视图时get_success_url 会调用reverse

class BlogCreateView(generic.CreateView):
    ...
    def get_success_url(self):
        return reverse('blog:list-post')

但是,您不能将reversesuccess_url 一起使用,因为在导入模块时会调用reverse,在加载url 之前。

覆盖get_success_url 是一种选择,但最简单的解决方法是使用reverse_lazy 而不是反向。

from django.urls import reverse_lazy
# from django.core.urlresolvers import reverse_lazy  # old import for Django < 1.10

class BlogCreateView(generic.CreateView):
    ...
    success_url = reverse_lazy('blog:list-post')

回答你关于重新启动runserver的最后一个问题,ImproperlyConfigured 错误与TemplateDoesNotExists 不同,因为它发生在加载 Django 应用程序时。

【讨论】:

reverse_lazy()Django 1.9 配合得很好,我试过了,reverse() 会抛出异常。【参考方案2】:

尝试在您的 CBV 中使用 reverse_lazy 而不是 reverse。它是reverse 的懒惰评估版本。在需要该值之前它不会执行。

from django.core.urlresolvers import reverse_lazy

class BlogCreateView(generic.CreateView):
    form_class = Blog
    template_name = 'blog/new-post.html'
    success_url = reverse_lazy('blog:list-post')

【讨论】:

以上是关于Django 基于类的视图上的 success_url 的反向抱怨循环导入的主要内容,如果未能解决你的问题,请参考以下文章

基于 Django 类的通用视图和 ModelForms

如何在 django 中使用基于类的视图

基于 Django 类的视图和通用视图详细信息使用

Django:基于类的视图无法呈现清晰的表单

Django 基于类的视图:覆盖表单名称

Django:在基于类的视图中包含媒体(css/js)