2009-03-03 12 views
19
class dbview(models.Model): 
    # field definitions omitted for brevity 
    class Meta: 
     db_table = 'read_only_view' 

def main(request): 
    result = dbview.objects.all() 

Gefangen eine Ausnahme beim Rendern anzuzeigen: (1054, "Unknown column 'read_only_view id' in 'field list'")Django: Querying schreibgeschützt ohne Primärschlüssel

ist es kein Primärschlüssel kann ich in der Ansicht sehen. Gibt es eine Problemumgehung?

Kommentar:
Ich habe keine Kontrolle über die Ansicht, die ich mit Django zugreife. Der MySQL-Browser zeigt dort Spalten, aber keinen Primärschlüssel.

Antwort

17

Wenn Sie sagen: ‚Ich habe keine Kontrolle über die Ansicht, die ich mit Django bin erreichbar. Der MySQL-Browser zeigt dort Spalten, aber keinen Primärschlüssel.

Ich nehme an, Sie meinen, dass dies eine Legacy-Tabelle ist und Sie nicht Spalten hinzufügen oder ändern dürfen?

Wenn ja und da ist wirklich kein Primärschlüssel (auch eine Zeichenfolge oder nicht-int-Spalte *) dann die Tabelle wurde nicht sehr gut eingerichtet und Leistung kann gut stinken.

Es ist Ihnen egal. Alles was Sie brauchen ist eine Spalte, die garantiert für jede Zeile eindeutig ist. Setze das in deinem Modell auf 'primary_key = True' und Django wird glücklich sein.

  • Es gibt eine andere Möglichkeit, die problematisch wäre. Wenn es keine Spalte gibt, die garantiert eindeutig ist, verwendet die Tabelle möglicherweise zusammengesetzte Primärschlüssel. Das heißt - es gibt an, dass zwei Spalten zusammen einen eindeutigen Primärschlüssel ergeben. Dies ist eine vollkommen gültige relationale Modellierung, die leider von Django nicht unterstützt wird. In diesem Fall können Sie außer Raw SQL nicht viel tun, es sei denn, Sie können eine weitere Spalte hinzufügen.
+0

Vielen Dank, das ist wirklich sehr hilfreich! – dmi

+0

Sehr hilfreich. Eine Sache hinzuzufügen; Wenn die Spalte, die Sie für einen Primärschlüssel verwenden möchten, ein CHAR-Typ ist, darf sie nicht länger als 255 Zeichen sein. –

+6

Dies betrifft nicht wirklich die Frage, die eine DB-Ansicht, keine Tabelle betrifft. Du hast eines deiner Felder als PK für Django angegeben, egal ob es das ist oder nicht. Sie können damit durchkommen, da es niemals ein Einfügen/Aktualisieren der Beziehung über das ORM geben wird. Siehe [die Antwort von David S] (http://stackoverflow.com/a/11594959/519015) und meinen Kommentar dazu für mehr über diese Technik. –

1

Es sollte ein automatisch generierter id Feld gewesen, wenn Sie syncdb lief (wenn es keinen Primärschlüssel in Ihrem Modell definiert ist, dann wird Django eine AutoField für Sie einfügen).

Dieser Fehler bedeutet, dass Django Ihre Datenbank nach dem Feld id fragt, aber keines existiert. Können Sie django manage.py dbshell und dann DESCRIBE read_only_view; ausführen und das Ergebnis veröffentlichen? Dadurch werden alle Spalten angezeigt, die sich in der Datenbank befinden.

Alternativ können Sie die Modelldefinition einschließen, die Sie ausgeschlossen haben? (Und bestätigen Sie, dass Sie die Modelldefinition geändert haben, seit Sie syncdb lief?)

+0

Danke, ich hätte es am Anfang deutlicher machen sollen. Bitte beachten Sie das Update. – dmi

+0

Ich möchte nicht die Zeile sehen, auf die Sie zugreifen, sondern nur Ihre Modelldefinition (nicht das Gleiche). – obeattie

+0

Die Modelldefinitionen sind wie folgt: text = models.CharField() Allerdings kann ich kein Feld mit 'primary_key = True' definieren, da die Ansicht keinen Primärschlüssel zu haben scheint. – dmi

3

Wenn es wirklich ist kein Primärschlüssel in der Ansicht, dann gibt es keine Abhilfe.

Django requires each model to have exactly one field primary_key=True.

+0

Danke! Wenn ich den Primärschlüssel in der Ansicht nicht sehen kann, bedeutet dies, dass kein Primärschlüssel vorhanden ist ...? Ich denke, ich werde einfach auf Raw SQL zurückgreifen. – dmi

+0

Nicht unbedingt. Siehe meinen Kommentar unten. –

12

Ich habe dieses Problem die ganze Zeit. Ich habe eine Ansicht, die ich nicht ändern kann oder will, aber ich möchte eine Seite haben, um zusammengesetzte Informationen anzuzeigen (vielleicht im Admin-Bereich). Ich überschreiben nur die sparen und einen NotImplementedError erhöhen:

def save(self, **kwargs): 
     raise NotImplementedError() 

(obwohl dies wahrscheinlich in den meisten Fällen nicht erforderlich ist, aber es macht mich ein bisschen besser fühlen)

ich auch auf False in der Meta verwalteten Set Klasse.

class Meta: 
     managed = False 

Dann wähle ich einfach ein beliebiges Feld aus und markiere es als Primärschlüssel. Es spielt keine Rolle, ob es wirklich einzigartig ist mit Ihnen tun nur Filter für die Anzeige von Informationen auf einer Seite, etc.

Scheint für mich gut zu funktionieren. Bitte komm, wenn es irgendwelche Probleme mit dieser Technik gibt, die ich übersehen habe.

+2

Sie können ein nicht eindeutiges Feld als Primärschlüssel für schreibgeschützten Zugriff kennzeichnen, dies hat jedoch Auswirkungen auf Dinge wie 'queryset.distinct(). Count()' und Instanzvergleiche. Als Workaround für Letzteres können Sie '__eq __()' im Modell neu definieren. –

+0

Etwas was Sie tun können, wenn Sie eine ID haben möchten, ist die Funktion 'row_number()' (zumindest in PostgreSQL). 'SELECT Zeilennummer() OVER (ORDER BY Feld ASC) AS ID,' – Bobort

Verwandte Themen