Подтвердить что ты не робот

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 в производном классе. Как это сделать?

4b9b3361

Ответ 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(...).