0

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.

2
  • Can you show us the view for this? The best solution would depend heavily on what type of view you are using. Commented Sep 28, 2019 at 18:58
  • My view is a CBV as such: class MemoDetailView(DetailView): model = Memo. But I will have this issue with ListView's as well. Is there somewhere specific in the Django docs that explains this better? Commented Sep 28, 2019 at 19:22

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

6 Comments

Lets use an example from the Django Docs I see that you can create a Poll Manager and tell the model that objects = PollManager(). But how do you access OpinionPoll.objects.with_counts() within the template. Django throws an error about Managers not being accessible in the templates.
Hmm, let's put it this way. Your model (and the related model manager) is basically a blueprint for your model instances. If you wanted to access an attribute then that must be a part of a model instance and not the blueprint. If you wanted to get the memo count in your template, you must a pass a context to your template through your view. The context is basically a dictionary which contains values/objects the template can access.
I have edited my answer, that should help you with your query. However, it seems you are a beginner in django and I would suggest to not use Generic Class Based Views in the initial stages of learning. Generic CBV's require less code but abstracts so many things and does so much implicitly that it might create a log of confusions. I would suggest to stick to normal views (CBV or FBV upto you). This might help you understand how a HTTP request is handled by a django app.
I see. Your detailed response has been very helpful and I will continue to read in the Django Documentation on Adding Extra Context
You are asking the right questions and also are on the right track. Model Managers are usually used for a lot of reasons (creating custom querysets is just one of them). Read this article if you have the time. medium.com/kolonial-no-product-tech/…
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.