django custom manager with filter parameter
I'd simplify it:
class CurrentManager(models.Manager):
def current(self, my_date):
return super(CurrentManager, self).get_query_set().filter(valid_from__lte=my_date)
and then use it like this:
a = A.objects.get(id=a_id)
my_date = request.user.get_profile().my_date
b_objects = a.b_set.objects.current(my_date)
and then just pass a to the template as the filtered objects accessing them using this:
{% for b in b_objects %}
Hope this helps!
Edit (by requestor):
I had to adjust it as follows to get it working:
a = A.objects.get(id=a_id)
my_date = request.user.get_profile().my_date
b_objects = a.b_set.current(my_date)
This threw an error: "'RelatedManager' object has no attribute 'objects'"
a.b_set.objects.current(my_date)
Related videos on Youtube
szeta
Updated on June 17, 2022Comments
-
szeta about 2 years
I would like to add a custom manager which can be called from a template, but does not affect the entire model (e.g. admin views) and which listens to a parameter set in the request (user_profile).
The following is what I have so far:
models.py:
class CurrentQuerySet(models.query.QuerySet): def current(self): return self.filter(id=1) ## this simplified filter test works.. class CurrentManager(models.Manager): use_for_related_fields = True def get_query_set(self): return CurrentQuerySet(self.model) def current(self, *args, **kwargs): return self.get_query_set().current(*args, **kwargs)
For model B is defined:
objects = CurrentManager()
The template calls:
{% for b in a.b_set.current %}
But as soon as I try to pass a parameter to that filter (in this case a date stored on the user-profile) the method does not return any results.
e.g.:
models.py
class CurrentQuerySet(models.query.QuerySet): def current(self,my_date): return self.filter(valid_from__lte=my_date)
showA.html
{% for b in a.b_set.current(request.user.get_profile.my_date) %}
Instead of passing the parameter from the template, I have also tried to set this in the view.py
@login_required def showA(request,a_id): my_date = request.user.get_profile().my_date a = A.objects.get(id=a_id) t = loader.get_template('myapp/showA.html') c = RequestContext(request,{'a':a,'my_date':my_date,}) return HttpResponse(t.render(c))
Which part am I missing (or misunderstanding) here?
Thanks
R
Edit
Here the models. As mentioned, in this example it's a simple 1:n relationship, but can also be m:n in other cases.
class A(models.Model): #objects = CurrentManager() a = models.CharField(max_length=200) description = models.TextField(null=True,blank=True) valid_from = models.DateField('valid from') valid_to = models.DateField('valid to',null=True,blank=True) def __unicode__(self): return self.a class B(models.Model): #objects = models.Manager() objects = CurrentManager() a = models.ForeignKey(A) b = models.CharField(max_length=200) screenshot = models.ManyToManyField("Screenshot",through="ScreenshotToB") description = models.TextField(null=True,blank=True) valid_from = models.DateField('valid from') valid_to = models.DateField('valid to',null=True,blank=True) def __unicode__(self): return self.b
Edit-2
The accepted answer works for at least one relationship.
In case of a more nested data model, this method seems not to deliver the expected results:models.py
class C(models.Model): objects = CurrentManager() b = models.ForeignKey(A) c = models.CharField(max_length=200) description = models.TextField(null=True,blank=True) valid_from = models.DateField('valid from') valid_to = models.DateField('valid to',null=True,blank=True) def __unicode__(self): return self.c
views.py
@login_required def showA(request,a_id): a = A.objects.get(id=a_id) my_date = request.user.get_profile().my_date b_objects = a.b_set.current(my_date) c_objects = b_objects.c_set.current(my_date) t = loader.get_template('controltool2/showA.html') c = RequestContext(request,{'a':a,'b_objects':b_objects,'c_objects':c_objects,}) return HttpResponse(t.render(c))
This returns the error:
'QuerySet' object has no attribute 'c_set'
. -
szeta almost 11 yearsHi, thanks for your simplification. Maybe I should have been more clear, that there are two models involved, Model A and Model B (in this case 1:n). That's why I do a
a = A.objects.get(id=a_id)
and then{% for b in a.b_set.current %}
. How would I apply this? In the view I'm only touching A so far.