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

pis*_*che 6 django django-urls lazy-evaluation

介绍

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

只要我不必传递参数,这就行得很好reverse_lazy().但是,如果我想Grid特定于某个对象(这里是a 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)
Run Code Online (Sandbox Code Playgroud)

错误

但是当然,导入文件时会失败,因为NoneType object has no attribute 'id'.

第二次尝试

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

def get_id(self):
    return self.id
Run Code Online (Sandbox Code Playgroud)

并通过使用此代码:

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)
Run Code Online (Sandbox Code Playgroud)

错误

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

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

结论

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

Igo*_*gor 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'
Run Code Online (Sandbox Code Playgroud)

但是,如果要替换函数中的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, })
Run Code Online (Sandbox Code Playgroud)