Django:更改扩展模型类的默认值

13

我之前发布过一个类似的问题,但这个问题不同。 我有一个相关类的模型结构,例如:

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的默认值,应该如何实现?

4个回答

15

首先,在这种继承使用中(至少根据我的测试),不可能更改子类中该字段的默认值。在这里,MathQuestionQuestion共享同一个字段,更改子类中的默认值会影响父类中的该字段。

现在,如果只有MathQuestionQuestion之间的行为不同(也就是说,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

3
我正在派生类中添加新字段,因此代理类方法将无法正常工作。 - Neo
@Neo 我尝试过了,但根据文档所述,这是不可能的:如果一个基类有一个名为author的字段,则您不能在任何继承自该基类的类中创建另一个名为author的模型字段。 - Reiner Gerecke
2
我并不想通过创建一个新字段来覆盖原有的内容,只是想在初始化方法中设置一个不同的“值”。这样做可行吗? - Neo
2
正如我回答的第一段所提到的,我尝试过那样做,但它会影响父类的字段,因为它们共享同一个对象。两个字段的默认值都变成了3。 - Reiner Gerecke
3
请在您的回答中明确指出,此解决方案无效。调用子类的init函数也会覆盖超类中的默认值。 - mutantacule
显示剩余2条评论

5

以上示例适用于代理模型。如果您需要更改从非抽象基本模型继承的模型的默认设置,可以执行以下操作:

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(...)中没有传递默认值,那么它将设置为默认值。


2
这很容易使用闭包完成。
从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导入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.

非常好的方法!它起作用了!在我的情况下,我有一个默认值生成器,它从类中接收一个参数,即类的slug名称。 - Neoecos

2
使用 FormModelForm,你可以在上面覆盖字段。对于模型,在其 __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/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接