django reverse 和 reverse_lazy 的 区别

在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")
因为函数是在被调用的时候才会执行,所以效果是一样的

你可能感兴趣的:(django)