반응형
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은 저장해 둔 캐싱 사용
- 불러온 데이터 변화를 일으키는 쿼리가 아니라면 저장해 둔 데이터 사용
반응형
'데이터베이스(SQL) > 데이터베이스 개념' 카테고리의 다른 글
[DB] 데이터베이스 정규화 & 참조 무결성 정리 (0) | 2023.04.16 |
---|---|
[DB]관계형 데이터베이스 정리 & DDL, DML, JOIN 사용 정리 (0) | 2023.04.16 |
댓글