django reverse vs reverse_lazy

这个世界上有很多好人。如果你找不到,就让自己成为一个。

  上一篇里分析了django url 里 name、namespace、app_name 的用途,但是上一篇里也提到了反向解析用在了 template 里,而在 python 代码里没有过多的体现,今天看到 CHENG’S BLOG 博客,容易理解,遂转载之。

现在定义了一个 url

urlpatterns = [

url(r'^$', views.IndexView.as_view(), name='index'),
]

当然了,如果我想在 template 里使用的话可以如下

<h1> {% url 'index' %} </h1>

现在后端有下面这段代码

from django.core.urlresolvers import reverse

class UserProfileView(FormView):
template_name = 'profile.html'
form_class = UserProfileForm
success_url = reverse('index')

如果运行,会报如下错

django.core.exceptions.ImproperlyConfigured: The included urlconf 'config.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.

根据 CHENG’S BLOG 里的介绍,有两种方式解决这个问题。
方法一:

from django.core.urlresolvers import reverse_lazy 

class UserProfileView(FormView):
template_name = 'profile.html'
form_class = UserProfileForm
success_url = reverse_lazy('index') # use reverse_lazy instead of reverse

方法二:

from django.core.urlresolvers import reverse

class UserProfileView(FormView):
template_name = 'profile.html'
form_class = UserProfileForm

def get_success_url(self): # override this function if you want to use reverse

return reverse('index')

单单从代码上看,reverse_lasy要方便很多。根据 Django’s document 上的描述,reverse_lazy当项目里的URLConf未加载时用来取代 reversereverse_lasy可以用在以下几个场景

  • 在 class-based view 中用 reversed url. (上述方法一)
  • 装饰器中使用 reversed url (例如装饰器 django.contrib.auth.decorators.permission_required() 中 login_url 参数).
  • 函数参数的默认值中的 reversed url

最后看了下两者的源码,看的一知半解,但是如下源码中

# reverse
def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None):
......

# reverse_lazy
reverse_lazy = lazy(reverse, six.text_type)

可以看到reverse_lasyreverse的一层封装,这样我就可以用reverse_lazy可以用在任何reverse的场景里,而且不用担心出错,所以 have a try~

  

参考阅读