Django model class methods for predefined values


Question

I'm working on some Django-code that has a model like this:

class Status(models.Model):
    code = models.IntegerField()
    text = models.CharField(maxlength=255)

There are about 10 pre-defined code/text-pairs that are stored in the database. Scattered around the codebase I see code like this:

status = Status.objects.get(code=0) # successful
status = Status.objects.get(code=1) # failed

I would rather have a method for each so that the code would look something like this instead:

status = Status.successful()
status = Status.failed()
etc...

Is this possible? I have looked in to the Manager-stuff but I haven't really found a way. Is it time to really RTFM?

In Java it would be a static method and in Ruby you would just define a method on self, but it's not that easy in Python, is it?

1
14
2/6/2010 1:57:11 PM

Accepted Answer

You should perhaps implement this by defining a custom manager for your class, and adding two manager methods on that manager (which I believe is the preferred way for adding table-level functionality for any model). However, another way of doing it is by throwing in two class methods on your class that query and return resulting objects, such as:

class Status(models.Model):
    code = models.IntegerField()
    text = models.CharField(maxlength=255)

    @classmethod
    def successful(cls):
        return cls.objects.get(code=0)

    @classmethod
    def failed(cls):
        return cls.objects.get(code=1)

Do note please that get() is likely to throw different exceptions, such as Status.DoesNotExist and MultipleObjectsReturned.

And for an example implementation of how to do the same thing using Django managers, you could do something like this:

class StatusManager(models.Manager):
    def successful(self):
        return self.get(code=1)

    def failed(self):
        return self.get(code=0)

class Status(models.Model):
    code = models.IntegerField()
    text = models.CharField(maxlength=255)

    objects = StatusManager()

Where, you could do Status.objects.successful() and Status.objects.failed() to get what you desire.

35
1/30/2015 4:59:15 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon