[python] Django : DB에서 객체를 얻거나 일치하는 것이 없으면 ‘None’

데이터베이스에서 객체를 얻을 수있는 Django 함수가 있습니까? 아니면 아무것도 일치하지 않으면 None?

지금은 다음과 같은 것을 사용하고 있습니다.

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

그러나 그것은 그다지 명확하지 않으며 모든 곳에있는 것이 지저분합니다.



답변

Django 1.6 에서는 다음을 사용할 수 있습니다.first() Queryset 메서드를 . 쿼리 셋과 일치하는 첫 번째 개체를 반환하거나 일치하는 개체가 없으면 None을 반환합니다.

용법:

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


답변

이를 수행하는 두 가지 방법이 있습니다.

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)


답변

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


답변

django를 귀찮게 사용해 볼 수도 있습니다 (다른 유용한 기능이 있습니다!).

다음과 함께 설치하십시오.

pip install django-annoying

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


답변

Foo 에게 맞춤 관리자를 제공합니다 . 매우 쉽습니다. 사용자 지정 관리자의 함수에 코드를 넣고 모델에 사용자 지정 관리자를 설정 한 다음Foo.objects.your_new_func(...) .

일반 함수가 필요한 경우 (사용자 지정 관리자가 아닌 모든 모델에서 사용) 직접 작성하고 Python 경로에 배치하고 더 이상 지저분하지 않게 가져옵니다.


답변

관리자 또는 일반 함수를 통해 수행하든, kwargs가 둘 이상의 객체를 검색하면 get () 함수가이를 발생시키기 때문에 TRY 문에서 ‘MultipleObjectsReturned’를 포착 할 수도 있습니다.

일반 기능을 기반으로 구축 :

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


답변

다음 QuerySet은 모델의 all객체 쿼리 셋이 아닌 쿼리 셋 (예 : 상위 인스턴스) :

def get_unique_or_none(model, queryset=None, *args, **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(*args, **kwargs)
    except model.DoesNotExist:
        return None

두 가지 방법으로 사용할 수 있습니다. 예 :

  1. obj = get_unique_or_none(Model, *args, **kwargs) 앞서 논의했듯이
  2. obj = get_unique_or_none(Model, parent.children, *args, **kwargs)