본문 바로가기
데이터베이스(SQL)/데이터베이스 개념

[DB] Django의 Filter 및 ORM과 참조 개념 정리

by char_lie 2023. 4. 16.
반응형

Django에서 filter + SQL 쿼리(ORM) 사용 방법

CREATE

-- SQL
CREATE TABLE "user_account" (
  "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "user_account" varchar(10) NOT NULL,
  "password" varchar(30) NOT NULL,
  "created_at" datetime NOT NULL,
  "updated_at" datetime NOT NULL
);

↓ ↓ ↓ ↓ ↓

# Djago ORM
class Account(models.Model):
    user_account = models.CharField(max_length=10)
    password = models.CharField(max_length=30)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'user_account'

SELECT

-- SQL
SELECT * FROM user_account;

↓ ↓ ↓ ↓ ↓

accounts = Account.objects.all()

for account in accounts:
  	print(account.user_account)
    print(account.password)
    print(account.created_at)
    print(account.updated_at)

Where

SELECT * FROM Account
WHERE user_account='abc';

↓ ↓ ↓ ↓ ↓

Account.objects.filter(user_account='abc')

exists()

DB에서 filter를 통해 원하는 조건의 데이터 유무에 따라 True, False를 반환하는 메서드

get()

  • queryset이 아닌 모델 객체를 반환하는 함수
  • 특정 칼럼 조건에 해당하는 결과를 객체로 변화하는 함수로 찾는 결과가 없다면 DoesNotExist에러 발생

Django에서 DB 사용하기 (게시판)

  • 모델 관계 설정하기(1: N, N:M)
  • 게시글과 댓글의 경우 N:1 관계 (게시글 1, 댓글 N)
  • Comment의 id가 Article의 id를 참조하도록 관계 설정

Django Relationship fields 종류

  • OneToOneField() (1:1 관계)
  • ForeignKey() (N:1 관계)
    • 2개의 필수 위치 인자가 필요함 (Model class, on_delete 옵션)
    • on_delete CASCADE : 부모 객체(참조된 객체)가 삭제됐을 때 이를 참조하는 객체도 삭제하는 것
  • ManyToManyField() (N:M 관계)

역참조

  • django는 모델 간 N:1이나 N:M 관계가 설정되면 역참조 할 때 사용할 수 있는 manager를 생성
  • 본인을 외래키로 참조 중인 다른 테이블에 접근하는 것
  • N:1의 경우 외래키를 가지지 않는 1이 외래키를 가진 N을 참조
class Person(models.Model)
	name = models.CharField(max_length=20)
    
class Dog(models.Model)
	owner = models.ForeignKey(Person)
  name = models.CharField(max_length=20)

# 개 -> 사람으로 참조하는 것은 정참조 (개가 사람의 외래키)
# 사람 -> 개로 참조하는 것은 역참조 (외래키 속성이 아닌 객체(사람) 에서 관계된 모델 참조(개)
  • 참조하기 위해서는 set manager를 사용함 (Person.dog_set.all())
  • 역참조 시 사용하는 매니저 이름을 변경하는 related_name을 사용하는 방법 (M:N 관계에서도 사용 가능)
class Person(models.Model)
	name = models.CharField(max_length=20)
    
class Dog(models.Model)
	owner = models.ForeignKey(Person, related_name='dogs')
  name = models.CharField(max_length=20)

# related_name 작성 후 migration 과정 필요
# 위처럼 변경시 set manager 사용 불가

Django에서 User 모델을 참조하는 방법

  • setting.AUTH_USER_MOEL 사용
    • 반환 값은 accounts.User(문자열)
    • models.py의 모델 필드에서 User 모델 참조할 때 사용
  • get_user_model() 사용
    • 반환 값은 User Object(객체)
    • model.py가 아닌 다른 모든 곳에서 유저 모델 참조 시 사용

Django에서의 M:N 관계

  • M:N 관계로 맺어진 두 테이블에는 변화 없음
  • django의 ManyToManyField는 M:N 관계를 맺는 두 모델 어디에 위치해도 상관없으나 정참조, 역참조 방향에 주의
  • add()
    • 지정된 객체를 객체 집합에 추가하는 기능
    • 이미 존재하는 관계에 사용하면 관계 복제 x
    • 모델 인스턴스, 필드 값(PK)을 인자로 허용함
  • remove()
    • 관련 객체 집합에서 지정된 모델 개체를 제거
    • 내부적으로 QuerySet.delete()를 이용하여 관계 삭제
    • 모델 인스턴스, 필드 값(PK)을 인자로 허용함

Django ORM

  • 장점
    • SQL문이 아닌 클래스의 메서드를 통해 데이터베이스를 조작할 수 있음
    • SQL의 절차/순차적 접근 방식과 달리 객체지향적 접근만 고려하면 되기에 생산성 증가
    • 재사용, 유지보수, 리팩토링이 용이함
    • 객체의 자료형 타입까지 사용할 수 있기 때문에 DBMS의 종속성 하락
  • 단점
    • 복잡한 SQL문을 ORM만으로 모든 걸 해결할 수 없음(적절하게 SQL문 사용)
    • 복잡한 쿼리문의 경우 SQL문이 오히려 직관적이고 효율적일 수 있음

Lazy-loading

  • Django의 ORM은 Lazy-loading(지연로딩) 방식 사용
  • 명령을 실행할 때마다 DB에 접근하여 데이터를 가져오는 것이 아닌 실제 데이터를 불러와야 할 때 DB Query문을 실행하는 방식
  • 객체 코드로 다루는 모든 경우에 호출하는 것은 비용이 매우 많이 드는 작업이므로 성능 개선 효과
  • N+1 query 문제가 발생함

Eager-loading

  • Lazy-loading의 반대 개념으로 즉시 로딩
  • 지금 당장 사용하지 않을 데이터도 포함하여 Query문을 실행하기 때문에 Lazy-loading의 N+1 문제의 해결을 위해 많이 사용
  • select_realted(정참조)와 prefertch_realted(역참조) 메서드를 사용

N+1 Query 문제

Lazy-loading의 성능이슈인 N+1 Query 문제는 외래키를 참조해서 데이터를 가져올 때 발생

캐싱

  • ORM을 이용해서 가져온 데이터는 캐싱
  • 특정 데이터를 불러온 후 재사용할 경우 ORM은 저장해 둔 캐싱 사용
  • 불러온 데이터 변화를 일으키는 쿼리가 아니라면 저장해 둔 데이터 사용
반응형

댓글