I posted a similar question a while earlier, but this one is different. I have a model structure of related classes like:
class Question(models.Model):
ques_type = models.SmallIntegerField(default=TYPE1, Choices= CHOICE_TYPES)
class MathQuestion(Question):
//Need to change default value of ques_type here
// Ex: ques_type = models.SmallIntegerField(default=TYPE2, Choices= CHOICE_TYPES)
I want to change the default value of ques_type in the derived class. How should i accomplish this?
Examples above are for proxy models. If you need to change default for model inherited from non-abstract base model you can do following:
from django.db import models
class Base(models.Model):
field_name = models.CharField(...)
class Child(Base):
def __init__(self, *args, **kwargs):
kwargs['field_name'] = kwargs.get('field_name') or 'default value'
super().__init__(*args, **kwargs)
Which will set default if it wasn't passed directly on Model(...)
or Model.objects.create(...)
.
First, in this use of inheritance it is (at least according to my tests) not possible to change the default of the field in the child class. MathQuestion
and Question
share the same field here, changing the default in the child class affects the field in the parent class.
Now if what only differs between MathQuestion
and Question
is the behaviour (so, MathQuestion
doesn't add any fields besides those defined in Question
), then you could make it a proxy model. That way, no database table is created for MathQuestion
.
from django.db import models
class Question(models.Model):
ques_type = models.SmallIntegerField(default=2)
class MathQuestion(Question):
def __init__(self, *args, **kwargs):
self._meta.get_field('ques_type').default = 3
super(MathQuestion, self).__init__(*args, **kwargs)
class Meta:
proxy = True
Test:
In [1]: from bar.models import *
In [2]: a=Question.objects.create()
In [3]: a.ques_type
Out[3]: 2
In [4]: b=MathQuestion.objects.create()
In [5]: b.ques_type
Out[5]: 3
This is easy to do using a closure.
from django.db import models
# You start here, but the default of 2 is not what you really want.
class Question(models.Model):
ques_type = models.SmallIntegerField(default=2)
class MathQuestion(Question):
def __init__(self, *args, **kwargs):
self._meta.get_field('ques_type').default = 3
super(MathQuestion, self).__init__(*args, **kwargs)
class Meta:
proxy = True
The closure allows you to define it how you like it.
from django.db import models
def mkQuestion(cl_default=2):
class i_Question(models.Model):
ques_type = models.SmallIntegerField(default=cl_default)
class i_MathQuestion(i_Question):
def __init__(self, *args, **kwargs):
super(MathQuestion, self).__init__(*args, **kwargs)
return i_MATHQUESTION
MathQuestion = mkQuestion()
MathQuestionDef3 = mkQuestion(3)
# Now feel free to instantiate away.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With