Django

Lesson 04

Model manager boundaries

Put common query rules in QuerySet or manager methods so views do not repeat domain filters.

Good Code

reviews/models.py
from django.db import models


class ReviewQuerySet(models.QuerySet):
    def visible_to(self, user):
        base = self.filter(deleted_at__isnull=True)
        if user.is_staff:
            return base
        return base.filter(status=Review.Status.PUBLISHED)

    def with_author(self):
        return self.select_related("author")


class Review(models.Model):
    objects = ReviewQuerySet.as_manager()


def review_list(request):
    reviews = Review.objects.visible_to(request.user).with_author()
    return render(request, "reviews/list.html", {"reviews": reviews})

Bad Code

reviews/views.py
def review_list(request):
    reviews = Review.objects.filter(
        deleted_at__isnull=True,
        status="published",
    ).select_related("author")
    return render(request, "reviews/list.html", {"reviews": reviews})


def review_feed(request):
    reviews = Review.objects.filter(
        deleted_at__isnull=True,
        status="published",
    ).order_by("-published_at")
    return render(request, "reviews/feed.html", {"reviews": reviews})

Review Notes

What to review

Good Code

The good version names the visibility rule once and lets views ask for the query they need.

Bad Code

The bad version repeats filters in multiple views. When the visibility rule changes, one path can easily drift.

Takeaways

  • Repeated filters are a sign that a query rule needs a named boundary.