Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Purpose of using a custom manager to create objects with django?

I see in the Django documentation :

Model Instance reference : Creating objects

You may be tempted to customize the model by overriding the __init__ method. If you do so, however, take care not to change the calling signature as any change may prevent the model instance from being saved.
Rather than overriding __init__, try using one of these approaches:

  • Add a classmethod on the model class.
  • Add a method on a custom manager (usually preferred)

Why is the second solution "usually preferred" ?

In a situation where I have a model B which extends a model A through a OneToOne relation, and I want to create a method generating a B object which generates the corresponding A object as well, how is it "better" to use a custom manager as suggested, given I'll probably not use this manager for anything other than what is provided by default manager ?

like image 448
Levans Avatar asked Aug 08 '13 12:08

Levans


1 Answers

I think it is preferred because it looks cleaner in code. You might also be reading into the emphasizes a bit too much, as the benefit or difference isn't that big. That said, when implementing things myself I do use the proposed approach.

Consider the following model (purely for illustrative purposes):

class Vehicle(models.Model):
    wheels = models.IntegerField()
    color = models.CharField(max_length=100)

In your application, the need often arises to get all cars, or all motorcycles, or whatever type of vehicle. To keep things DRY, you want some standard form of retrieving this data. By using class methods, you'd get the following:

class Vehicle(models.Model):
    #(...)
    @classmethod
    def cars(cls):
        return Vehicle.objects.filter(wheels=4)

cars = Vehicle.cars()
green_cars = Vehicle.cars().filter(color='green')

If you create a manager, you'll get something like this:

class CarManager(models.Manager):
    def get_query_set(self):
        return super(CarManager, self).get_query_set().filter(wheels=4)

class Vehicle(models.Model):
    #(...)
    car_objects = CarManager()

cars = Vehicle.car_objects.all()
green_cars = Vehicle.car_objects.filter(color='green')

In my opinion, the latter looks cleaner, especially when things get more complex. It keeps the clutter out of your model definitions, and keeps things similar to using the default objects manager.

like image 93
jro Avatar answered Oct 09 '22 12:10

jro