ORM

sihwan_e·2021년 6월 5일
0

Django

목록 보기
19/21

ORM

Django ORM Cookbook
링크텍스트

ORM (Object Relational Mapping)
Django는 여러 종류의 데이터를 DB의 것 과는 다른 독립적인 형태로 객체화 한다.
그리고 생성된 객체에 상호 작용할 수 있는 메서드 세트를 제공한다.
Model Class를 통해 객체를 만들고, 그 객체를 통해 DB에 접근한다.

데이터 베이스의 종류가 다르면 각 필드 데이터 타입에 대해 저마다 다르게 작동한다. 어떤 개발자는 SQLite3, 어떤 개발자는 PostgreSQL을 운영 환경에서 이용할 때 장고 ORM이 이 두 데이터베이스 간의 차이에 대해 처리해준다. 그래도 문제는 생기지만.

Query

Query표현식의 장점

from models.customers import Customer

customer = []
for customer in Customer.objects.iterate():
	if customer.sccopps_ordered > customer.store_visits:
    	customers.append(customer

데이터베이스 안의 모든 고객 레코드에 대해 하나하나 파이썬을 이용한 루프가 돌고 있기때문에 느리며, 메모리도 많이 이용한다. 코드 자체가 경합 상황(race condition: 공유 자원에 대해 여러 개의 프로세스가 동시에 접근을 시도하는 상태) 가 발생한다.

쿼리 표현식을 통해 장고는 코드들이 서로 경합을 피해갈수 있게 한다

from django.db.models import F
from models.customers import Customer

customers = Customer.objects.filter(scoops_ordered__gt=F('store_visit'))

이 코드는 데이터 베이스 자체 내에서 해다 조건을 비교하는 기능을 가지고 있으며 , 내부적으로는 장고는 다음과 같은 코드를 실행한다.

SELECT * from customers_customer where scoops_ordered > store_visits

쿼리 표현식은 프로젝트의 안전성과 성능을 대폭 향상 시켜주는 것이다.

참고 Field lookups
SQL의 WHERE에 해당하는 기능이다.
filter, get, exclude 메소드로 출력되는 쿼리셋을 조건에 맞게 제한한다.

__exact  Exact match.
(ex:Entry.objects.get(id__exact=14) )
(ex2:Entry.objects.get(id__exact=None) )

SQL equivalents:

SELECT ... WHERE id = 14;
SELECT ... WHERE id IS NULL;


__lt/__gt 보다 작다/ 보다 크다    less than / greater than

__lte/__gte 같거나 보다 작다/ 같거나 보다 크다

__in 주어진 리스트 안에 존재하는 자료 검색

__year / __month / __day  해당 년도, 월, 일 자료 검색
(ex: >>People.objects.filter(birth__year=2000)

__isnull  해당 열의 값이 null인 자료 검색
(ex:>>People.objects.filter(first_name__isnull=True)

__contains 해당 열의 값이 지정한 문자열을 포함하는 자료 검색 
__icontains (  대 소문자 구별안하는 contains)
(ex:>>People.objects.filter(first_name__icontains='ter')
([<People: peter>])
sql 로 치면 select ...where...like '%ter%';

__startswith/ __istartwith 해당 열의 값이 지정한 문자열로 시작하는 자료(i는 대소문자 구별 안함)

__endswith/ __iendswith

__range 문자, 숫자, 날짜 따위의 범위를 지정함
(ex:>>People.objects.filter(age__range=(19,22))

Example:

import datetime

start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))

SQL equivalent:

SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';

다른 모델 필드 기준으로 정렬하기
다른 모델의 필드를 기준으로 정렬하려면, 이중 언더바(__)를 사용한다.

Entry.objects.order_by('blog__name', 'headline')

_ _id
lookup 에서 사용되는 field 는 model field 이름이여야 하지만, ForeignKey 의 경우는

 field name + '_id' 

 를 사용한다. 

  예 ) 

       >>> Entry.objects.filter(blog_id=4)

        --> Entry 가 Blog 모델의 primary key (id) 에 대한 ForeignKey 가지고 있는 경우

우선 장고에서 제공하는 모델을 사용하기 위해선 프로젝트디렉토리에서 python manage.py shell 을 통해서 from user.models import 모델1, 모델 이런 식으로 선언하는 것 으로부터 시작된다.

Django는 여러 종류의 데이터를 DB의 것 과는 다른 독립적인 형태로 객체화 한다.
라는 앞 선 설명이 아주 중요하다.
model.objects.(1)
(1) 에 올 수있는 것들
get() (단일 행을 반환, query set이 아닌 단일행으로 출력) get 안에는 조건이 들어감. 그러므로 단일행이상을 반환하는 조건상에서 key.name 등과 같은 이용은 불가함.
all() (query set 으로 반환)
filter() (조건을 걸어 조건에 맞는 여러 행을 출력)

(get, filter 에는 조건을 걸수있으며 lookup 키워드로 조건을 걸수잇다)
order_by() (기본 디폴트는 오름차순, - 붙이면 내림차순)
value()
aggregate() : sum, count, avg, max, min

from django.db.models import Avg, Max, Min

>>> Model.objects.all().aggregate(Max('col'))

>>> Model.objects.all().aggregate(Min('col'))

>>> Model.objects.all().aggregate(Avg('col'))

Q()
django models ORM으로 WHERE절에 or 문을 추가하고 싶을떄 사용한다.

1) OR
>>> from django.db.models import Q
>>> queryset = User.objects.filter(
    Q(first_name__startswith='R') | Q(last_name__startswith='D')
    
2) AND
>>> queryset = User.objects.filter(
    Q(first_name__startswith='R') & Q(last_name__startswith='D')
)
>>> queryset = User.objects.filter(
    Q(first_name__startswith='R') & ~Q(last_name__startswith='Z')
)
3) NOT
2번 예의 ~Q(last_name__startswith='Z'
~를 통해 나타낼수 있다.

Q() 의 조건 연결

from django.db.models import Q

q = Q()
q.add(Q(n = 121), q.OR)
q.add(Q(name = lee) | Q(name=kim), q.AND)

Base.objects.filter(q)

==
SELECT * FROM base WHERE (n = 121 AND (name='lee' OR name = 'kim'))

_set
자신을 FK(foreignkey)로 가지고 있는 모델에 접근하기 위함(역참조)
모델명(소문자)+_set 로 접근 한다.

academy 테이블이 student테이블을 참조 하는 관계

a = student.objects.get(id=1)
a.academy_set.all()
a.academy_set.filter(student__contains='ter')

select_related()
prefetch_related()

링크텍스트

profile
Sometimes you gotta run before you can walk.

0개의 댓글