410 Stimmen

Wie erhalte ich das Objekt, wenn es existiert, oder None, wenn es in Django nicht existiert?

Wenn ich den Modelmanager bitte, ein Objekt zu erhalten, wird DoesNotExist ausgelöst, wenn kein passendes Objekt vorhanden ist.

go = Content.objects.get(name="baby")

Anstatt DoesNotExist, wie kann ich stattdessen go None haben?

24voto

Moti Radomski Punkte 255

Um es einfacher zu machen, hier ist ein Ausschnitt des Codes, den ich basierend auf den wunderbaren Antworten hier geschrieben habe:

class MyManager(models.Manager):

    def get_or_none(self, **kwargs):
        try:
            return self.get(**kwargs)
        except ObjectDoesNotExist:
            return None

Und dann in Ihrem Modell:

class MyModel(models.Model):
    objects = MyManager()

Das war's. Jetzt haben Sie MyModel.objects.get() sowie MyModel.objetcs.get_or_none()

8 Stimmen

Auch nicht vergessen zu importieren: from django.core.exceptions import ObjectDoesNotExist

1 Stimmen

Oder außer self.model.DoesNotExist, um den Import zu vermeiden.

19voto

Ryan Saxe Punkte 16089

Sie könnten exists mit einem Filter verwenden:

Content.objects.filter(name="baby").exists()
# gibt False oder True zurück, je nachdem, ob sich etwas in der QS befindet

Nur eine Alternative, wenn Sie nur wissen möchten, ob es existiert

4 Stimmen

Das würde einen zusätzlichen Datenbankaufruf verursachen, wenn er existiert. Keine gute Idee.

0 Stimmen

@Christoffer bin nicht sicher, warum das ein zusätzlicher Datenbankaufruf wäre. Laut den Dokumenten: Hinweis: Wenn Sie nur feststellen möchten, ob mindestens ein Ergebnis vorhanden ist (und die tatsächlichen Objekte nicht benötigen), ist es effizienter, exists() zu verwenden.

3 Stimmen

@Christoffer Ich denke, du hast recht. Ich lese die Frage jetzt noch einmal und der OP möchte tatsächlich, dass das tatsächliche Objekt zurückgegeben wird. Also wird exists() mit einer if-Klausel verwendet, bevor das Objekt abgerufen wird und dadurch einen doppelten Treffer in der Datenbank verursacht. Ich werde den Kommentar trotzdem stehen lassen, falls er jemand anderem hilft.

11voto

mknecht Punkte 1125

Es ist eine dieser ärgerlichen Funktionen, die Sie möglicherweise nicht erneut implementieren möchten:

from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")

1 Stimmen

Ich habe den Code von get_object_or_None überprüft, aber festgestellt, dass es immer noch MultipleObjectsReturned auslöst, wenn mehr als ein Objekt vorhanden ist. Daher sollte der Benutzer möglicherweise eine try-except-Konstruktion in Betracht ziehen (obwohl die Funktion selbst bereits über ein try-except verfügt).

9voto

Jonathan Souza Punkte 81

Vielleicht ist es besser, wenn du dies benutzt:

User.objects.filter(username=admin_username).exists()

2 Stimmen

Das Problem dabei ist, dass der Benutzer zwischen dieser Zeile und der Zeile, an der er tatsächlich abgerufen wird, gelöscht wird.

8voto

Adil Malik Punkte 8420

Das Bearbeiten von Ausnahmen an verschiedenen Stellen in Ihren Ansichten könnte wirklich umständlich sein.. Was ist mit der Definition eines benutzerdefinierten Model Managers in der models.py-Datei, wie zum Beispiel

class ContentManager(model.Manager):
    def get_nicely(self, **kwargs):
        try:
            return self.get(kwargs)
        except(KeyError, Content.DoesNotExist):
            return None

und dann fügen Sie es der content Model-Klasse hinzu

class Content(model.Model):
    ...
    objects = ContentManager()

Auf diese Weise kann es in den Ansichten leicht behandelt werden, z.B.

post = Content.objects.get_nicely(pk = 1)
if post:
    # Mach etwas
else:
    # Dieser Beitrag existiert nicht

2 Stimmen

Ich mag diese Lösung wirklich, konnte sie aber nicht so zum Laufen bringen, wenn ich Python 3.6 verwendet habe. Wollte einen Hinweis hinterlassen, dass die Änderung des Rückgabewerts im ContentManager zu return self.get(**kwargs) dazu geführt hat, dass es bei mir funktioniert hat. Nicht dass etwas mit der Antwort falsch wäre, nur ein Tipp für alle, die versuchen, es mit späteren Versionen zu verwenden (oder mit allem anderen, das mich daran gehindert hat, es zum Laufen zu bringen).

0 Stimmen

Jetzt in Python 3.12 und Django 5 und es funktioniert immer noch, mit dem Update aus dem vorherigen Kommentar.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X