如何使参数的reverse_lazy()变得懒惰?

时间:2013-03-29 12:42:56

标签: django django-urls lazy-evaluation

简介

对于特定需求(django-jqgrid),我定义了一个类(代表Grid),我必须提供url属性。由于我只使用反向URL(没有静态定义),因此我使用reverse_lazy()

只要我不必将参数传递给reverse_lazy(),这就行得很好。但是,如果我想使Grid特定于某个对象(此处为DocumentSet),则此url参数也需要特定于该对象,因此我需要提供reverse_lazy()的参数。

在运行时,我可以访问DocumentSet因为我将它定义为对象的属性,并且我确保调用此Grid的第一个函数将此对象作为参数,并设置属性正确。

首次尝试

代码

我尝试使用此代码:

class DocumentGrid(JqGrid):
    documentset = None
    model = Document
    url = reverse_lazy('document-grid-handler', kwargs = {'pk' : documentset.id, })

    def get_queryset(self, request):
        return self.documentset.documents
    def get_json(self, request, documentset):
        self.documentset = documentset
        return super(DocumentGrid, self).get_json(request)

错误

但当然,由于NoneType object has no attribute 'id'导入文件时失败。

第二次尝试

代码

所以我尝试使用django.utils.functional.lazy(),将这个琐碎和愚蠢的函数添加到我的模型中:

def get_id(self):
    return self.id

使用此代码:

class DocumentGrid(JqGrid):
    documentset = DocumentSet
    model = Document
    url = reverse_lazy('document-grid-handler', kwargs = {'pk' : lazy(documentset.get_id, int), })

    def get_queryset(self, request):
        return self.documentset.documents
    def get_json(self, request, documentset):
        self.documentset = documentset
        return super(DocumentGrid, self).get_json(request)

错误

现在文件正确导入,没有Django抱怨。 但是,在运行时,我收到以下错误:

Reverse for 'document-grid-handler' with arguments '()' and keyword arguments '{'pk': <function get_id at 0x1a07410>}' not found.

结论

这是正确的方法,但我犯了一个小错误?或者我是否误解了关于懒惰评估的所有内容,应采取完全不同的方法并重写reverse_lazy()

1 个答案:

答案 0 :(得分:7)

django.utils.functional.lazy()返回一个懒惰计算的可调用对象,换句话说它会为你提供一个返回延迟值的函数。

参见示例:

l = lazy(lambda : 42, str)
unicode(l)  # returns u'<function <lambda> at 0x3a5bcf8>'
lazy_value = l()
unicode(lazy_value)  # returns u'42'

但是,如果您要替换self.documentset函数中的get_json字段,则您的懒惰调用可能会导致错误的结果。因为它将使用旧的DocumentSet

对于JqGrid,还有另一种解决方案。 JqGrid为您提供了get_url方法,默认情况下它只返回self.url。但您可以覆盖此行为:

class DocumentGrid(JqGrid):
    documentset = None
    model = Document
    url = None

    def get_queryset(self, request):
        return self.documentset.documents

    def get_json(self, request, documentset):
        self.documentset = documentset
        return super(DocumentGrid, self).get_json(request)

    def get_url(self):
        return reverse('document-grid-handler', kwargs = {'pk' : self.documentset.id, })