我知道在FBV中可以使用reverse()
,而在CBV中可以使用reverse_lazy()
。 我们必须在CBV中使用reverse_lazy()
,因为在导入文件时未加载URL(参考:Reverse_lazy and URL Loading?)
我不明白的是:
当我们从FBV调用reverse
时,URL如何加载? 因为在Django应用程序的urls.py
顶部导入视图时,urlpatterns
列表尚未被评估。 reverse()
如何适用于FBV,但不适用于CBV?
我知道在FBV中可以使用reverse()
,而在CBV中可以使用reverse_lazy()
。 我们必须在CBV中使用reverse_lazy()
,因为在导入文件时未加载URL(参考:Reverse_lazy and URL Loading?)
我不明白的是:
当我们从FBV调用reverse
时,URL如何加载? 因为在Django应用程序的urls.py
顶部导入视图时,urlpatterns
列表尚未被评估。 reverse()
如何适用于FBV,但不适用于CBV?
考虑以下两种定义success_url的方式。第一种已经被注释掉了,第二种是函数:
class NewJobCBV(LoginRequiredMixin, CreateView):
template_name = 'company/job.html'
form_class = newJobForm
# success_url = reverse_lazy('newJob')
def get_success_url(self, **kwargs):
return reverse("newJob")
@CoffeeBasedLifeform :你说得对,类属性在导入时就会被评估,在阅读了你的回答后我进行了检查。因此,
success_url
,我们必须使用reverse_lazy()
。reverse()
。现在一切都很清楚了。
谢谢,CoffeeBasedLifeform :)
#importme.py
def a():
print("FUNCTION HELLO")
class B():
print("CLASS HELLO")
>>> import importme
>>> CLASS HELLO
编辑: 原因: 类的创建过程涉及执行类的主体。
类主体执行为
exec(body, globals(), namespace)
。[...] 一旦通过执行类主体填充了类名称空间,就通过调用metaclass(name, bases, namespace, **kwds)
创建类对象。
原始回答文本。您可以忽略它 - 我只是保留它,因为mirek的评论是对它的直接回应:
导入时计算类属性。关于何时以及如何发生,这取决于Python的导入系统的深度。
Reverse_lazy是反向URL解析器的一种惰性实现,顾名思义。与传统的反向函数不同,只有在需要值时,reverse_lazy才会执行。
它很有用,因为在处理可能不会立即知道的URL时可以防止反向未找到(Reverse Not Found)异常。
为什么我们需要它? 因为类属性在导入时被计算,在那个时候 Reverse方法将返回'Reverse Not Found'。 稍后需要时,在其执行时,所有必要的代码片段已经被执行,以给出有效的URL。
理解它们之间的区别:
reverse() 返回一个 字符串
,而 reverse_lazy() 返回一个 <对象>
区别:
reverse
和reverse_lazy
函数的目标相同:根据输入(如命名URL)生成URL。
reverse
用于在调用函数或方法时生成URL。让我们举个例子:
一个函数:
#views.py
from django.urls import reverse
def my_view(request):
url = reverse('url-name', args=[1])
# do something with the URL
reverse
函数在调用my_view
函数时被评估:它生成一个命名为url-name
的URL,并将整数1作为参数传递。
一种方法:
#models.py
from django.db import models
class Post(models.Model):
#rest of the class
def get_absolute_url(self):
return reverse("blog:post_detail", kwargs={"pk": self.pk})
再次强调,reverse
函数在调用get_absolute_url
方法时被评估。
在这两种情况下重要的是,在调用reverse
函数时,它已经具有URLConf
的信息,因此可以轻松找到url模式。
reverse_lazy
也用于生成URL,但它推迟了评估的时刻,直到实际需要为止。这就是它是reverse
的惰性评估版本的原因。你可能会想知道为什么...
在代码中有时需要使用URL反转,但不确定URLConf
是否已加载。
如果在URLConf
尚未加载时使用reverse
,则会出现错误。
这个错误是因为反向解析需要知道项目中定义的URLConf
URL模式,以便生成正确的URL。如果URLConf
没有被加载,reverse
将无法找到生成URL所需的信息,并引发异常。
例如:
一个基于类的视图:
from django.views.generic.edit import DeleteView
from django.urls import reverse_lazy
class PostDeleteView(DeleteView):
model = Post
template_name = "post_delete.html"
success_url = reverse_lazy('home')
当您定义success_url
(一个类属性)时,您使用了reverse_lazy
而不是reverse
。这是因为类属性在执行类定义时进行评估。这意味着分配给类属性的值是在定义类时确定的,而不是在创建类的实例时确定的。
当您导入类时,Python解释器会从上到下执行类定义,包括类属性,如success_url
,但有可能URLConf
尚未加载。
为了避免错误,我们使用reverse_lazy
而不是reverse
,它将实际调用URLConf
的时间延迟到需要的时候,而不是在评估类属性时。
reverse
的理由吗?只需始终使用reverse_lazy
,不必担心 URL 是否已加载。reverse
有什么好处吗? - Sviatozar Petrenko