[django] 장고 필터 대 단일 객체 얻기?

나는 동료들과 이것에 대해 토론하고 있었다. 장고에서 객체를 하나만 기대할 때 선호하는 방법이 있습니까?

두 가지 확실한 방법은 다음과 같습니다.

try:
    obj = MyModel.objects.get(id=1)
except MyModel.DoesNotExist:
    # We have no object! Do something...
    pass

과:

objs = MyModel.objects.filter(id=1)

if len(objs) == 1:
    obj = objs[0]
else:
    # We have no object! Do something...
    pass

첫 번째 방법은 동작이 더 정확 해 보이지만 제어 흐름에서 예외를 사용하여 오버 헤드가 발생할 수 있습니다. 두 번째는 더 우회하지만 예외는 발생하지 않습니다.

이 중 어느 쪽이 바람직한 지 생각하십니까? 어느 것이 더 효율적입니까?



답변

get()이 경우에 특별히 제공됩니다 . 그걸 써.

옵션 2는 거의 get()장고에서 메소드가 실제로 구현 되는 방식과 거의 동일 하므로 “성능”차이가 없어야합니다 (생각하고 있다는 사실은 프로그래밍의 기본 규칙 중 하나를 위반한다는 것을 나타냅니다. 코드를 작성하고 프로파일 링하기 전에 코드를 최적화하십시오. 코드를 가지고 실행할 수있을 때까지 코드의 성능을 모르고 그 전에 최적화를 시도하는 것이 고통의 경로입니다).


답변

django-annoying 이라는 모듈을 설치 한 후 다음을 수행 할 수 있습니다 .

from annoying.functions import get_object_or_None

obj = get_object_or_None(MyModel, id=1)

if not obj:
    #omg the object was not found do some error stuff


답변

1이 맞습니다. 파이썬에서 예외는 리턴과 동일한 오버 헤드를 갖습니다. 간단한 증명을 위해 이것을 볼 수 있습니다 .

2 장고가 백엔드에서하는 일입니다. 항목이 없거나 둘 이상의 개체가있는 경우 예외를 get호출 filter하고 발생시킵니다.


답변

나는 파티에 조금 늦었지만 장고 1.6에는 first()쿼리 세트에 대한 방법이 있습니다.

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


쿼리 세트와 일치하는 첫 번째 개체를 반환하거나 일치하는 개체가 없으면 None을 반환합니다. QuerySet에 순서가 정의되어 있지 않으면 기본 키에 의해 쿼리 세트가 자동으로 정렬됩니다.

예:

p = Article.objects.order_by('title', 'pub_date').first()
Note that first() is a convenience method, the following code sample is equivalent to the above example:

try:
    p = Article.objects.order_by('title', 'pub_date')[0]
except IndexError:
    p = None


답변

Django의 경험으로 말할 수는 없지만 옵션 # 1은 시스템에 하나의 객체를 요구하고 있지만 두 번째 옵션은 그렇지 않다는 것을 분명히 알려줍니다. 이는 옵션 # 1이 캐시 또는 데이터베이스 인덱스를보다 쉽게 ​​활용할 수 있음을 의미합니다. 특히 필터링하는 속성이 고유하지 않은 경우에 특히 그렇습니다.

또한 두 번째 옵션은 filter () 호출이 일반적으로 많은 행을 리턴 할 수 있기 때문에 일종의 결과 콜렉션 또는 반복자 오브젝트를 작성해야 할 수도 있습니다. get ()으로 이것을 무시할 것입니다.

마지막으로 첫 번째 옵션은 짧고 여분의 임시 변수를 생략합니다. 약간의 차이 만 있지만 모든 작은 도움이됩니다.


답변

왜 모든 것이 작동합니까? 4 줄을 하나의 내장 단축키로 바꿉니다. (이것은 자체 시도 / 제외를 수행합니다.)

from django.shortcuts import get_object_or_404

obj = get_object_or_404(MyModel, id=1)


답변

예외에 대한 추가 정보. 그들이 자라지 않으면 거의 비용이 들지 않습니다. 따라서 결과가 나올 것이라는 것을 알고 있다면 예외를 사용하십시오. 조건식을 사용하면 무엇이든 상관없이 매번 검사 비용을 지불하기 때문입니다. 반면에, 그것들은 그들이 올라올 때 조건식보다 약간 더 비쌉니다. 따라서 어떤 빈도 (예 : 메모리가 제공되는 경우 30 %의 시간)로 결과를 기대하지 않으면 조건부 검사가 나타납니다 조금 더 저렴합니다.

그러나 이것은 장고의 ORM이며 아마도 데이터베이스로의 왕복 또는 캐시 된 결과가 성능 특성을 지배 할 가능성이 높 으므로이 경우 가독성을 선호하십시오 get(). 정확히 하나의 결과를 기대하기 때문에를 사용하십시오 .