在django中,reverse 和 reverse_lazy 都可用于将别名转换为真实的url,但两者存在一个很重要的区别。
习惯地,大家都会使用reverse(),但在某些情况下,使用reverse()会导致如下的错误:
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.
导致如上错误的原因是,你尝试在项目还未加载url的情况下转换别名,这肯定是找不到对应的url的,因此会报错,但是这个错误提示真的比较难懂。
接下来看看导致错误发生的代码
class NewsDeleteView(LoginRequiredMixin, DeleteView):
model = News
success_url = reverse("news:list")
解决方法有两种
第一种.
class NewsDeleteView(LoginRequiredMixin, DeleteView):
model = News
success_url = **reverse_lazy**("news:list")
第二种.
class NewsDeleteView(LoginRequiredMixin, DeleteView):
model = News
def get_success_url(self, **kwargs):
return **reverse**("news:list")
好了,问题解决了,但是为什么这样可以解决问题呢,先来看看官网的解释:
reverse_lazy()
1.通常用于你转换别名的时机是在URLConf加载前。
2.通常用于CBV,而reverse()通常用于FBV
[django reverse_lazy¶](https://docs.djangoproject.com/en/3.0/ref/urlresolvers/)
看到官网的解释我很疑惑,什么是在加载前,项目启动,所有url不都应该会被加载进来吗。
后面看了CoffeeBasedLifeform 解释,明白了很多,将我的理解写在下面(其实就是英译汉=_=)
1.如果直接定义success_url
success_url = **reverse_lazy**("news:list")
success_url 相当于类属性,在类加载的时候,属性就会被赋值,也就是会对别名进行解析,这里我理解的是django中url的加载在所有类加载后,因此找不到对应的url。
reverse_lazy()里实际也是调用了reverse(),只是延迟这个过程至该url被访问时。
2.如果选择重写get_success_url,而不是直接定义success_url
def get_success_url(self, **kwargs):
return **reverse**("news:list")
因为函数是在被调用的时候才会执行,所以效果是一样的