2010-06-22 15 views

Antwort

168

Es gibt keine "eingebaute" Möglichkeit, dies zu tun. Django löst die DoesNotExist-Ausnahme jedes Mal aus. Der idiomatische Weg, dies in Python zu handhaben ist es in einem Try-Catch-wrap:

try: 
    go = SomeModel.objects.get(foo='bar') 
except SomeModel.DoesNotExist: 
    go = None 

Was ich tat, ist models.Manager Unterklasse, ein safe_get wie der obigen Code erstellen und diese Manager für meine Modelle. Auf diese Weise können Sie schreiben: SomeModel.objects.safe_get(foo='bar').

+5

+1 für das Abfangen der spezifischen Ausnahme. –

+6

Nette Verwendung von SomeModel.DoesNotExist, anstatt die Ausnahme auch zu importieren. – Symmitchry

+102

Diese Lösung ist vier Zeilen lang. Für mich ist das zu viel. Mit django 1.6 können Sie 'SomeModel.objects.filter (foo = 'bar') verwenden. First()' gibt die erste Übereinstimmung oder None zurück. Es schlägt nicht fehl, wenn es mehrere Instanzen wie 'querieset.get()' gibt. – guettli

23

From django docs

get() wirft eine DoesNotExist Ausnahme, wenn ein Objekt nicht für die gegebenen Parameter zu finden ist. Diese Ausnahme ist auch ein Attribut der Modellklasse. Die DoesNotExist Ausnahme erbt von django.core.exceptions.ObjectDoesNotExist

Sie die Ausnahme abfangen können, und weisen None zu gehen.

from django.core.exceptions import ObjectDoesNotExist 
try: 
    go = Content.objects.get(name="baby") 
except ObjectDoesNotExist: 
    go = None 
17

Sie können hierfür eine generische Funktion erstellen.

def get_or_none(classmodel, **kwargs): 
    try: 
     return classmodel.objects.get(**kwargs) 
    except classmodel.DoesNotExist: 
     return None 

verwenden wie unten:

go = get_or_none(Content,name="baby") 

go Keine sein wird, wenn kein Eintrag sonst passt die Inhalte Eintrag zurückzukehren.

Hinweis: Es wird wirft MultipleObjectsReturned Ausnahme, wenn mehr als ein Eintrag für name = „baby“ zurück

6

Handhabung Ausnahmen an verschiedenen Punkten in Ihre Ansichten wirklich cumbersome..What über das Definieren eines benutzerdefinierten Model Manager sein könnte, in die models.py Datei, wie

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

und darunter dann im Content-Modell-Klasse

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

auf diese Weise es eas sein kann ily gehandelt wird die Ansichten

dh
post = Content.objects.get_nicely(pk = 1) 
if post: 
    # Do something 
else: 
    # This post doesn't exist 
+0

Ich mag diese Lösung, aber war nicht in der Lage, es zur Arbeit zu bekommen wie bei Python 3.6. Wollte eine Notiz hinterlassen, dass die Rückkehr in den ContentManager zu 'return self.get (** kwargs)' hat es für mich arbeiten lassen. Um nicht zu sagen, dass mit der Antwort etwas falsch ist, nur ein Tipp für jeden, der versucht, es mit späteren Versionen zu verwenden (oder mit allem anderen, was es davon abhält, für mich zu arbeiten). – skagzilla

9

Dinge einfacher zu machen, hier ein Ausschnitt des Codes I, hier auf Eingaben von den wunderbaren Antworten basierend schrieb:

class MyManager(models.Manager): 

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

Und dann im Modell:

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

Das ist es. Jetzt haben Sie MyModel.objects.get() sowie MyModel.objetcs.get_or_none()

+4

auch, vergessen Sie nicht zu importieren: von django.core.exceptions importieren ObjectDoesNotExist –

8

Sie exists mit einem Filter verwenden:

Content.objects.filter(name="baby").exists() 
#returns False or True depending on if there is anything in the QS 

nur eine Alternative für, wenn Sie wollen nur wissen, ob es

+1

Das würde einen zusätzlichen Datenbankaufruf verursachen, wenn vorhanden. Keine gute Idee – Christoffer

1

existiert Hier ist eine Variation der Hilfefunktion, die Ihnen erlaubt, übergeben Sie optional eine QuerySet Instanz, falls Sie das eindeutige Objekt (falls vorhanden) von einem anderen als dem all Objekt-Queryset des Modells abfragen möchten (z. B. aus einer Untergruppe von untergeordneten Objekten, die zu einer übergeordneten Instanz gehören):

