How to Create Custom Manager in Django?

Published On: 04/01/2023 | Category: Django


Hi Dev,

This post is focused on how to create custom manager in django. I explained simply step by step django custom manager example. you can understand a concept of django model manager example. you will learn django model manager get queryset. Let's get started with django model manager get_queryset.

In Django manager serves as an interface for Django models to communicate with databases. There is at least one manager object in every model. It has a lot of methods, attributes to ease working with databases

Here i will give you we will help you to give example of how to create custom manager in django. So let's see the bellow example:

Step 1: Create a Project

In this step, we’ll create a new django project using the django-admin. Head back to your command-line interface and run the following command:

django-admin startproject myproject
Step 2: Create a App
cd myproject
django-admin startapp base

Step 3: Update settings.py

Next, you need to add it in the settings.py file as follows:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'base', #new
] 
Step 4: Create a Model

Now go for the models we will We'll call our single model File and it will have just two fields: name, size and file_type. And finally set __str__ to display the name of the file in admin interface.

base/models.py
from django.db import models

# Create your models here.
class FileManager(models.Manager):

    def pdfs(self):
        return self.filter(file_type='pdf')

    def smaller_than(self, size):
        return self.filter(size__lt=size)

class File(models.Model):
    name = models.CharField(max_length=30)
    size = models.PositiveIntegerField(default=0)
    file_type = models.CharField(max_length=10, blank=True)

    def __str__(self):
        return self.name

    objects = FileManager()

Ok, all set. We can engender a migrations file for this change, then integrate it to our database via migrate.

python manage.py makemigrations
python manage.py migrate

In this step, you can obtain all PDF files in the following way:

File.objects.pdfs()

The issue is that this technique cannot be chained. In the result, you can still apply an order_by or filter:

File.objects.pdfs().order_by('name')

So, if you are trying to the chain method like this.

File.objects.pdfs().smaller_than(700)
AttributeError: 'QuerySet' object has no attribute 'smaller_than'

Next, you can create custom queryset method following below code.

from django.db import models

# Create your models here.
class FileQuerySet(models.QuerySet):
    def pdfs(self):
        return self.filter(file_type='pdf')

    def smaller_than(self, size):
        return self.filter(size__lt=size)

class FileManager(models.Manager):
    def get_queryset(self):
        return FileQuerySet(self.model, using=self._db)  # Important!

    def pdfs(self):
        return self.filter(file_type='pdf')

    def smaller_than(self, size):
        return self.filter(size__lt=size)

class File(models.Model):
    name = models.CharField(max_length=30)
    size = models.PositiveIntegerField(default=0)
    file_type = models.CharField(max_length=10, blank=True)

    def __str__(self):
        return self.name

    objects = FileManager()

Ok, all set. We can create a migrations file for this change, then integrate it to our database via migrate.

python manage.py makemigrations
python manage.py migrate

Now, you can get a any queryset method.

File.objects.pdfs().smaller_than(1000).exclude(name='File').order_by('name')

Simply extend the models if all you're doing in the Manager is creating unique QuerySets. QuerySet and FileQuerySet.as_manager() both set the manager as objects in the model

from django.db import models

# Create your models here.
class FileQuerySet(models.QuerySet):
    def pdfs(self):
        return self.filter(file_type='pdf')

    def smaller_than(self, size):
        return self.filter(size__lt=size)

class File(models.Model):
    name = models.CharField(max_length=30)
    size = models.PositiveIntegerField(default=0)
    file_type = models.CharField(max_length=10, blank=True)

    objects = FileQuerySet.as_manager()

I Hope It will help you....