327 votes

Comment obtenir l'objet s'il existe, ou None s'il n'existe pas dans Django ?

Lorsque je demande au gestionnaire de modèle d'obtenir un objet, il soulève la question suivante DoesNotExist lorsqu'il n'y a pas d'objet correspondant.

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

Au lieu de DoesNotExist comment puis-je avoir go être None à la place ?

5voto

blhsing Points 57682

Si vous voulez une solution simple en une ligne qui n'implique pas la gestion des exceptions, des instructions conditionnelles ou une exigence de Django 1.6+, faites plutôt ceci :

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

5voto

Mohammad Reza Points 129

Je pense que ce n'est pas une mauvaise idée d'utiliser 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)

Cet exemple est équivalent à :

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.")

Vous pouvez en savoir plus sur get_object_ou_404() dans la documentation en ligne de django.

2voto

À partir de django 1.7, vous pouvez faire comme suit :

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):
    ...

L'avantage de "MyQuerySet.as_manager()" est que les deux méthodes suivantes fonctionneront :

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

2voto

Il s'agit d'une copie de la méthode get_object_or_404 de Django, sauf que la méthode renvoie None. C'est extrêmement utile lorsque nous devons utiliser only() pour ne récupérer que certains champs. Cette méthode peut accepter un modèle ou un ensemble de requêtes.

from django.shortcuts import _get_queryset

def get_object_or_none(klass, *args, **kwargs):
    """
    Use get() to return an object, or return None if object
    does not exist.
    klass may be a Model, Manager, or QuerySet object. All other passed
    arguments and keyword arguments are used in the get() query.
    Like with QuerySet.get(), MultipleObjectsReturned is raised if more than
    one object is found.
    """
    queryset = _get_queryset(klass)
    if not hasattr(queryset, 'get'):
        klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__
        raise ValueError(
            "First argument to get_object_or_none() must be a Model, Manager, "
            "or QuerySet, not '%s'." % klass__name
        )
    try:
        return queryset.get(*args, **kwargs)
    except queryset.model.DoesNotExist:
        return None

1voto

Gary Points 826

Voici une variante de la fonction d'aide qui vous permet de passer facultativement dans un fichier QuerySet au cas où vous voudriez obtenir l'objet unique (s'il existe) à partir d'un ensemble de requêtes autre que celui du modèle. all d'objets queryset (par exemple, à partir d'un sous-ensemble d'éléments enfants appartenant à une instance parent) :

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

Cela peut être utilisé de deux manières, par exemple :

  1. obj = get_unique_or_none(Model, **kwargs) comme indiqué précédemment
  2. obj = get_unique_or_none(Model, parent.children, **kwargs)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X