Django provides a great way to query your database with few lines of code and without writing SQL. However, there are some cases when you'll find yourself repeating the same piece of code logic in a project.π₯Ά
Problem
Let's say we've added a new field to a model to create a public_id
based on uuid4
.
class Product(models.Model):
public_id = models.UUIDField(db_index=True, unique=True, default=uuid.uuid4, editable=False)
Basically, this public_id
will be used instead of the id
of an object to perform CRUD actions.
Suppose that a user makes a request to retrieve a specific object in the database.
A solid logic will look like this:
public_id = kwargs.get("public_id")
try:
product = Product.objects.get(public_id=public_id)
except ObjectDoesNotExist:
raise Http404("Product does not exist")
Simple logic right here, until you are adding other models to your project that use the same public_id
field and you find yourself repeating the same piece of code logic.
Solution
Custom model managers allow developers to write extra methods for a model.
Returning to the example, let's create a custom Manager
class for the Product
model.
class ProductManager(models.Manager):
def get_object_by_public_id(self, public_id):
try:
instance = self.get(public_id=public_id)
return instance
except ObjectDoesNotExist as e:
raise e
class Product(models.Model):
public_id = models.UUIDField(db_index=True, unique=True, default=uuid.uuid4, editable=False)
objects = ProductManager()
And when retrieving an object, the code will simply be:
public_id = kwargs.get("public_id")
product = Product.objects.get_object_by_public_id(public_id)
If you have other models in the database, let's suppose a Shop
model or a User
model with also a public_id
field. We can write an AbstractManager
class.
class AbstractManager(models.Manager):
def get_object_by_public_id(self, public_id):
try:
instance = self.get(public_id=public_id)
return instance
except (ObjectDoesNotExist, ValueError, TypeError) as e:
raise e
class ShopManager(AbstractManager):
pass
class ProductManager(AbstractManager):
pass
class Product(models.Model):
public_id = models.UUIDField(db_index=True, unique=True, default=uuid.uuid4, editable=False)
objects = ProductManager()
class Shop(models.Model):
public_id = models.UUIDField(db_index=True, unique=True, default=uuid.uuid4, editable=False)
objects = ShopManager()
product = Product.objects.get_object_by_public_id(public_id)
shop = Shop.objects.get_object_by_public_id(public_id)
πππ
You can learn more about managers in the official documentation of Django.
Article posted using bloggu.io. Try it for free.