Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 628
grucha Avatar asked Aug 26 '10 09:08

grucha


People also ask

What is the purpose of __ Str__ method in Django?

str function in a django model returns a string that is exactly rendered as the display name of instances for that model. # Create your models here. This will display the objects as something always in the admin interface.

What is default in Django model?

default: The default value for the field. This can be a value or a callable object, in which case the object will be called every time a new record is created. null: If True , Django will store blank values as NULL in the database for fields where this is appropriate (a CharField will instead store an empty string).

How do I override a save in Django?

save() method from its parent class is to be overridden so we use super keyword. slugify is a function that converts any string into a slug. so we are converting the title to form a slug basically.

How Django knows to update VS insert?

The doc says: If the object's primary key attribute is set to a value that evaluates to True (i.e. a value other than None or the empty string), Django executes an UPDATE. If the object's primary key attribute is not set or if the UPDATE didn't update anything, Django executes an INSERT link.


2 Answers

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.

like image 106
vdboor Avatar answered Dec 23 '22 07:12

vdboor


If you want to just output default value, override __getattr__() method like this:

class ModelA(models.Model):   # your fields   def __getattr__(self, name):     if(name == 'fieldA' and !self.fieldA):       return self.get_previous()     else:       return super(ModelA, self).__getattr__(name) 

Saving default value from object will be little difficultier. First solution that comes in my mind, override save() method (i believe there is simpler solution)

like image 27
Anpher Avatar answered Dec 23 '22 07:12

Anpher