단일 개체에 대한 .filter() vs.get()? (장고)
저는 몇몇 동료들과 이것에 대해 토론하고 있었습니다.하나만 예상할 때 장고에서 객체를 검색하는 선호하는 방법이 있습니까?
두 가지 분명한 방법은 다음과 같습니다.
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이 맞습니다.Python에서 예외는 반환과 동일한 오버헤드를 가집니다.간단한 증거를 위해 이것을 볼 수 있습니다.
입니다.2 Django 백가서니 작는다 업입하 수행엔 에이드 것이▁2. get
출들filter
항목을 찾을 수 없거나 둘 이상의 개체를 찾을 경우 예외를 발생시킵니다.
, 1 에조늦만었금지장파, 에고는 1.6티가 .first()
쿼리 세트의 메서드입니다.
https://docs.djangoproject.com/en/dev/ref/models/querysets/ #django.db.models.query.QuerySet.first
쿼리 집합과 일치하는 첫 번째 개체를 반환하거나 일치하는 개체가 없으면 없음을 반환합니다.쿼리 세트에 순서가 정의되지 않은 경우 쿼리 세트는 기본 키에 의해 자동으로 순서가 지정됩니다.
예:
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
왜 그게 다 효과가 있는 거지?4개의 선을 하나의 내장된 바로 가기로 바꿉니다.(이것은 자체적으로 시도/제외를 수행합니다.)
from django.shortcuts import get_object_or_404
obj = get_object_or_404(MyModel, id=1)
나는 장고의 경험으로 말할 수 없지만 옵션 #1은 시스템에 당신이 1개의 객체를 요청한다고 분명히 말하지만, 두 번째 옵션은 그렇지 않습니다.이는 특히 필터링 중인 특성이 고유하지 않은 경우 옵션 #1이 캐시 또는 데이터베이스 인덱스를 보다 쉽게 활용할 수 있음을 의미합니다.
또한 필터() 호출이 일반적으로 많은 행을 반환할 수 있기 때문에 두 번째 옵션은 일종의 결과 수집 또는 반복기 개체를 만들어야 할 수도 있습니다.get()을 사용하여 이를 무시할 수 있습니다.
마지막으로, 첫 번째 옵션은 더 짧고 추가적인 임시 변수를 생략합니다. - 작은 차이지만 모든 작은 도움이 됩니다.
예외에 대한 추가 정보입니다.만약 그것들을 키우지 않는다면, 그것들은 거의 비용이 들지 않습니다.따라서 결과가 나올 것이라는 것을 알고 있다면 예외를 사용하십시오. 조건식을 사용하면 어떤 일이 있어도 매번 확인 비용을 지불하기 때문입니다.반면에, 그것들을 올릴 때, 조건식보다 약간 더 많은 비용이 들기 때문에, 만약 당신이 어떤 빈도(예를 들어, 메모리가 사용된다면, 30%)로 결과를 기대하지 않는다면, 조건식 검사는 약간 더 저렴한 것으로 밝혀집니다.
그러나 이것은 Django의 ORM이며, 아마도 데이터베이스로의 왕복 또는 캐시된 결과가 성능 특성을 지배할 가능성이 높기 때문에 가독성을 선호합니다. 정확히 하나의 결과를 기대하기 때문에, 이 경우,get()
.
이 문제를 조금 해결해 본 결과 옵션 2가 두 개의 SQL 쿼리를 실행한다는 것을 알게 되었습니다. 이는 단순한 작업에 비해 과도한 것입니다.내 주석 보기:
objs = MyModel.objects.filter(id=1) # This does not execute any SQL
if len(objs) == 1: # This executes SELECT COUNT(*) FROM XXX WHERE filter
obj = objs[0] # This executes SELECT x, y, z, .. FROM XXX WHERE filter
else:
# we have no object! do something
pass
단일 쿼리를 실행하는 동등한 버전은 다음과 같습니다.
items = [item for item in MyModel.objects.filter(id=1)] # executes SELECT x, y, z FROM XXX WHERE filter
count = len(items) # Does not execute any query, items is a standard list.
if count == 0:
return None
return items[0]
이 접근 방식으로 전환함으로써 애플리케이션이 실행하는 쿼리 수를 크게 줄일 수 있었습니다.
.get()
필드 룩업에 설명된 형식으로 지정된 룩업 매개 변수와 일치하는 개체를 반환합니다.
get()은 MultipleObjects를 발생시킵니다. 둘 이상의 개체가 발견된 경우 반환됩니다.MultipleObjectsReturned 예외는 모델 클래스의 특성입니다.
get()은 지정된 매개 변수에 대한 개체를 찾을 수 없는 경우 DoesNotException을 발생시킵니다.이 예외는 모델 클래스의 특성이기도 합니다.
.filter(필터)
지정된 조회 매개 변수와 일치하는 개체를 포함하는 새 QuerySet을 반환합니다.
메모
단일 고유 개체를 가져오려면 get()을 사용하고, 조회 매개 변수와 일치하는 모든 개체를 가져오려면 filter()를 사용합니다.
흥미로운 질문이지만, 나에게 있어 #2 옵션은 시기상조 최적화의 냄새가 납니다.어느 것이 더 성능이 좋은지는 모르겠지만, 옵션 #1은 확실히 저에게 더 비단결처럼 보이고 느껴집니다.
저는 다른 디자인을 제안합니다.
가능한 결과에 대해 함수를 수행하려면 QuerySet에서 다음과 같이 파생할 수 있습니다. http://djangosnippets.org/snippets/734/
결과는 매우 훌륭합니다. 예를 들어 다음과 같습니다.
MyModel.objects.filter(id=1).yourFunction()
여기서 필터는 빈 쿼리 세트 또는 단일 항목이 있는 쿼리 세트를 반환합니다.사용자 지정 쿼리 집합 기능도 체인으로 연결하여 재사용할 수 있습니다.항목에 합니다.MyModel.objects.all().yourFunction()
.
또한 관리 인터페이스에서 작업으로 사용하는 것이 이상적입니다.
def yourAction(self, request, queryset):
queryset.yourFunction()
옵션 1이 더 우아하지만 try를 사용해야 합니다.제외하고.
제 경험에 따르면 데이터베이스에 일치하는 개체가 둘 이상 있을 수 없다고 확신할 수 있습니다. 하지만 두 개가 있을 것입니다.(물론 기본 키로 객체를 가져오는 경우는 제외).
이 문제에 대한 테이크를 한 번 더 추가해서 죄송합니다만, 저는 장고 페이지 관리자를 사용하고 있으며, 제 데이터 관리 앱에서는 사용자가 쿼리할 대상을 선택할 수 있습니다.때로는 문서의 ID이지만, 그렇지 않으면 둘 이상의 오브젝트(즉, 쿼리 집합)를 반환하는 일반 쿼리입니다.
사용자가 ID를 쿼리하면 다음을 실행할 수 있습니다.
Record.objects.get(pk=id)
django의 페이지 관리자에 오류를 발생시킵니다. 이는 django가 레코드 집합이 아니라 레코드이기 때문입니다.
실행해야 합니다.
Record.objects.filter(pk=id)
하나의 항목이 들어 있는 쿼리 집합을 반환합니다.그러면 페이지 관리자가 잘 작동합니다.
".get"은 다음과 같은 개체를 반환할 수 있습니다.
{
"name": "John",
"age": "26",
"gender": "Male"
}
".filter"는 하나 이상의 개체 목록(세트)을 ** 반환할 수 있습니다.
[
{
"name": "John",
"age": "26",
"gender": "Male"
},
{
"name": "Tom",
"age": "18",
"gender": "Male"
},
{
"name": "Marry",
"age": "22",
"gender": "Female"
}
]
언급URL : https://stackoverflow.com/questions/1018886/filter-vs-get-for-single-object-django
'programing' 카테고리의 다른 글
사용자 지정 라이브러리 구성 요소는 알려진 요소가 아니지만 앱이 컴파일 및 실행됩니다. (0) | 2023.07.05 |
---|---|
Firebase 전자 메일 확인이 스팸 폴더로 이동합니다. (0) | 2023.07.05 |
파이어베이스 분석을 처음 보고하는 데 시간이 얼마나 걸립니까? (0) | 2023.06.30 |
쿼리에서 스프링 데이터 사용 OR (0) | 2023.06.30 |
Vue.set /Vue.delete 대신 Vue.js 스프레드 연산자 (0) | 2023.06.30 |