如何获得该对象(如果存在)或“无”(如果不存在)?

问题:如何获得该对象(如果存在)或“无”(如果不存在)?

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

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

相反的DoesNotExist,我怎么能有go可以None代替?

When I ask the model manager to get an object, it raises DoesNotExist when there is no matching object.

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

Instead of DoesNotExist, how can I have go be None instead?


回答 0

没有“内置”方式可以做到这一点。Django每次都会引发DidNotExist异常。在python中处理此问题的惯用方式是将其包装在try catch中:

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

我所做的就是将模型.Manager子类化,创建safe_get类似于上面的代码,并将该经理用于我的模型。这样,您可以编写:SomeModel.objects.safe_get(foo='bar')

There is no ‘built in’ way to do this. Django will raise the DoesNotExist exception every time. The idiomatic way to handle this in python is to wrap it in a try catch:

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

What I did do, is to subclass models.Manager, create a safe_get like the code above and use that manager for my models. That way you can write: SomeModel.objects.safe_get(foo='bar').


回答 1

从Django 1.6开始,您可以像这样使用first()方法:

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

Since django 1.6 you can use first() method like so:

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

回答 2

来自Django文档

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

From django docs

get() raises a DoesNotExist exception if an object is not found for the given parameters. This exception is also an attribute of the model class. The DoesNotExist exception inherits from django.core.exceptions.ObjectDoesNotExist

You can catch the exception and assign None to go.

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

回答 3

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

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异常

You can create a generic function for this.

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

Use this like below:

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

go will be None if no entry matches else will return the Content entry.

Note:It will raises exception MultipleObjectsReturned if more than one entry returned for name="baby".

You should handle it on the data model to avoid this kind of error but you may prefer to log it at run time like this:

def get_or_none(classmodel, **kwargs):
    try:
        return classmodel.objects.get(**kwargs)
    except classmodel.MultipleObjectsReturned as e:
        print('ERR====>', e)

    except classmodel.DoesNotExist:
        return None

回答 4

您可以这样操作:

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

现在go变量可以是您想要的对象,也可以是None

参考:https : //docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first

You can do it this way:

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

Now go variable could be either the object you want or None

Ref: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first


回答 5

为了使事情变得更容易,以下是我编写的代码的片段,这些代码基于来自此处精彩答复的输入:

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()

To make things easier, here is a snippet of the code I wrote, based on inputs from the wonderful replies here:

class MyManager(models.Manager):

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

And then in your model:

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

That’s it. Now you have MyModel.objects.get() as well as MyModel.objetcs.get_or_none()


回答 6

您可以使用exists过滤器:

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

如果您只想知道它是否存在,则只是一个选择

you could use exists with a filter:

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

just an alternative for if you only want to know if it exists


回答 7

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

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

然后将其包含在内容模型类中

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

这样可以很容易地在视图中处理,即

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

Handling exceptions at different points in your views could really be cumbersome..What about defining a custom Model Manager, in the models.py file, like

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

and then including it in the content Model class

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

In this way it can be easily dealt in the views i.e.

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

回答 8

这是您可能不想重新实现的那些烦人的功能之一:

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

It’s one of those annoying functions that you might not want to re-implement:

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

回答 9

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

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

If you want a simple one-line solution that doesn’t involve exception handling, conditional statements or a requirement of Django 1.6+, do this instead:

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

回答 10

我认为使用它不是一个坏主意 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()的更多信息。

I think it isn’t bad idea to use 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)

This example is equivalent to:

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

You can read more about get_object_or_404() in django online documentation.


回答 11

从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()

From django 1.7 onwards you can do like:

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

The advantage of “MyQuerySet.as_manager()” is that both of the following will work:

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

回答 12

这是helper函数的一种变体QuerySet,如果您希望从除模型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)

Here’s a variation on the helper function that allows you to optionally pass in a QuerySet instance, in case you want to get the unique object (if present) from a queryset other than the model’s all objects queryset (e.g. from a subset of child items belonging to a parent instance):

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

This can be used in two ways, e.g.:

  1. obj = get_unique_or_none(Model, **kwargs) as previosuly discussed
  2. obj = get_unique_or_none(Model, parent.children, **kwargs)

回答 13

毫无exceptions:

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中使用异常有一些参数。一方面,“请求宽恕比允许更容易”。尽管我同意这一点,但我认为应该保留一个exceptions,这个exceptions,并且“理想情况”应该继续存在而不会碰到一个exceptions。

Without exception:

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

Using an exception:

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

There is a bit of an argument about when one should use an exception in python. On the one hand, “it is easier to ask for forgiveness than for permission”. While I agree with this, I believe that an exception should remain, well, the exception, and the “ideal case” should run without hitting one.


回答 14

我们可以使用Django内置异常,该异常附加到名为的模型上.DoesNotExist。因此,我们不必导入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

We can use Django builtin exception which attached to the models named as .DoesNotExist. So, we don’t have to import ObjectDoesNotExist exception.

Instead doing:

from django.core.exceptions import ObjectDoesNotExist

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

We can do this:

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

回答 15

这是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

This is a copycat from Django’s get_object_or_404 except that the method returns None. This is extremely useful when we have to use only() query to retreive certain fields only. This method can accept a model or a queryset.

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

回答 16

也许使用更好:

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

Maybe is better you use:

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