Django: field's default value from self model's instances

grucha picture grucha · Aug 26, 2010 · Viewed 14k times · Source

How can I make default value for a field to be taken from existing objects of a model?

I tried these and it didn't worked:

1)

class ModelA(models.Model):
    fieldA = models.CharField(default=self.get_previous())

    def get_previous(self):
        return ModelA.objects.all()[0].fieldA

NameError: name 'self' is not defined

2)

class ModelA(models.Model):
    fieldA = models.CharField(default=ModelA.get_previous())

    @staticmethod
    def get_previous():
        return ModelA.objects.all()[0].fieldA

NameError: name 'ModelA' is not defined

3)

class ModelA(models.Model):
    fieldA = models.CharField(default=get_previous())

def get_previous():
    return ModelA.objects.all()[0].fieldA

NameError: global name 'get_previous' is not defined

4)

def get_previous():
    return ModelA.objects.all()[0].fieldA

class ModelA(models.Model):
    fieldA = models.CharField(default=get_previous())

NameError: global name 'ModelA' is not defined

I it's clear why 3) and 4) won't work. I can imagine why 1) won't work - looks like class' properies can't refer to instance's (i.e. self). I can imagine why 2) won't work - apparently there's no reference to ModelA until interpreter will go trough whole class.

So how should I approach this?

Answer

vdboor picture vdboor · Aug 26, 2010

In your examples, you need to remove the call operator ().

Currently the statement is executed immediately at the first read-parsing cycle. By specifying the symbol name instead, the Django class receives a function pointer which it will execute when it actually needs the default value.

The example becomes:

def get_previous():
    return ModelA.objects.all()[0].fieldA

class ModelA(models.Model):
    fieldA = models.CharField(default=get_previous)

If you're going to do this for a lot of fields, consider overridding the save function, so you only have to fetch the previous object from the database just once.