当我要求模型管理器获取一个对象时,当没有匹配的对象时,它会引发DoesNotExist。

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

而不是DoesNotExist,我怎么能去是None代替?


当前回答

没有例外:

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

使用异常:

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

关于在python中什么时候应该使用异常有一点争论。一方面,“请求原谅比请求允许容易”。虽然我同意这一点,但我认为应该保留一个异常,好吧,异常,并且“理想情况”应该运行而不碰到异常。

其他回答

我使用的是Django 2.2.16。这就是我解决这个问题的方法:

from typing import Any

from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.db.models.base import ModelBase
from django.db.models.manager import Manager


class SManager(Manager):
    def get_if_exist(self, *args: Any, **kwargs: Any):
        try:
            return self.get(*args, **kwargs)
        except ObjectDoesNotExist:
            return None


class SModelBase(ModelBase):
    def _prepare(cls):
        manager = SManager()
        manager.auto_created = True
        cls.add_to_class("objects", manager)

        super()._prepare()

    class Meta:
        abstract = True


class SModel(models.Model, metaclass=SModelBase):
    managers = False

    class Meta:
        abstract = True

之后,在每个模型中,你只需要导入:

from custom.models import SModel


class SUser(SModel):
    pass

在视图中,你可以这样调用:

SUser.objects.get_if_exist(id=1)

这是Django get_object_or_404方法的一个副本,只是该方法返回None。当我们必须使用only()查询来只检索某些字段时,这是非常有用的。该方法可以接受模型或查询集。

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

这是一个讨厌的函数,你可能不想重新实现:

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

来自django docs

如果没有找到给定参数的对象,get()将引发一个DoesNotExist异常。这个异常也是模型类的一个属性。DoesNotExist异常继承自django.core.exceptions.ObjectDoesNotExist

您可以捕获异常并将None指定为go。

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

如果你想要一个简单的单行解决方案,不涉及异常处理、条件语句或Django 1.6+的要求,可以这样做:

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