2016-04-29 4 views
1

In meinem Django-Modell sollte nur ein Wert der Hauptwert sein, während der Rest optional ist.Wie kann nur einer Zeile ein bestimmter Feldwert zugewiesen werden?

In meinem Modell:

@with_author 
class BOMVersion(models.Model): 
    name = models.CharField(max_length=200,null=True, blank=True) 
    description = models.TextField(null=True, blank=True) 
    tomaterial = models.ForeignKey(Material, related_name = 'tomaterial') 

    status = models.CharField(max_length=1, choices=STATUS_CHOICES) 

BOM_CHOICES = (
    ('M','Main'), 
    ('A','Additional'), 
) 

Ich soll so dieses Modell mit Daten füllen kann, dass nur eine der Zeilen status den Wert Haupt haben, während der Rest immer Zusätzliche seine . (Es ist völlig die Radio-Button-Funktionalität, wenn nur Wert gewählt werden.)

Zum Beispiel:

1 v1 ...A 
2 v2 ...M 
3 v3 ...A 
......... 
n vn ...A 

ich mit einer Vermeidung des Problems kam, wo alle Werte hinzugefügt werden immer zusätzlich und wird über einen separaten haben Benutzeroberfläche mit einem Optionsfeld, in dem der Benutzer auswählen kann, welcher Wert der Hauptwert sein soll.

Aber fragte sich, gibt es eine Möglichkeit, diese Logik direkt auf ein Django-Modell anzuwenden?

+0

Ich bin mir nicht bewusst, eine Möglichkeit, es dem Modell hinzuzufügen, asside für das Testen in der Save-Methode. Sie könnten eine Bedingung eingeben, dass, wenn dieser Instanzstatus main ist, alle anderen Objekte in der Datenbank als zusätzliche Objekte aktualisiert werden. Sie müssen jedoch sicherstellen, dass Sie dort nicht in eine Endlosschleife geraten. – Shovalt

+0

Die Funktionalität der Formularelemente muss mit JavaScript implementiert und vorzugsweise in einem ModelForm-Objekt validiert werden. – Shovalt

Antwort

2

Wenn Ihre Datenbank dies unterstützt, ist ein partial unique index ein guter Ansatz. In PostgreSQL würde es in etwa so aussehen:

CREATE UNIQUE INDEX bom_constraint ON appname_bomversion (status) WHERE status = 'M'; 

Django noch nicht solche Indizes unterstützen, aber Sie können sie selbst hinzufügen, indem Sie eine Migration zu schaffen. Details finden Sie unter this answer.

Obwohl dies die Beschränkung auf der Datenbankebene erzwingt, wird es nicht magisch machen Ihre Formulare alles schön zu validieren. Aber es hört sich so an, als hätten Sie das schon auf der Formularebene angesprochen.

+0

Erstellt das wirklich eine Einschränkung, die verhindert, dass "M" in mehr als eine Zeile eingefügt wird? Die verknüpfte Dokumentation gibt nicht an, dass: "Der Index enthält Einträge nur für die Tabellenzeilen, die das Prädikat erfüllen. [...] Ein Hauptgrund für die Verwendung eines partiellen Index besteht darin, die Indizierung gemeinsamer Werte zu vermeiden." Die Beispiele zeigen deutlich, dass sie erwarten, dass mehr als 1 Wert indiziert wird. – Risadinha

+0

@Risadinha: Der Unterschied hier ist, dass die eindeutige Spalte die gleiche wie das Prädikat ist. Stellen Sie sich vor, Sie haben versucht, eine zweite Zeile mit 'status == M' hinzuzufügen. Da es das Prädikat erfüllt, müsste es indiziert werden. Wenn Sie versuchen, es dem Index hinzuzufügen, würde dies die Einschränkung, dass "status" für solche Zeilen eindeutig ist, verletzen. –

+0

Vielen Dank für die Erklärung! – Risadinha