web-dev-qa-db-fra.com

Django: Obtenir un objet de la base de données, ou 'Aucun' si rien ne correspond

Existe-t-il une fonction Django qui me permette d'obtenir un objet de la base de données ou Aucune si rien ne correspond?

En ce moment, j'utilise quelque chose comme:

foo = Foo.objects.filter(bar=baz)
foo = len(foo) > 0 and foo.get() or None

Mais ce n'est pas très clair et c'est un désordre d'avoir partout.

94
David Wolever

Dans Django 1.6 , vous pouvez utiliser la méthode first() Queryset. Il retourne le premier objet correspondant au queryset, ou None s'il n'y a pas d'objet correspondant.

Usage:

p = Article.objects.order_by('title', 'pub_date').first()
84
Cesar Canassa

Il y a deux façons de faire ça;

try:
    foo = Foo.objects.get(bar=baz)
except model.DoesNotExist:
    foo = None

Ou vous pouvez utiliser un wrapper:

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

Appelez ça comme ça

foo = get_or_none(Foo, baz=bar)
136
Nick Craig-Wood

Pour ajouter un exemple de code à la réponse de sorki (j'ajouterais cela sous forme de commentaire, mais il s'agit de mon premier message et je n'ai pas assez de réputation pour laisser des commentaires), j'ai mis en place un gestionnaire personnalisé get_or_none comme suit:

from Django.db import models

class GetOrNoneManager(models.Manager):
    """Adds get_or_none method to objects
    """
    def get_or_none(self, **kwargs):
        try:
            return self.get(**kwargs)
        except self.model.DoesNotExist:
            return None

class Person(models.Model):
    name = models.CharField(max_length=255)
    objects = GetOrNoneManager()

Et maintenant je peux faire ça:

bob_or_none = Person.objects.get_or_none(name='Bob')
81
kaapstorm

Vous pouvez également essayer d'utiliser Django ennuyeux (il a une autre fonction utile!)

installez-le avec:

pip install Django-annoying

from annoying.functions import get_object_or_None
get_object_or_None(Foo, bar=baz)
13
llazzaro

Donnez Foo son gestionnaire personnalisé . C'est assez facile - il suffit de mettre votre code en fonction dans le gestionnaire personnalisé, de définir le gestionnaire personnalisé dans votre modèle et de l'appeler avec Foo.objects.your_new_func(...).

Si vous avez besoin d’une fonction générique (pour l’utiliser sur n’importe quel modèle et pas seulement avec un gestionnaire personnalisé), écrivez la vôtre et placez-la quelque part sur votre chemin python, puis importez-la.

9
sorki

Que vous le fassiez via un gestionnaire ou une fonction générique, vous pouvez également capturer 'MultipleObjectsReturned' dans l'instruction TRY, car la fonction get () le soulève si votre kwargs récupère plusieurs objets.

Construire sur la fonction générique:

def get_unique_or_none(model, *args, **kwargs):
    try:
        return model.objects.get(*args, **kwargs)
    except (model.DoesNotExist, model.MultipleObjectsReturned), err:
        return None

et dans le manager:

class GetUniqueOrNoneManager(models.Manager):
    """Adds get_unique_or_none method to objects
    """
    def get_unique_or_none(self, *args, **kwargs):
        try:
            return self.get(*args, **kwargs)
        except (self.model.DoesNotExist, self.model.MultipleObjectsReturned), err:
            return None
4
emispowder