관리 메뉴

프로그래밍

[DRF] QuerySet과 Instance(error. AttributeError: 'NoneType' object has no attribute 'exists') 본문

Python/Django REST Framework

[DRF] QuerySet과 Instance(error. AttributeError: 'NoneType' object has no attribute 'exists')

시케 2024. 12. 19. 17:55
728x90
반응형

2024.12.19.목

QuerySet

QuerySet은 데이터베이스의 객체 목록을 나타내는 Django의 고유 데이터 구조이다

ORM으로 질의를 하게되면 QuerySet을 반환하는 것을 볼 수 있다

 

다만 지연로딩(lazy loading) 방식을 사용하기 때문에 데이터를 가져오는 때가 되어야만이 쿼리를 실행한다

# 데이터를 액세스하려고 할 때 (예: list(qs), for obj in qs, qs[0]) 쿼리가 실행
qs = MyModel.objects.filter(name="Example")  # 아직 쿼리 실행 X
for obj in qs:  # 여기서 쿼리 실행
    print(obj)

 

또한 QuerySet은 불변 객체처럼 작동한다

→ 기존의 QuerySet을 변경하지 않고 항상 새로운 QuerySet 반환

Model 인스턴스

인스턴스라는 표현대로 객체이다

Django 모델에서 DB 데이터를 Python 객체로 다룰 수 있게 한 것이다

QuerySet과 Model 인스턴스

그럼 어느때는 QuerySet이고 어느때는 Model 인스턴스일까?

 

답은 개수에 있다

ORM 쿼리의 결과가 여러 개일 가능성이 있을 경우에는 QuerySet을 반환한다

다만 반드시 하나일 경우에는 Model 인스턴스를 반환한다

 

※ 답이 하나라고 반드시 인스턴스인 것은 아니다

여러 개일 가능성만 있으면 QuerySet 반환된다

# QuerySet인 경우
qs = MyModel.objects.filter(name="Alice")
qs = MyModel.objects.all()
qs = MyModel.objects.exclude(name="Alice")
qs = MyModel.objects.order_by('name')
qs = MyModel.objects.distinct('name')
# 인스턴스 반환할 경우
obj = MyModel.objects.get(id=1)				# 없으면 DoesNotExist Error 많으면 MultipleObjectsReturned Error
obj = MyModel.objects.filter(name="Alice").first()	# 없으면 None
obj = MyModel.objects.filter(name="Alice").last()	# 없으면 None

Exists와 is None 혼용 시 에러

Queryset과 인스턴스 조회 후 존재하는지 확인하는 로직 또한 자주 사용한다

이때 Queryset인지 혹은 인스턴스인지에 따라 사용하는 메서드가 다르다

 

Queryset

Queryset에 is None 사용시 항상 False를 반환한다

Queryset이 비었는지 확인하기 위해서는 exists() 를 사용해야 한다

qs = MyModel.objects.filter(name="Nonexistent")
if qs is None:
    print("QuerySet is None")  # 이 조건은 절대 참이 되지 않음

# 특정 조건에 맞는 객체가 존재하는지 확인
if qs.exists():
    print("객체가 존재합니다.")
else:
    print("객체가 존재하지 않습니다.")

Model 인스턴스

인스턴스 객체가 비어있는지 확인할때는 is None을 사용해야 한다

인스턴스 객체에 exists() 메서드를 사용할 경우 AttributeError가 발생한다

해당 오류는 어찌보면 당연한 결과이다

exists() 메서드는 QuerySet이 가지고 있는 메서드이지 인스턴스 객체는 해당 메서드를 가지고 있지 않기 때문이다

# 특정 조건에 맞는 첫 번째 객체가 None인지 확인
obj = MyModel.objects.filter(name="Alice").first()
if obj is None:
    print("객체가 존재하지 않습니다.")
else:
    print(f"객체가 존재합니다: {obj.name}")

if obj.exists():  # AttributeError 발생
    print("Object exists")

 

728x90
반응형
Comments