Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django:从数据库中获取对象,或';无';如果没有匹配_Python_Django - Fatal编程技术网

Python Django:从数据库中获取对象,或';无';如果没有匹配

Python Django:从数据库中获取对象,或';无';如果没有匹配,python,django,Python,Django,是否有任何Django函数可以让我从数据库中获取对象,或者如果没有匹配的对象,则没有 现在我用的是这样的东西: foo = Foo.objects.filter(bar=baz) foo = len(foo) > 0 and foo.get() or None 但这还不是很清楚,到处都是,这很混乱。有两种方法可以做到这一点 try: foo = Foo.objects.get(bar=baz) except model.DoesNotExist: foo = None

是否有任何Django函数可以让我从数据库中获取对象,或者如果没有匹配的对象,则没有

现在我用的是这样的东西:

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

但这还不是很清楚,到处都是,这很混乱。

有两种方法可以做到这一点

try:
    foo = Foo.objects.get(bar=baz)
except model.DoesNotExist:
    foo = None
或者您可以使用包装器:

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

foo = get_or_none(Foo, baz=bar)
给福。这很简单-只需将代码放入自定义管理器的函数中,在模型中设置自定义管理器,并使用
Foo.objects.your_new_func(…)
调用它即可


如果您需要泛型函数(在任何模型上使用它,而不仅仅是在自定义管理器上),请编写自己的函数,并将其放置在python路径上的某个位置进行导入,不再凌乱。

要在sorki的答案中添加一些示例代码(我会将其作为注释添加,但这是我的第一篇文章,我没有足够的声誉留下注释),我实现了一个get_or_none自定义管理器,如下所示:

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()
现在我可以做到:

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

无论是通过管理器还是泛型函数执行此操作,您可能还希望在TRY语句中捕获“multipleObjectsReturn”,因为如果kwargs检索到多个对象,get()函数将引发此问题

基于通用功能:

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

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

在Django1.6中,可以使用
first()
Queryset方法。它返回queryset匹配的第一个对象,如果没有匹配的对象,则返回None

用法:

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

您也可以尝试使用django(它还有另一个有用的功能!)

安装时请使用:

pip install django-annoying

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

以下是helper函数的一个变体,允许您有选择地传入
QuerySet
实例,以防您希望从模型的
all
objects QuerySet以外的QuerySet(例如,从属于父实例的子项的子集)获取唯一对象(如果存在):

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

  • obj=get\u unique\u或\u none(Model,*args,**kwargs)
    如前所述
  • obj=get\u unique\u或\u none(Model、parent.children、*args、**kwargs)

  • 我认为在大多数情况下,您可以使用:

    foo, created = Foo.objects.get_or_create(bar=baz)
    

    只有当在Foo表中添加一个新条目并不重要时(其他列将具有None/默认值)

    我不喜欢它对功能使用异常的事实-这在大多数语言中都是一种不好的做法。这在python中是如何实现的?这就是python迭代的工作方式(引发StopIteration),这是该语言的核心部分。我也不是try/except功能的超级粉丝,但它似乎被认为是python的。@pcv:“大多数”语言都没有可靠的传统智慧。我想你会考虑一些你碰巧使用的特定语言,但要小心使用这些量词。异常可以和Python中的任何东西一样慢(或“足够快”)。回到问题上来——这是框架的一个缺点,在1.6之前,他们没有提供任何
    queryset
    方法来实现这一点!但对于这个结构来说,它只是笨拙。这不是“邪恶”,因为你最喜欢的语言的一些教程作者这样说。试试谷歌:“请求原谅而不是允许”。@TomaszGandor:是的,不管你最喜欢的语言教程怎么说,它都很笨拙,很难阅读。当我看到一个异常时,我认为发生了一些不标准的事情。可读性很重要。但是我同意当没有其他合理的选择时,你应该去做,不会有什么不好的事情发生。@pcv
    get
    方法不应该返回
    None
    ,因此异常是有意义的。您应该在确定对象将在那里/对象“应该”在那里的情况下使用它。同样,使用这样的异常也被认为是“好的”,因为它是有意义的。您需要一个具有不同协定的
    get
    ,因此您可以捕获异常并抑制它,这是您所追求的更改。您知道您可以使用foo=foo[0]如果foo-else-NonePython有一个三元运算符,则不必使用布尔运算符。另外,:“注意:如果您只想确定集合中的记录数,就不要在QuerySet上使用len()。使用SQL的SELECT count()在数据库级别处理计数要高效得多,Django正是出于这个原因提供了count()方法。”。重写:
    foo=foo[0]如果foo.exists(),则没有
    可能重复的@mustafa.0x,我认为这不适用于这里。在这里,检查计数将运行另一个查询。然后我们需要再次查询以获得实际数据。在这种情况下,过滤和计数会更有意义。。。但这并不比过滤和调用
    first()
    :p这不是一个好的答案,如果找到多个对象,则不会引发
    MultipleObjectsReturned()
    。你可以找到更好的答案@sleepycal我不同意。
    first()。它返回查询结果中的第一个对象,不关心是否找到多个结果。如果需要检查返回的多个对象,则应使用
    .get()
    。[编辑]正如OP所说,
    .get()
    不适合他的需要。这个问题的正确答案可以在下面的@kaapstorm中找到,显然是更合适的答案。滥用
    filter()
    这种方式可能会导致意外后果,OP可能没有意识到(除非我在这里遗漏了什么)@sleepycal这种方法会产生什么意外后果?如果您的数据库约束不能正确管理对象之间的唯一性,然后,您可以遇到逻辑预期只有一个对象(由first()选择)但实际上存在多个对象的边缘情况。使用get()而不是first()可以通过提升
    多个对象return()
    为您提供额外的保护层。如果返回的结果为n
    foo, created = Foo.objects.get_or_create(bar=baz)