Ich habe zwei Modelle wie dieses:
class Type1Profile(models.Model):
user = models.OneToOneField(User, unique=True)
...
class Type2Profile(models.Model):
user = models.OneToOneField(User, unique=True)
...
Ich muss etwas tun, wenn der Benutzer ein Profil vom Typ 1 oder Typ 2 hat:
if request.user.type1profile != None:
# do something
elif request.user.type2profile != None:
# do something else
else:
# do something else
Für Benutzer, die weder Typ1- noch Typ2-Profile haben, führt die Ausführung eines solchen Codes jedoch zu folgendem Fehler:
Type1Profile matching query does not exist.
Wie kann ich den Profiltyp eines Benutzers überprüfen?
Vielen Dank
python
django
django-models
one-to-one
John Bright
quelle
quelle
select_related()
jetzt oder in Zukunft damit arbeiten möchten - oder vielleicht sogar sicher sein möchten, dass Sie auch mit anderen Arten von Magie umgehen, die anderswo auftreten können - müssen Sie den Test wie folgt erweitern:if hasattr(object, 'onetoonerevrelattr') and object.onetoonerevrelattr != None
hasattr
verschluckt werden , die während der Datenbanksuche auftreten, und nicht nur . Dies ist wahrscheinlich kaputt und nicht das, was Sie wollen.DoesNotExist
Sie können feststellen, ob eine nullfähige Eins-zu-Eins-Beziehung für ein bestimmtes Modell null ist, indem Sie einfach das entsprechende Feld im Modell auf
None
Ness testen , aber nur, wenn Sie das Modell testen, aus dem die Eins-zu-Eins-Beziehung stammt. Zum Beispiel angesichts dieser beiden Klassen…… Um zu sehen, ob a ein
Restaurant
hatPlace
, können wir den folgenden Code verwenden:Um zu sehen, ob a eine
Place
hatRestaurant
, ist es wichtig zu verstehen, dass das Referenzieren derrestaurant
Eigenschaft auf eine Instanz vonPlace
eineRestaurant.DoesNotExist
Ausnahme auslöst, wenn es kein entsprechendes Restaurant gibt. Dies geschieht, weil Django intern eine Suche durchführtQuerySet.get()
. Beispielsweise:In diesem Szenario herrscht Occams Rasiermesser vor, und der beste Ansatz, um festzustellen, ob a ein
Place
hat oder nicht,Restautrant
wäre ein Standardtry
/except
Konstrukt, wie hier beschrieben .Während der Vorschlag von joctee,
hasattr
in der Praxis zu arbeiten, tatsächlich nur zufällig funktioniert, werden alle Ausnahmen (einschließlich ) im Gegensatz zu nur shasattr
unterdrückt , wie es sollte. Wie Pi Delport betonte, wurde dieses Verhalten in Python 3.2 gemäß dem folgenden Ticket tatsächlich korrigiert: http://bugs.python.org/issue9666 . Außerdem - und auf die Gefahr hin opinionated - ich glaube , das oben / Konstrukt ist repräsentativ dafür , wie Django funktioniert, während der Verwendung kann das Problem für Neulinge Wolke, die FUD und Verbreitung schlechten Gewohnheiten können erstellen.DoesNotExist
AttributeError
try
except
hasattr
BEARBEITEN Don Kirkbys vernünftiger Kompromiss erscheint mir ebenfalls vernünftig.
quelle
Ich mag Joctees Antwort , weil es so einfach ist.
Andere Kommentatoren haben Bedenken geäußert, dass es mit bestimmten Versionen von Python oder Django möglicherweise nicht funktioniert, aber die Django-Dokumentation zeigt diese Technik als eine der Optionen:
Natürlich zeigt die Dokumentation auch die Ausnahmefangtechnik:
Ich stimme Joshua zu, dass das Fangen der Ausnahme klarer macht, was passiert, aber es scheint mir nur chaotischer. Vielleicht ist das ein vernünftiger Kompromiss?
Dies ist nur die Abfrage der
Restaurant
Objekte nach Ort. Es kehrt zurück,None
wenn dieser Ort kein Restaurant hat.Hier ist ein ausführbares Snippet, mit dem Sie mit den Optionen spielen können. Wenn Sie Python, Django und SQLite3 installiert haben, sollte es nur ausgeführt werden. Ich habe es mit Python 2.7, Python 3.4, Django 1.9.2 und SQLite3 3.8.2 getestet.
quelle
Wie wäre es mit Try / Except-Blöcken?
Dann verwenden Sie so!
Ich nehme an, Sie könnten dies als generische Funktion verwenden, um eine umgekehrte OneToOne-Instanz zu erhalten, wenn eine Ursprungsklasse (hier: Ihre Profilklassen) und eine verwandte Instanz (hier: request.user) angegeben sind.
quelle
Verwenden Sie
select_related
!quelle
RelatedObjectDoesNotExist
.falls Sie das Modell haben
Und Sie müssen nur für jeden Benutzer wissen, ob UserProfile vorhanden ist oder nicht - der aus Sicht der Datenbank effizienteste Weg , eine vorhandene Abfrage zu verwenden .
Die vorhandene Abfrage gibt nur einen booleschen Wert zurück und nicht den umgekehrten Attributzugriff wie
hasattr(request.user, 'type1profile')
dies. Dadurch wird eine Abfrage generiert und eine vollständige Objektdarstellung zurückgegebenDazu müssen Sie dem Benutzermodell eine Eigenschaft hinzufügen
quelle
Ich verwende eine Kombination aus has_attr und ist None:
quelle
Einer der intelligenten Ansätze wird hinzuzufügen benutzerdefiniertes Feld OneToOneOrNoneField und verwendet es [Werke für Django> = 1.9]
Implementierung
Verwendung
quelle
SingleRelatedObjectDescriptor
anstattReverseOneToOneDescriptor
wie diesefrom django.db.models.fields.related import SingleRelatedObjectDescriptor