def get_unique_or_none(model, queryset=None, **kwargs): 
    """ 
     Performs the query on the specified `queryset` 
     (defaulting to the `all` queryset of the `model`'s default manager) 
     and returns the unique object matching the given 
     keyword arguments. Returns `None` if no match is found. 
     Throws a `model.MultipleObjectsReturned` exception 
     if more than one match is found. 
    """ 
    if queryset is None: 
     queryset = model.objects.all() 
    try: 
     return queryset.get(**kwargs) 
    except model.DoesNotExist: 
     return None 

Dies kann auf zwei Arten genutzt werden, zum Beispiel:

  1. obj = get_unique_or_none(Model, **kwargs) als previosuly
  2. obj = get_unique_or_none(Model, parent.children, **kwargs)
  3. diskutiert
+0

Ich sehe, dass 'Django nerving' bereits diesen Fall behandelt. – Gary

76

Seit django 1.6 Sie können first() Methode, wie so verwenden:

Content.objects.filter(name="baby").first() 
+10

In diesem Fall wird kein Fehler ausgelöst, wenn mehrere Übereinstimmungen vorhanden sind. –

+1

Ich mag diese Lösung, denn wenn wir 'objecst.get()' verwenden, wissen wir, dass es in der Datenbank entweder eine oder keine gibt. – EmptyFlash

+2

'FeroxTL' müssen Sie @guettli für diese Antwort gutschreiben, wie er dies ein Jahr vor Ihrer Post auf die angenommene Antwort kommentierte. – colminator

1

Ohne Ausnahme:

if SomeModel.objects.filter(foo='bar').exists(): 
    x = SomeModel.objects.get(foo='bar') 
else: 
    x = None 

Mit einer Ausnahme:

try: 
    x = SomeModel.objects.get(foo='bar') 
except SomeModel.DoesNotExist: 
    x = None 

Es ist ein bisschen ein Argument, wenn man eine Ausnahme in Python verwenden sollte. Auf der einen Seite "ist es leichter, um Vergebung als um Erlaubnis zu bitten". Obwohl ich damit einverstanden bin, glaube ich, dass eine Ausnahme bleiben sollte, nun, die Ausnahme, und der "Idealfall" sollte laufen, ohne einen zu treffen.

1

Von django 1.7 ab können Sie tun:

class MyQuerySet(models.QuerySet): 

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


class MyBaseModel(models.Model): 

    objects = MyQuerySet.as_manager() 


class MyModel(MyBaseModel): 
    ... 

class AnotherMyModel(MyBaseModel): 
    ... 

Der Vorteil von "MyQuerySet.as_manager()" ist, dass beide der folgenden arbeiten:

MyModel.objects.filter(...).get_or_none() 
MyModel.objects.get_or_none() 
7

Es ist einer von denen, annoying functions, die Sie vielleicht nicht neu implementieren wollen:

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

Wir Django builtin Ausnahme, die verwenden ein tached zu den Modellen, die als .DoesNotExist benannt werden. Also müssen wir ObjectDoesNotExist Exception nicht importieren.

Stattdessen tun:

from django.core.exceptions import ObjectDoesNotExist 

try: 
    content = Content.objects.get(name="baby") 
except ObjectDoesNotExist: 
    content = None 

Wir können dies tun:

try: 
    content = Content.objects.get(name="baby") 
except Content.DoesNotExist: 
    content = None 
2

Wenn Sie eine einfache einzeilige Lösung wollen, die nicht die Ausnahmebehandlung, bedingte Anweisungen oder eine Anforderung von Django 1.6+ mit sich bringt, dies zu tun, statt:

x = next(iter(SomeModel.objects.filter(foo='bar')), None) 
1

Ich denke, es isn ‚schlechte Idee t get_object_or_404()

from django.shortcuts import get_object_or_404 

def my_view(request): 
    my_object = get_object_or_404(MyModel, pk=1) 

Verwendung dieses Beispiels entspricht:

from django.http import Http404 

def my_view(request): 
    try: 
     my_object = MyModel.objects.get(pk=1) 
    except MyModel.DoesNotExist: 
     raise Http404("No MyModel matches the given query.") 

Sie können mehr über get_object_or_404() in Django Online-Dokumentation lesen.

Verwandte Themen