하나의 글에 배웠던 모든 내용과 코드를 작성할 경우 글이 너무 길어지기 때문에 핵심적인 내용만 요약해서 정리할 예정입니다. 과정을 마무리하는 단계에서 지금(현재 6주차)까지 배웠던 내용을 주제별로 나눈다면 다음과 같습니다.
week1: Django가 무엇인지, 가상환경, 프로젝트 세팅에 관하여
week2: Model, View, Template, 템플릿 상속
week3: ORM,
week4: FBV, CBV
week5: Authentication
week6: AWS 배포
ORM은 Object Relation Mapper의 약자입니다. Django ORM은 데이터베이스와 상호작용하는 강력하고 우아한 방법입니다. Django ORM은 SQL 명령문이 아닌 비교적 간단한 파이썬 명령문으로 데이터베이스를 다룰 수 있는 추상화된 레이어입니다. 최종적으로 Django ORM은 모든 작업을 SQL 문으로 변환합니다. 이 포스팅에서는 일반적인 SQL 쿼리의 ORM에 대해 알아보겠습니다.
Django ORM은 관계형 데이터베이스 관리 시스템중에 널리 사용되는 PostgreSQL, MySQL, Oracle, sqlite3 등의 RDBMS를 Wrapping하여 사용할 수 있습니다. Django ORM 명령어를 통해 다양한 데이터베이스 시스템을 제어할 수 있습니다.
데이터베이스의 모델 인스턴스를 Django shell을 통해 제어할 수 있습니다. 아래의 명령어를 실행하면 Python shell 처럼 동작합니다.
python manage.py shell
User 스키마를 가지는 테이블을 생성하고 데이터베이스의 데이터를 표와 같이 추가합니다.
# member/models.py
from django.db import models
# Create your models here.
class User(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
city = models.CharField(max_length=255)
id | name | age | city |
---|---|---|---|
1 | lee | 20 | seoul |
2 | kim | 25 | busan |
3 | park | 30 | daegu |
조회
User 테이블의 id가 1인 데이터를 조회하는 경우
User.objects.filter(id=1)
User 테이블의 모든 인스턴스 조회
User.objects.all()
생성
name="choi", age=35, city="daejeon"이란 데이터를 추가하는 경우
u = User.objects.create(name="choi", age=35, city="daejeon")
u.save()
혹은
u = User(name="choi", age=35, city="daejeon")
u.save(force_insert=True)
수정
u = User.objects.get(pk=1)
u.age = 21
u.save()
삭제
id=1인 인스턴스 삭제
User.objects.get(pk=1).delete()
User의 모든 인스턴스 삭제
User.objects.all().delete()
Null Value
‘__isnull’
은 Null value를 체크하는 ORM 문법이고 True
, False
를 리턴한다.
User.objects.filter(age__isnull=True).values('id','age')
<QuerySet []>
User.objects.filter(age__isnull=False).values('id','age')
<QuerySet [{'id': 1, 'age': 20}, {'id': 2, 'age': 25}, {'id': 3, 'age': 30}]>
exists()
queryset을 확인하려면 exists()
메서드를 사용합니다. queryset 에 결과가 포함되어 있으면 True를 반환하고, 포함되어 있지 않으면 False를 반환합니다.
User.objects.filter(age__isnull=True).values('id','age').exists()
False
User.objects.filter(age__isnull=False).values('id','age').exists()
True
LIKE
User.objects.filter(city__contains='city').values('id','city')
<QuerySet [{'id': 1, 'city': 'city1'}, {'id': 2, 'city': 'city2'}, {'id': 3, 'city': 'city3'}]>
위 쿼리에서 __contains
는 city 열의 'city' 하위 문자열을 검색하는 데 사용됩니다. 또한 __exact
를 사용하여 정확히 일치하는지를 확인할 수 있습니다.
User.objects.filter(city__exact='city').values('id','city')
<QuerySet []>
__startswith
, __endswith
User.objects.filter(city__startswith='city').values('id','city')
<QuerySet [{'id': 1, 'city': 'city1'}, {'id': 2, 'city': 'city2'}, {'id': 3, 'city': 'city3'}]>
User.objects.filter(city__startswith='ity').values('id','city')
<QuerySet []>
User.objects.filter(city__endswith='2').values('id','city')
<QuerySet [{'id': 2, 'city': 'city2'}]>
비교
gt
- Greater than.
gte
- Greater than or equal to.
lt
- Less than.
lte
- Less than or equal to.
User.objects.filter(age__gt=20).values('id','age')
<QuerySet [{'id': 2, 'age': 25}, {'id': 3, 'age': 30}]>
User.objects.filter(age__gte=20).values('id','age')
<QuerySet [{'id': 1, 'age': 20}, {'id': 2, 'age': 25}, {'id': 3, 'age': 30}]>
User.objects.filter(age__lt=25).values('id','age')
<QuerySet [{'id': 1, 'age': 20}]>
User.objects.filter(age__lte=25).values('id','age')
<QuerySet [{'id': 1, 'age': 20}, {'id': 2, 'age': 25}]>
특정 칼럼 선택
User.objects.values('id')
<QuerySet [{'id': 1}, {'id': 2}, {'id': 3}]>
User.objects.values('id','first_name','last_name')
<QuerySet [{'id': 1, 'first_name': 'sample', 'last_name': '1'}, {'id': 2, 'first_name': 'sample', 'last_name': '2'}, {'id': 3, 'first_name': 'sample', 'last_name': '3'}]>
IN
__in
은 Multiple values를 필터링하기 위해 사용된다.
User.objects.filter(id__in=[1,2])
<QuerySet [<User: User object (1)>, <User: User object (2)>]>
exclude()
조회 매개 변수와 일치하는 개체를 queryset에서 제외합니다.
User.objects.exclude(id=1)
<QuerySet [<User: User object (2)>, <User: User object (3)>]>
Aiias, AS
extra() 메서드는 ORM 컬럼의 이름을 변경하기 위해 사용됩니다.
User.objects.extra(select={'FirstName':'first_name','LastName':'last_name'}).values('FirstName','LastName')
<QuerySet [{'FirstName': 'sample', 'LastName': '1'}, {'FirstName': 'sample', 'LastName': '2'}, {'FirstName': 'sample', 'LastName': '3'}]>
Group By
aggregate() 함수는 sum, average, min, max 등의 집계 연산을 실행하기 위해 사용됩니다.
User.objects.aggregate(Sum('age'))
{'age__sum': 75}
User.objects.aggregate(Avg('age'))
{'age__avg': 25.0}
User.objects.aggregate(Max('age'))
{'age__max': 30}
User.objects.aggregate(Min('age'))
{'age__min': 20}
aggregate()
aggregate 함수는 전체 데이터 집합에서만 작동합니다. 도시별 평균 연령 그룹을 원할 경우 aggregate() 대신 annotate()를 사용합니다.
User.objects.values('city').annotate(Sum('age'))
<QuerySet [{'city': 'city1', 'age__sum': 20}, {'city': 'city2', 'age__sum': 25}, {'city': 'city3', 'age__sum': 30}]>
Order by
User.objects.values('city').annotate(total_age=Sum('age')).order_by('-total_age')
<QuerySet [{'city': 'city3', 'total_age': 30}, {'city': 'city2', 'total_age': 25}, {'city': 'city1', 'total_age': 20}]>
출력의 기본 이름을 변경
total_age라는 이름을 변경하고 total_age에 order_by를 사용합니다. '-total_age'는 내림차순으로 사용됩니다.
일반적으로 데이터베이스에서는 쿼리별로 그룹에 'HAVING' 절을 사용합니다. Django에서는 filter() 함수를 사용할 수 있습니다.
User.objects.values('city').annotate(total_age=Sum('age')).filter(total_age__gt=20).order_by('-total_age')
<QuerySet [{'city': 'city3', 'total_age': 30}, {'city': 'city2', 'total_age': 25}]>
Q 객체
를 사용한 필터링Q 객체는 AND, OR 및 NOT 연산에 사용됩니다.
AND
‘&’ is used for AND operation between 2 Q expressions.
User.objects.filter(Q(city='city1') & Q(age=25)).values('id','city','age')
<QuerySet []>
User.objects.filter(Q(city='city1') & Q(age=20)).values('id','city','age')
<QuerySet [{'id': 1, 'city': 'city1', 'age': 20}]>
OR
User.objects.filter(Q(city='city1') | Q(age=25)).values('id','city','age')
<QuerySet [{'id': 1, 'city': 'city1', 'age': 20}, {'id': 2, 'city': 'city2', 'age': 25}]>
User.objects.filter(Q(city='city1') & ~Q(age=20)).values('id','city','age')
<QuerySet []>
User.objects.filter(Q(city='city2') & ~Q(age=20)).values('id','city','age')
<QuerySet [{'id': 2, 'city': 'city2', 'age': 25}]>
F() Expressions
Django QuerySet API에서 F() 표현은 데이터베이스의 모델 필드 값을 직접 참조하기 위해 사용됩니다.
User.objects.annotate(new_age=F('age')*2).values('id','age','new_age')
<QuerySet [{'id': 1, 'age': 20, 'new_age': 40}, {'id': 2, 'age': 25, 'new_age': 50}, {'id': 3, 'age': 30, 'new_age': 60}]>
User.objects.filter(id__lt=F('age')).values('id','age')
<QuerySet [{'id': 1, 'age': 20}, {'id': 2, 'age': 25}, {'id': 3, 'age': 30}]>
User.objects.filter(id__gt=F('age')).values('id','age')
<QuerySet []>