Update 3 (zuerst lesen):Django: ein generisches (content_type) Feldes mit einem realen Objekt Einstellung setzt es auf None
Ja, dies wurde durch das Objekt „Profil“ verursacht nicht gespeichert wurde. Für diejenigen, die die gleichen Symptome haben, lautet die Moral "Wenn ein ForeignKey-Feld auf" None "gesetzt wird, wenn Sie ihm ein reales Objekt zuweisen, liegt das wahrscheinlich daran, dass diese anderen Objekte nicht gespeichert wurden."
Auch wenn Sie 100% sicher sind, dass es gespeichert wurde, klicken Sie hier ;-)
Hallo,
Ich verwende content_type/generic Fremdschlüssel in einer Klasse in Django.
Die Linie eine Instanz der Klasse zu erstellen, ist in etwa so:
tag = SecurityTag(name='name',agent=an_agent,resource=a_resource,interface=an_interface)
Wo beiden Mittel und Ressourcen sind content_type Felder aus.
Meistens funktioniert das so, wie ich es erwarte und erschafft das passende Objekt. Aber ich habe einen speziellen Fall, in dem ich diese Zeile anrufe, um einen SecurityTag zu erstellen, aber der Wert des Agentenfelds scheint am Ende wie Kein zu enden.
Jetzt, in diesem speziellen Fall, teste ich in der vorhergehenden Zeile, dass der Wert von an_agent ein vorhandenes, gespeichertes Django.model-Objekt eines Agententyps enthält. Und es tut es.
Der resultierende SecurityTag-Datensatz wird jedoch mit None für dieses Feld ausgegeben.
Ich bin davon ziemlich verblüfft. Ich vermute, dass irgendwo in der Leitung etwas fehlschlägt, wenn der ORM versucht, die ID des Objekts in an_agent zu extrahieren, aber es wird weder eine Fehlermeldung noch eine Exception ausgelöst. Ich habe überprüft, dass das Objekt an_agent gespeichert ist und einen Wert in seinem ID-Feld hat.
Wer hat so etwas gesehen? Oder haben Sie irgendwelche Ideen?
====
Update: 10 Tage später genau das gleiche Bug mich in einen neuen Kontext wieder zu beißen ist gekommen:
einige Code Hier ist die die „Sicherheitsetikett“ Objekt beschreibt, das ist im Grunde eine Abbildung zwischen
a) einer Art von permission-Rolle (bekannt als "Agent" in unserem System), das eine generische content_type ist,
b) eine Ressource, die auch eine generische content_type ist, (und Im aktuellen Problem wird ein Pin vergeben ax "Profil"),
und c) eine "Schnittstelle" (was im Grunde eine Art von Zugriff ist ... z. „Sichtbarer“ oder „Editierbare“, die nur eine Zeichenfolge ist)
class SecurityTag(models.Model) :
name = models.CharField(max_length='50')
agent_content_type = models.ForeignKey(ContentType,related_name='security_tag_agent')
agent_object_id = models.PositiveIntegerField()
agent = generic.GenericForeignKey('agent_content_type', 'agent_object_id')
interface = models.CharField(max_length='50')
resource_content_type = models.ForeignKey(ContentType,related_name='security_tag_resource')
resource_object_id = models.PositiveIntegerField()
resource = generic.GenericForeignKey('resource_content_type', 'resource_object_id')
Zu einem bestimmten Zeitpunkt später, ich dies tun:
print "before %s, %s" % (self.resource,self.agent)
t = SecurityTag(name=self.tag_name,agent=self.agent,resource=self.resource,interface=self.interface_id)
print "after %s, %s, %s, %s" % (t.resource,t.resource_content_type,type(t.resource),t.resource_object_id)
Das Ergebnis davon ist, dass vor, die „Ressource“ Variable bedeutet Referenz ein Profil, aber nach ...
before phil, TgGroup object
after None, profile, <type 'NoneType'>, None
Mit anderen Worten, während der Wert von t.resource_content_type auf „Profil“ gesetzt wurde, ist alles andere Keine. In meiner vorherigen Begegnung mit diesem Problem habe ich es "gelöst", indem ich das Ding, das ich dem generischen Typ zuweisen wollte, neu lade. Ich fange an mich zu fragen, ob dies eine Art von ORM-Cache-Problem ist ... ist die Variable "self.resource" mit einem netten Proxy-Objekt statt der realen Sache?
Eine Möglichkeit ist, dass das Profil nicht gespeichert wurde. Dieser Code wird jedoch als Ergebnis eines after_save-Signals für das Profil aufgerufen. (Es setzt Standardberechtigungen), könnte es also sein, dass die Profilspeicherung nicht festgeschrieben wurde oder so?
Update 2: unter folgenden Matthew Vorschlag, fügte ich
print self.resource._get_pk_value() and self.resource.id
das Profil der Luft gejagt hat sagen _get_pk_value nicht hat()
Dies ist eindeutig ein Fehler, nicht beabsichtigtes Verhalten, und um ehrlich zu sein, es ist viel eher ein Fehler in Ihrem Code als in Django (obwohl letzteres sicherlich möglich ist). Daher denke ich, dass nützliche Antworten schwer zu bekommen sind, wenn Sie nicht den gesamten relevanten Code veröffentlichen (oder mit einem Pastebin-Dump verknüpfen) können. –
Können Sie die Datei "self.resource._get_pk_value()" und "self.resource.id" zur Druckanweisung "before" hinzufügen und die Frage mit den Ergebnissen bearbeiten? Wenn der erste zurückkehrt, kann ich aus irgendeinem Grund nicht verstehen, warum dies geschieht. –
Brilliant! Matthew, du hattest Recht. Das zeigte, dass das Objekt nicht wirklich gespeichert wurde. Was mich wiederum auf einen Fehler hinwies. Wenn Sie eine Antwort geben, werde ich Ihnen den Bonus gewähren. – interstar