Nothing here
Nothing here

Reputation: 2363

How to access object count in template using model manager?

I have a model which creates Memo objects. I would like to use a custom Model Manager's posted method to return the total number of Memo objects - then use this number within a template. I am trying to keep as much of my code as possible within my Models and Model Managers and less within my Views as I read that this was a best practice in 'Two Scoops of Django'.

In the shell I can get the number of memos as such:

>>> from memos.models import Memo
>>> Memo.objects.all()
<QuerySet [<Memo: Test Memo 2>, <Memo: Test Memo 1>]>
>>> Memo.objects.all().count()
2

This is what my Model and Model Manager look like:

class MemoManager(models.Manager):

    use_for_related_fields = True

    def posted(self):
        return self.count()


class Memo(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    date_time = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)

    objects = MemoManager()

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('memos-detail', kwargs={'pk': self.pk})

I know this is clearly the wrong way to do it but I have confused myself here. So how do I use my Model Manager to get the count of objects and use it in a template like: {{ objects.all.count }}?

P.S. I see other posts that show how to do this within the view but as stated I am trying not to use the view. Is using the view required? I also understand my posted method is written incorrectly.

Upvotes: 0

Views: 276

Answers (1)

Mehran
Mehran

Reputation: 1304

I'm sorry but you have misinterpreted what was written in TSD. The Lean View Fat Model is meant to keep code which pertains to 'business logic' out of the views, and certain model specific things. A request should be handled by a view. So when you want to load a template, you must first have a GET request to your app.

A view function should be written such that Validation of POST data or the Creation of a new object in DB or Querying/Filtering for GET requests should be handled in the corresponding serializer/model/model manager.

What should be happening while you want to load your template.

  1. Have a url for the template that you have created and a view function mapped for it
  2. In the view function you should render said template and pass the necessary data inside the context.
  3. To keep in line with the Lean View Fat Model style, if you want to get a Queryset of of Memo's but only those which have their is_deleted fields set to False, you can overwrite the model manager get_queryset() method for Memo model.
  4. If you want to create a new Memo with a POST request, you can handle the creation using a ModelForm!

Hope this clears things up!

EDIT: How to pass a context to a template, in your case the memo count.

def random_memo_view(request):
    context = {'memo_count': Memo.posted()}
    return render(request, 'template.html', context=context)

RE-EDIT I just checked that you were using DetailView. In this case follow this from the django docs. Class Based Views: Adding Extra Context

Upvotes: 1

Related Questions