2017-12-31 41 views
0

Ich habe folgendes Modell in django zu modellieren:Django Daten beschränken, das Feld gegeben werden kann

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')}") 

Aber ich will das Feld ‚Art‘ nur eine der folgenden Werte annehmen: oben, unten, seltsame , Charme, oben oder unten. Wie kann ich dies in der Datenbank erzwingen oder kann dies nur in den Ansichten erzwungen werden, wenn Daten aufgenommen werden?

Antwort

0

Ich denke choices tun soll?

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") 
     ) 
    ) 

Obwohl in vielen Gelegenheiten habe ich es als SmallInteger gesehen haben Platz in der Datenbank zu speichern: In der DB speichern Sie eine Nummer ein, und in Ihrem Admin-Bereich finden Sie ein Drop-Down mit dem Abschnitt " menschenfreundliche "Entscheidungen.

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

See:

Choices in action

Dies wird nicht auf DB-Ebene erzwungen (siehe this ticket und diese SO question), die Sie immer noch bedeutet, tun können:

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

aber Es wird im Admin erzwungen. Wenn Sie es auf einer niedrigeren Ebene erzwingen wollen, schlage ich vor, Sie gehen mit Noah Lc's answer. Soweit ich verstehe, ist dies nicht zu 100% erzwungen: Sie können weiterhin Bulk-Updates durchführen, die nicht die .save()-Methode des Modells durchlaufen, was bedeutet, dass Cast.objects.all().update(kind=70) immer noch einen ungültigen Wert (70) im Feld kind einstellt, aber seine Lösung ist in der Tat ein Schritt "niedriger" als die Entscheidungen. Sie können keine Modellaktualisierungen durchführen, die die Methode .save() der Instanz durchlaufen. Das heißt, Sie werden es nicht erlaubt sein zu tun:

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

Wenn Sie REAL Datenbank Durchsetzung tun müssen, müssen Sie tatsächlich Ihre Datenbanken die Möglichkeiten überprüfen und eine Einschränkung für die cast.kind Spalte hinzuzufügen.

Zum Beispiel für Postgres (und wahrscheinlich auch für die meisten anderen SQL-Aromen) Sie könnten eine neue Migration erstellen, die dies taten:

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) 
    ] 

Und dann ja ... Sie 100% gesichert werden würde (Die Überprüfung hängt nicht von Django ab: jetzt liegt in den Händen Ihrer Datenbank-Engine):

>>> 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). 
0

Sie es in Ihrer Methode des Modells speichern:

def save(self, *args, **kwargs): 
    mylist = ['up', 'down', 'strange', 'charm',....] 
    if slef.kind in mylist: 
     super(Foo, self).save(*args, **kwargs) 
    else: 
     raise Exception, "kind take only one of the following values: up, down, strange, charm,...." 
Verwandte Themen