Django: изменить значение по умолчанию для расширенного класса модели
Я отправил аналогичный вопрос раньше, но это другое. У меня есть модель структуры связанных классов вроде:
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)
Я хочу изменить значение по умолчанию ques_type в производном классе. Как это сделать?
Ответы
Ответ 1
Во-первых, в этом использовании наследования он (по крайней мере, согласно моим тестам) не может изменить значение по умолчанию для поля в дочернем классе. MathQuestion
и Question
совместно используют одно и то же поле, изменение значения по умолчанию в дочернем классе влияет на поле родительского класса.
Теперь, если разница между MathQuestion
и Question
отличается от поведения (поэтому MathQuestion
не добавляет никаких полей, кроме тех, которые определены в Question
), вы можете сделать это прокси-модель. Таким образом, для 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
Тест:
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
Ответ 2
Используйте Form
или ModelForm
, на котором вы можете переопределить это поле. Для моделей задайте в нем значение по умолчанию __init__
:
class Question(models.Model):
ques_type = models.SmallIntegerField(default=2)
class MathQuestion(Question):
def __init__(self, *args, **kwargs):
super(MathQuestion, self).__init__(*args, **kwargs)
self.ques_type = 3
class Meta:
proxy = True
Обратите внимание, что это нужно сделать после вызова родительского класса init.
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/
Ответ 3
Это легко сделать, используя закрытие.
из моделей импорта django.db
# 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
Закрытие позволяет вам определить, как вам это нравится.
из моделей импорта django.db
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.
Ответ 4
Приведенные выше примеры для прокси-моделей. Если вам нужно изменить значение по умолчанию для модели, унаследованной от неабстрактной базовой модели, вы можете сделать следующее:
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)
Который установит значение по умолчанию, если оно не было передано непосредственно в Model(...)
или Model.objects.create(...)
.