如何覆盖抽象模型的null和空白字段属性

时间:2017-06-06 17:36:18

标签: python django inheritance django-models

我想在从抽象模型继承的所有字段上将null和blank设置为true。

我目前的尝试遵循类似的SO问题,例如overriding the 'default' attribute on ABCoverriding parent model's attribute,表示有可能。当从python控制台初始化对象时,我得到了所需的运行时行为,但它没有反映在迁移文件或数据库中。

背景:

我有一个系统模型,我希望能够在某些数据上创建客户端特定的覆盖。我有以下型号:

  • abstract BaseSystem - 定义可覆盖的字段
  • 具体的SystemOverride - 包含部分覆盖的记录
  • 具体系统 - 包含' full'系统记录。

使SystemOverride中的所有字段为null / blank = True非常重要,这样只有初始化的字段(由客户端)才会覆盖相关的System对象。

代码:

class BaseSystem(models.Model):

    class Meta:
        abstract = True

    def __init__(self, *args, **kwargs):
        super(BaseSystem, self).__init__(args, kwargs)

        # Mark all fields with 'override' attribute
        for field in self._meta.get_fields():
            field.override = True

    name = models.CharField(max_length=128)


class System(BaseSystem):
    pass


class SystemOverride(BaseSystem):

    def __init__(self, *args, **kwargs):
        super(SystemOverride, self).__init__(args, kwargs)

        # Set all overridable fields to null/blank = True. 
        for field in self._meta.get_fields():
            if(hasattr(field, 'override') and field.override):
                field.null = True
                field.blank = True

    # Override-specific fields
    system = models.ForeignKey(System)

makemigrations的结果:

class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='System',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=128)),
            ],
            options={
                'abstract': False,
            },
        ),
        migrations.CreateModel(
            name='SystemOverride',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=128)),
                ('system', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='overide.System')),
            ],
            options={
                'abstract': False,
            },
        ),
    ]

null = True和blank = True尚未添加到SystemOveride中的名称字段中。

2 个答案:

答案 0 :(得分:0)

这不能在班级的 init 中完成。 makemigrations永远不会看到它。您需要在元类级别执行此操作。

答案 1 :(得分:0)

你可以像这样创建一个抽象的 CharField 类:

class AbstractCharField(models.CharField):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.null = True
        self.blank = True

    class Meta:
        abstract = True


# usage
name = AbstractCharField(max_length=128)
相关问题