For a particular need (django-jqgrid), I define a class (representing a Grid
) where I have to provide an url
attribute. Since I use only reversed URLs (nothing statically defined), I use reverse_lazy()
for this matter.
This works great as long as I do not have to pass an argument to reverse_lazy()
. However, if I want to make that Grid
specific to an object (here, a DocumentSet
), this url
arguments needs to be also specific to that object, and so I need to provide an argument to reverse_lazy().
On runtime, I can access the DocumentSet
because I defined it as an attribute on the object, and I ensure that the first function called on this Grid
takes this object as an argument, and sets the attribute correctly.
I tried using this code :
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)
But of course, this fails when the file is imported because NoneType object has no attribute 'id'
.
So I tried using django.utils.functional.lazy()
, by adding this trivial and stupid function to my model :
def get_id(self):
return self.id
And by using this code :
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)
Now the file is imported correctly, without Django complaining. However, at runtime, I get the following error :
Reverse for 'document-grid-handler' with arguments '()' and keyword arguments '{'pk': <function get_id at 0x1a07410>}' not found.
Is this the correct way to go, but I'm making a small mistake ? Or did I misunderstood everything about lazy evaluation and should take a completely different approach and rewrite reverse_lazy()
?
django.utils.functional.lazy()
return you a lazy-evaluated callable, in other words it gives you a function that will return lazy value.
See example:
l = lazy(lambda : 42, str)
unicode(l) # returns u'<function <lambda> at 0x3a5bcf8>'
lazy_value = l()
unicode(lazy_value) # returns u'42'
However if you are replacing the self.documentset
field in your get_json
function you can get wrong results with your lazy call. As it will use an old DocumentSet
.
For JqGrid
there is another solution. JqGrid
provides you the get_url
method, by default it just returns self.url
. But you can override this behaviour:
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, })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With