"2. 장고 뷰 DB 다루기"의 두 판 사이의 차이
(→CRUD) |
|||
22번째 줄: | 22번째 줄: | ||
def index(request): | def index(request): | ||
c = 모델.objects.create(칼럼="내용", 칼럼2="내용2") | c = 모델.objects.create(칼럼="내용", 칼럼2="내용2") | ||
+ | # 단순 생성이 아니라, 찾아보고 없을 때 생성하려면 아래처럼 진행한다. | ||
+ | c = 모델.objects.get_or_create(칼럼="내용", 칼럼2="내용2") | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- |
2022년 8월 29일 (월) 12:49 판
1 개요
일반적으로 모델을 통해 DB를 정의하고 뷰를 통해 생성, 열람, 수정, 삭제 등의 과정을 수행한다. 이와 관련된 기능들을 QuerySet(쿼리셋)이라고 한다. 이곳에서 소개되지 않은 쿼리셋은 공식문서에서 살펴보도록.
2 데이터 다루기
2.1 CRUD
Create(생성), Read(읽기), Update(갱신), Delete(삭제)
기능 | 설명 | 코드 |
---|---|---|
데이터 생성하기
객체 생성 |
모델에 해당하는 객체를 새로 만든다.
(테이블 안에 튜플을 하나 추가한다.) |
from .models import 모델명 # 모델을 임포트 한다.
def index(request):
c = 모델.objects.create(칼럼="내용", 칼럼2="내용2")
# 단순 생성이 아니라, 찾아보고 없을 때 생성하려면 아래처럼 진행한다.
c = 모델.objects.get_or_create(칼럼="내용", 칼럼2="내용2")
|
데이터 불러오기 | pk를 알면 다음과 같이 해당 객체를 불러올 수 있다. 모델.objects.get(id=pk)
|
기본적으로 모델을 임포트한 후에 불러온다.from django.shortcuts import get_object_or_404 # 기본키값에 해당하는 모델이 없을 경우 404 에러 반환.
from .models import 모델명 # 모델을 임포트 한다.
객체 = 모델.objects.get(pk=기본키값) # 없으면 에러가 나는데, 서버에러로 인식한다.
객체 = 모델.objects.get(id=기본키값) # 위와 동일
객체 = 모델.objects.filter(id=기본키값) # 위와 동일
객체 = get_object_or_404(모델명, pk=기본키값) # 서버에러가 나지 않게끔 404 에러를 발생시킨다.
|
데이터 수정하기 | def index(request):
c = 모델.objects.get(pk=기본키값) # 객체를 불러오고...
c.수정할칼럼 = "수정할 내용"
c.save() # 항상 저장을 해주어야 한다.
| |
데이터 삭제하기 | 조회, 조작한 후 모델.delete() 를 실행.
해당 객체를 불러온 후 delete()를 붙여준다.
|
def index(request):
c = 모델.objects.get(pk=기본키값) # 객체를 불러오고...
c.delete()
def index(request):
목록 = 모델.objects.exclude(조건).delete() # 조건을 제외한 것들을 삭제한다.
|
2.1.1 객체의 속성에 접근
모델.속성 형태로 속성에 접근 가능하다. 일반적으로
객체 = 모델.objects.get(id=pk)
객체 = 모델.objects.get(모델속성=특정속성)
객체.속성 형태로 접근한다.(수정을 하고 반드시 저장을 해주어야 한다.)
서버에서 에러를 내고 싶으면 위 방식으로, 404 에러를 내고 싶으면 get_object_or_404를 사용하면 된다.
객체 = get_object_or_404(get_user_model(), nickname=user_nickname)
2.2 데이터 불러오기
2.2.1 객체 다 가져오기
만들어진 모든 객체를 다 불러온다.
from django.shortcuts import render
from .models import 모델명 # 모델을 임포트 한다.
# 모델.objects는 객체목록을 받는다는 의미이다.
def index(request):
목록 = 모델.objects.all()
모델.objects.all[:5] 처럼 상위 5개만 가져오는 방식도 가능.
2.2.2 모델의 pk 얻기
모델명.id 가 pk이다.
3 필터
특정 조건에 대해 True인 튜플들을 가져온다.
3.1 필터로 걸러서 가져오기
from django.shortcuts import render
from .models import 모델명 # 모델을 임포트 한다.
# 모델.objects는 객체목록을 받는다는 의미이다.
def index(request):
목록 = 모델.objects.filter(칼럼="내용") # True가 나오는, >0 따위의 조건들을 건다.
목록2= 목록.objects.filter(조건들..) # 걸러진 객체들에 또다시 필터를 걸 수도 있다.
필터는 몇번이라도 걸 수 있는데, 장고는 지연평가 방식을 사용하기 때문에 실제로 데이터를 질의하는 것은 한 번 뿐이다. 덕분에 부하가 걸리지 않고도 filter를 자유롭게 사용할 수 있다.
def index(request):
목록 = 모델.objects.filter(조건)
.filter(조건)
.filter(조건2)
filter에서 각종 연산자를 사용할 땐 '__'를 붙인다.
def index(request):
목록 = 모델.objects.filter(속성__startswith='시작할단어')
3.2 Fieldlookup
filter 안에서 언더바 2개로 작동하는 장고의 기능.
값__in 은 SELECT ... WHERE 값 IN ...; 과 대응한다.
조금 더 복잡한 DB query를 사용하기 위한 기능이다.
장고 도큐먼트를 보면.... 나온다.
3.3 범위 지정
필터 안에서 > 따위의 기호는 사용할 수 없다. 대신 __을 사용해 명령을 지정한다.
기능 | 설명 | 사용예시 |
---|---|---|
gt | greater than | question_list= question_list.filter(create_date__gte= date) # greater than equal
question_list = question_list.filter(create_date__lte=date)
question_list = question_list.filter(created_date__range=(first_date, last_date))
|
gte | greater than or equal to | |
lt | less than | |
lte | less than or equal to |
이외 다양한 연산자를 사용할 수 있다.
3.4 날짜데이터
필터에 들어가는 날짜데이터는 datetime.date 형태의 데이터여야 한다. 다음과 같은 형태로 쓴다.
time = request.GET.get('start').split('-') # 날짜데이터를 요소별로 구분한다.
date = datetime(int(time[0]), int(time[1]), int(time[2])) # 문자열을 통해 시간객체를 만든다.
date = datetime.date(date) # 데이터형을 date로 바꾸어준다.
3.5 제외하기
필터가 True를 가져온다면 exclude는 False를 내는 튜플들을 가져온다.
필터로 원하는 조건을 받아들이는 것과 반대로, 조건에 따라 제외하는 것도 가능하다. 필터와 동일하게 중첩으로 걸 수 있다.
from django.shortcuts import render
from .models import 모델명#모델을 임포트 한다.
def index(request):
목록 = 모델.objects.exclude(칼럼명 = True, __gte=0 따위의 조건들...)
3.6 특정단어 검색
속성에 특정 단어가 포함된 객체를 불러올 땐 다음과 같이 한다. 모델.objects.filter(속성__contains='장고')
(언더바가 2개임에 유의)
3.7 다른 모델 불러오기
3.7.1 외래키 연결
모델에서 외래키로 1:N 연결을 한 경우.
외래키가 연결된 모델의 경우, 외래키 필드에 해당 키의 아이디(pk)를 넣어주면 된다.
ex) answer(question=질문키, 기타등등 필드 채우기)
이후 answer.save()를 하면 해당 질문에 대한 답변이 저장된다.
answer.question 을 사용하면 어느 질문에 달린 것인지, 질문의 id를 얻어올 수 있다.
하위에서 상위모델로 갈 땐 모델.상위모델
형태로 접근. 하위모델에서 자신과 연결된 상위모델을 조회할 수 있다.
상위에서 하위모델로 갈 땐 모델.하위모델_set
형태로 접근.(_set은 아래로 간다는 방향을 지정해주기 위한 기능인듯)
3.7.1.1 DB에 접근하는 경우
DB의 칼럼에 접근하여 뽑아내는 경우, 상위모델을 뽑아낼 땐 '모델.상위모델__속성명
' 형태로 접근할 수 있다.(모두 소문자로)
3.7.2 질문에서 답변 뽑아내기
반대로 질문에서 여러 답변들이 어떤 게 달렸는지 추출할 수도 있다.
모델.연결모델_set.all() 를 실행하면 모델에 foreign키로 연결모델들 객체를 얻을 수 있다.
모델.연결모델_set.count() 는 몇 개가 있는지 세어주고.
이처럼 속성을 가져오는 것은 탬플릿에서도 사용이 가능하다.
3.7.2.1 잘 안될 때
굳이 또 다른 모델을 임포트 할 필요는 없다.(연결된 모델이 다른 앱에 있다 하더라도)
- 유의할 점. 연결모델의 이름은 대문자가 들어갔다 하더라도 전부 소문자로 바꾸어 가져와야 한다.
- 혹시 related_name속성이 지정되어 있다면... 연결모델_set 형태가 안된다면,
모델.related_name.all()
형태로 가져오기도 한다.
기본적으로 모델명_set으로 역조회를 할 수 있지만 이는 기본옵션이고, related_name을 설정해두면 모델명.related_name
으로 접근할 수 있다.(모델.하위모델_set.all 이 아니라 바로 모델.related_name으로 접근이 가능해진다.)
같은 모델을 참조하는 모델 전체에 related_name옵션을 주어야 한다.
related_name='이름' 형태로.
이런 역참조가 필요치 않은 경우엔 related_name='+'
를 주면 된다.(혹은 맨 마지막에만 +를 넣어주어도 된다.)
3.7.3 연결된 모델 조작하기
기능 | 설명 | 코드 |
---|---|---|
불러오기 | 연결된 모델을 해당 모델의 이름을 통해 불러올 수 있다. | 모델.objects.filter(연결한모델명__속성명__예약어)
Publication.objects.filter(article__headline__startswith="NASA")
|
관계더하기(상위) | 하위모델에서 상위모델을 지정하는 것. | 모델.상위모델로연결된속성.set([상위모델객체를 담은 리스트])
|
관계더하기(하위) | 상위모델에서 하위모델을 지정하는 것. | 모델.하위모델_set.add(하위모델객체1, 하위모델객체2, ...)
|
관계제거(상위) | 상위로 연결된 관계를 제거한다. | 모델.상위모델로연결되는속성.remove(상위모델객체)
|
관계제거(하위) | 하위로 연결된 관계를 제거한다. | 모델.하위모델명_set.remove(하위모델객체)
|
3.8 다대다 관계에서
예컨대 posting에서 tag 속성이 주어져 있다면 tag에선 하위속성에 접근하듯 tag.posting_set.all()로 posting객체에 접근할 수 있다.
posting에선 posting.tag.all() 형태로 연결된 객체셋을 얻을 수 있다.
3.9 데이터 조작하기
3.9.1 객체 정렬
모델명.objects.order_by('속성') 형태로 정렬한다. 작은 것부터 보여주고 싶다면 속성 앞에 -를 붙이면 된다.
from django.shortcuts import render
from .models import 모델명#모델을 임포트 한다.
#모델.objects는 객체목록을 받는다는 의미이다.
def index(request):
목록 = 모델.objects.order_by('-create_date') # create_date속성의 역순으로 정리하라는 의미.
context={'템플릿에서 쓸 변수명':목록)
return render(request, '템플릿', context)
order_by('?') 로 두면 객체들을 랜덤하게 배치한다.
3.9.2 새로운 속성 만들어 사용하기
정렬을 하는데 하위 모델의 갯수를 세어 정렬해야 할 때엔 새로운 속성을 만들어 적용해야 한다.
모델.objects.order_by(Count='answer', '-create_date')
형태로 작성이 되진 않는다. order_by 안의 괄호에 들어가야 하는 건 항상 속성 뿐이다.
때문에 annotate를 사용해 새로운 속성을 만들어준 후에 oreder_by를 써야 한다. 모델.objects.annotate(num=Count('하위모델')).order_by('-num', '-create_date')
# -num으로 우선배치한 후, 같은 숫자가 나온다면 만들어진 순서로 우열을 정한다.)
Count를 사용하기 위해선 from django.db.models import Count
가 필요하다.
3.10 유의
탬플릿에선 위 속성들을 그대로 사용할 수 있지만, 괄호는 빼주고 기입한다.