如果对象存在,如何获取对象,如果不存在则为None?

时间:2010-06-22 04:38:42

标签: python django

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

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

而不是DoesNotExist,我如何让go成为None

19 个答案:

答案 0 :(得分:260)

没有'内置'的方法来做到这一点。 Django每次都会引发DoesNotExist异常。 在python中处理这个问题的惯用方法是将它包装在try catch中:

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

我做了什么,是继承models.Manager,创建一个safe_get,就像上面的代码一样,并将该经理用于我的模型。这样你就可以写:SomeModel.objects.safe_get(foo='bar')

答案 1 :(得分:130)

从django 1.6开始,您可以使用first()方法,如下所示:

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

答案 2 :(得分:28)

From django docs

  如果找不到给定参数的对象,

get()会引发DoesNotExist异常。此异常也是模型类的属性。 DoesNotExist例外情况继承自django.core.exceptions.ObjectDoesNotExist

您可以捕获异常并指定None去。

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

答案 3 :(得分:26)

您可以为此创建一个通用函数。

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

使用如下所示:

go = get_or_none(Content,name="baby")
如果没有条目匹配,

go将为None,否则将返回Content条目。

注意:如果为name =“baby”返回了多个条目,它将引发异常MultipleObjectsReturned

答案 4 :(得分:12)

为了简化操作,以下是我编写的代码片段,基于此处精彩回复的输入:

class MyManager(models.Manager):

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

然后在你的模型中:

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

就是这样。 现在你有MyModel.objects.get()以及MyModel.objetcs.get_or_none()

答案 5 :(得分:12)

你可以这样做:

go  = Content.objects.filter(name="baby").first()

现在go变量可以是你想要的对象,也可以是无

参考:APIdock

答案 6 :(得分:11)

您可以将exists与过滤器结合使用:

Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
如果您只想知道它是否存在,

只是一种替代方案

答案 7 :(得分:7)

在视图中的不同点处理异常真的很麻烦。在models.py文件中定义自定义模型管理器,如

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

然后将其包含在内容Model类

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

通过这种方式,可以很容易地在视图中处理,即

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

答案 8 :(得分:7)

您可能不想重新实施的annoying functions之一:

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

答案 9 :(得分:3)

如果您想要一个不涉及异常处理,条件语句或Django 1.6+要求的简单单行解决方案,请改为:

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

答案 10 :(得分:2)

我认为使用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)

此示例相当于:

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

您可以在django在线文档中阅读有关 get_object_or_404() 的更多信息。

答案 11 :(得分:1)

从django 1.7开始你可以这样做:

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

“MyQuerySet.as_manager()”的优点是以下两个都可以使用:

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

答案 12 :(得分:1)

我也面临着同样的问题。像@Arthur Debert的答案一样,每次要从模型中获取元素时,都很难编写和读取try-except。因此,我的解决方案是创建一个由模型继承的Getter类:

class Getter:
    @classmethod
    def try_to_get(cls, *args, **kwargs):
        try:
            return cls.objects.get(**kwargs)
        except Exception as e:
            return None

class MyActualModel(models.Model, Getter):
    pk_id = models.AutoField(primary_key=True)
    ...

通过这种方式,我可以获得MyActualModelNone的实际元素:

MyActualModel.try_to_get(pk_id=1)

答案 13 :(得分:1)

也许最好使用:

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

答案 14 :(得分:1)

我们可以使用附加到名为.DoesNotExist的模型的Django内置异常。因此,我们不必导入ObjectDoesNotExist例外。

相反做:

from django.core.exceptions import ObjectDoesNotExist

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

我们可以这样做:

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

答案 15 :(得分:1)

毫无例外:

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中使用异常,有一点争论。一方面,“要求宽恕比获得许可更容易”。虽然我同意这一点,但我认为应该保留一个例外情况,例外情况,并且“理想情况”应该在不触及的情况下运行。

答案 16 :(得分:1)

这里有一个帮助函数的变体,它允许您可选地传入QuerySet实例,以防您想要从模型以外的查询集中获取唯一对象(如果存在)&#39 ; s all对象查询集(例如,来自属于父实例的子项的子集):

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

这可以通过两种方式使用,例如:

    正如所讨论的
  1. obj = get_unique_or_none(Model, **kwargs)
  2. obj = get_unique_or_none(Model, parent.children, **kwargs)

答案 17 :(得分:0)

这是Django的get_object_or_404的模仿者,只是该方法返回None。当我们必须使用#!/usr/bin/env node const fs = require('fs'); const program = require('commander'); require('colors'); program .version('0.1.0') .option('--project [project]', 'Specifies the project name', 'mono') .option('--type [type]', 'Type of code to generate, either "item" or "config"', /^(config|item)$/, 'config') .option('--title [title]', 'Title of the item or config', 'untitled') .option('--comments [comments]', 'Configs: describe the config', '@todo description/comments') .option('--write', 'Write the source code to a new file in the expected path') .option('--read', 'To see what would be written the source code to a new file in the expected path') .parse(process.argv); console.log(program.write, program.read); //=> undefined undefined 查询仅检索某些字段时,这非常有用。此方法可以接受模型或查询集。

only()

答案 18 :(得分:0)

我使用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

views中,您可以这样调用:

SUser.objects.get_if_exist(id=1)