Django限制可以提供给模型字段的数据

时间:2017-12-31 04:32:28

标签: python django django-models

我在django中有以下模型:

class Cast(TimeStampedModel):
    user = models.ForeignKey(User, unique=True)
    count = models.PositiveIntegerField(default=1)
    kind = models.CharField(max_length = 7)

    def __str__(self):
        return(f"{self.kind} || {self.count} || {self.modified.strftime('%x')}")

但我希望'种类'字段只能采用以下值之一:向上,向下,奇怪,魅力,顶部或底部。如何在数据库中强制执行此操作,或者只能在接收数据时在视图中强制执行此操作?

2 个答案:

答案 0 :(得分:2)

我认为choices应该做什么?

class Cast(TimeStampedModel):
    user = models.ForeignKey(User, unique=True)
    count = models.PositiveIntegerField(default=1)
    kind = models.CharField(
        max_length=7,
        choices=(
            ("up", "Up"),
            ("down", "Down"),
            ("strange", "Strange"),
            ("charm", "Charm"),
            ("top", "Top"),
            ("bottom", "Bottom")
        )
    )

虽然在很多情况下我已经看到它用作SmallInteger来节省数据库中的空间:在数据库中存储一个数字,在您的管理区域中,您会看到一个带有&的下拉菜单#34;人性化"选择。

kind = models.PositiveSmallIntegerField(
    choices=(
        (1, "Up"),
        (2, "Down"),
        (3, "Strange"),
        (4, "Charm"),
        (5, "Top"),
        (6, "Bottom")
    )
)

请参阅:

Choices in action

这是未在数据库级别强制执行(请参阅this ticket和此SO question),这意味着您仍然可以执行此操作:

>>> c = Cast.objects.first()
>>> c.kind = 70
>>> c.save()

但它在管理员中强制实施。如果您需要在较低级别强制执行,我建议您使用Noah Lc's answer。据我了解,这并非100%强制执行:您仍然可以执行不会通过模型的.save()方法的批量更新,这意味着,执行Cast.objects.all().update(kind=70)仍会设置70字段中的值无效(kind),但他的解决方案确实是一步"更低"而不是选择。您无法通过实例的.save()方法进行模型更新。意思是,你不会被允许这样做:

>>> c=Cast.objects.first()
>>> c.kind=70
>>> c.save()

如果确实需要REAL数据库实施,则需要实际检查数据库的可能性并在cast.kind列上添加约束。

例如,对于Postgres(可能还有大多数其他SQL版本),您可以创建一个新的迁移来执行此操作:

from django.db import migrations


def add_kind_constraint(apps, schema_editor):
    table = apps.get_model('stackoverflow', 'Cast')._meta.db_table
    schema_editor.execute("ALTER TABLE %s ADD CONSTRAINT check_cast_kind"
                          " CHECK (kind IN (1, 2, 3, 4, 5, 6) )" % table)


def remove_kind_constraint(apps, schema_editor):
    table = apps.get_model('stackoverflow', 'Cast')._meta.db_table
    schema_editor.execute("ALTER TABLE %s DROP CONSTRAINT check_cast_kind" % table)


class Migration(migrations.Migration):

    dependencies = [
        ('stackoverflow', '0003_auto_20171231_0526'),
    ]

    operations = [
        migrations.RunPython(add_kind_constraint, reverse_code=remove_kind_constraint)
    ]

然后是啊...你是100%安全的(支票不依赖于Django:现在掌握在数据库引擎的手中):

>>> c = Cast.objects.all().update(kind=70)
django.db.utils.IntegrityError: new row for relation "stackoverflow_cast" violates check constraint "check_cast_kind"
DETAIL:  Failing row contains (2, 1, 70, 1).

答案 1 :(得分:1)

在模型的保存方法中执行此操作:

<div class="wrap">
  
<div class="container">
<div class="half">
                    <div id="quarter1">
<a href=""><img class="photo" src="http://letsprattle.com/image/prattle-icon-square-white.png" class="" alt="" title=""></a>
                   
                    </div>    
                    <div id="quarter2">
<a href=""><img class="photo" src="http://yvonnemichaelides.com/wp-content/uploads/2016/01/clock2.gif" class="" alt="" title="" ></a>
                    </div>                    
</div>
<div class="half">
                    <div id="quarter3">
<a href=""><img class="photo" src="https://cdn.shopify.com/s/files/1/0387/1545/products/product_analysis_1024x1024.png?v=1426535435" class="" alt="" title="" ></a>
                    </div>    
                   <div id="quarter4">
<a href=""><img class="photo" src="http://www.northperthcommunityhospice.org/images/icons/calendar-icon.png" class="" alt="" title="" ></a>
                    </div>                   
</div>
</div>
</div>