"2. 장고 뷰 DB 다루기"의 두 판 사이의 차이
(→CRUD) |
잔글 |
||
(같은 사용자의 중간 판 13개는 보이지 않습니다) | |||
3번째 줄: | 3번째 줄: | ||
== 개요 == | == 개요 == | ||
일반적으로 모델을 통해 DB를 정의하고 뷰를 통해 생성, 열람, 수정, 삭제 등의 과정을 수행한다. 이와 관련된 기능들을 QuerySet(쿼리셋)이라고 한다. 이곳에서 소개되지 않은 쿼리셋은 공식문서에서 살펴보도록. | 일반적으로 모델을 통해 DB를 정의하고 뷰를 통해 생성, 열람, 수정, 삭제 등의 과정을 수행한다. 이와 관련된 기능들을 QuerySet(쿼리셋)이라고 한다. 이곳에서 소개되지 않은 쿼리셋은 공식문서에서 살펴보도록. | ||
+ | |||
+ | === 가능하면 탬플릿에서.. === | ||
+ | 뷰에서 탬플릿으로 넘길 수 있지만.. 탬플릿 자체에서도 하위 객체를 불러오거나 정렬이 가능하다. [[5. 장고 탬플릿 DB 다루기]] 문서를 참고하자. | ||
=데이터 다루기= | =데이터 다루기= | ||
23번째 줄: | 26번째 줄: | ||
c = 모델.objects.create(칼럼="내용", 칼럼2="내용2") | c = 모델.objects.create(칼럼="내용", 칼럼2="내용2") | ||
# 단순 생성이 아니라, 찾아보고 없을 때 생성하려면 아래처럼 진행한다. | # 단순 생성이 아니라, 찾아보고 없을 때 생성하려면 아래처럼 진행한다. | ||
− | c = 모델.objects.get_or_create(칼럼="내용", 칼럼2="내용2") | + | c, 생성여부 = 모델.objects.get_or_create(칼럼="내용", 칼럼2="내용2") |
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |- | ||
32번째 줄: | 35번째 줄: | ||
from .models import 모델명 # 모델을 임포트 한다. | from .models import 모델명 # 모델을 임포트 한다. | ||
− | 객체 = 모델.objects.get(pk=기본키값) # | + | 객체 = 모델.objects.get(pk=기본키값, 이외옵션.) # 없거나 2개 이상이면 에러가 나는데, 서버에러로 인식한다. |
객체 = 모델.objects.get(id=기본키값) # 위와 동일 | 객체 = 모델.objects.get(id=기본키값) # 위와 동일 | ||
− | 객체 = 모델.objects.filter(id=기본키값) # 위와 | + | 객체 = 모델.objects.filter(id=기본키값) # 위와 동일하나, 1개도 쿼리셋으로 가져온다. get처럼 쓰려면 맨 뒤에 .first() 혹은 .last()로 하나만 뽑아내자. |
− | 객체 = get_object_or_404( | + | 객체 = get_object_or_404(모델, pk=기본키값) # 서버에러가 나지 않게끔 404 에러를 발생시킨다. |
166번째 줄: | 169번째 줄: | ||
===특정단어 검색=== | ===특정단어 검색=== | ||
속성에 특정 단어가 포함된 객체를 불러올 땐 다음과 같이 한다. <code>모델.objects.filter(속성__contains='장고')</code> (언더바가 2개임에 유의) | 속성에 특정 단어가 포함된 객체를 불러올 땐 다음과 같이 한다. <code>모델.objects.filter(속성__contains='장고')</code> (언더바가 2개임에 유의) | ||
+ | |||
+ | === 쿼리셋에서 제외하기 === | ||
+ | 필터가 아니라 외부에서 얻은 정보를 토대로 쿼리셋에서 지워야 하는 경우가 있다. | ||
+ | |||
+ | 그럴 땐 쿼리셋 자체를 리스트로 만든 후 리스트에서 remove(객체)를 통해 제거하는 방법이 있다. | ||
== 다른 모델 불러오기 == | == 다른 모델 불러오기 == | ||
180번째 줄: | 188번째 줄: | ||
answer.question 을 사용하면 어느 질문에 달린 것인지, 질문의 id를 얻어올 수 있다. | answer.question 을 사용하면 어느 질문에 달린 것인지, 질문의 id를 얻어올 수 있다. | ||
− | 하위에서 상위모델로 갈 땐 <code>모델.상위모델</code> 형태로 접근. 하위모델에서 자신과 연결된 상위모델을 조회할 수 있다. | + | 하위에서 상위모델로 갈 땐 <code>모델.상위모델</code> 형태로 접근. 하위모델에서 자신과 연결된 상위모델을 조회할 수 있다.(다른 모델을 연결할 땐 대문자를 소문자로 바꾸어주어야 한다.) |
− | 상위에서 하위모델로 갈 땐 <code>모델.하위모델_set</code> 형태로 접근.(_set은 아래로 간다는 방향을 지정해주기 위한 | + | 상위에서 하위모델로 갈 땐 <code>모델.하위모델_set.all()</code> 형태로 접근.(_set은 아래로 간다는 방향을 지정해주기 위한 것) |
====DB에 접근하는 경우==== | ====DB에 접근하는 경우==== | ||
DB의 칼럼에 접근하여 뽑아내는 경우, 상위모델을 뽑아낼 땐 '<code>모델.상위모델__속성명</code>' 형태로 접근할 수 있다.(모두 소문자로) | DB의 칼럼에 접근하여 뽑아내는 경우, 상위모델을 뽑아낼 땐 '<code>모델.상위모델__속성명</code>' 형태로 접근할 수 있다.(모두 소문자로) | ||
249번째 줄: | 257번째 줄: | ||
posting에선 posting.tag.all() 형태로 연결된 객체셋을 얻을 수 있다. | posting에선 posting.tag.all() 형태로 연결된 객체셋을 얻을 수 있다. | ||
+ | |||
+ | posting.tag.add(tag객체) 형태로 태그와의 연결을 추가할 수 있다. | ||
== 데이터 조작하기 == | == 데이터 조작하기 == | ||
254번째 줄: | 264번째 줄: | ||
===객체 정렬=== | ===객체 정렬=== | ||
모델명.objects.order_by('속성') 형태로 정렬한다. 작은 것부터 보여주고 싶다면 속성 앞에 -를 붙이면 된다. | 모델명.objects.order_by('속성') 형태로 정렬한다. 작은 것부터 보여주고 싶다면 속성 앞에 -를 붙이면 된다. | ||
+ | |||
+ | 이미 불러온 객체들을 정렬하고 싶다면 <code>객체목록.order_by('속성')</code>으로 정렬할 수 있다. | ||
<syntaxhighlight lang="python"> | <syntaxhighlight lang="python"> | ||
from django.shortcuts import render | from django.shortcuts import render | ||
263번째 줄: | 275번째 줄: | ||
context={'템플릿에서 쓸 변수명':목록) | context={'템플릿에서 쓸 변수명':목록) | ||
return render(request, '템플릿', context) | return render(request, '템플릿', context) | ||
− | </syntaxhighlight>order_by('?') 로 두면 객체들을 랜덤하게 배치한다. | + | </syntaxhighlight> |
+ | |||
+ | * <code>order_by('?')</code> 로 두면 객체들을 랜덤하게 배치한다. | ||
+ | * <code>order_by('속성', '속성2', ...)</code>로 두면 여러 개의 기준으로 정렬할 수 있다. | ||
+ | * 속성이 다른 모델과 연결된 경우, <code>order_by('모델__속성')</code> 형태로 연결된 모델의 속성을 사용할 수도 있다. | ||
+ | * 하위속성을 가져와 정렬하는 경우 <code>school.homeroom_set.all().order_by('name')</code> 형태로 사용한다. | ||
===새로운 속성 만들어 사용하기=== | ===새로운 속성 만들어 사용하기=== | ||
277번째 줄: | 294번째 줄: | ||
==유의== | ==유의== | ||
탬플릿에선 위 속성들을 그대로 사용할 수 있지만, 괄호는 빼주고 기입한다. | 탬플릿에선 위 속성들을 그대로 사용할 수 있지만, 괄호는 빼주고 기입한다. | ||
+ | |||
+ | = 요약 = | ||
+ | |||
+ | == 모델 조회 == | ||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | !기능 | ||
+ | !설명 | ||
+ | |- | ||
+ | |all() | ||
+ | |모든 데이터셋을 가져온다. | ||
+ | |- | ||
+ | |get() | ||
+ | |조건에 맞는 것 하나. | ||
+ | |- | ||
+ | |filter() | ||
+ | |조건에 맞는 것 다. | ||
+ | |- | ||
+ | |exclude() | ||
+ | |조건에 맞는 것 빼고 다. | ||
+ | |- | ||
+ | |first() | ||
+ | |처음 하나. | ||
+ | |- | ||
+ | |last() | ||
+ | |마지막 하나. | ||
+ | |- | ||
+ | |exists() | ||
+ | |있나 없나 여부만 True, False로 반환. | ||
+ | 모델.objects.filter().exists() 형태로 활용. | ||
+ | |- | ||
+ | |order_by() | ||
+ | |조건에 따라 정리한다. | ||
+ | |} | ||
[[분류:장고 뷰]] | [[분류:장고 뷰]] |
2024년 7월 4일 (목) 16:57 기준 최신판
1 개요편집
일반적으로 모델을 통해 DB를 정의하고 뷰를 통해 생성, 열람, 수정, 삭제 등의 과정을 수행한다. 이와 관련된 기능들을 QuerySet(쿼리셋)이라고 한다. 이곳에서 소개되지 않은 쿼리셋은 공식문서에서 살펴보도록.
1.1 가능하면 탬플릿에서..편집
뷰에서 탬플릿으로 넘길 수 있지만.. 탬플릿 자체에서도 하위 객체를 불러오거나 정렬이 가능하다. 5. 장고 탬플릿 DB 다루기 문서를 참고하자.
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=기본키값, 이외옵션.) # 없거나 2개 이상이면 에러가 나는데, 서버에러로 인식한다.
객체 = 모델.objects.get(id=기본키값) # 위와 동일
객체 = 모델.objects.filter(id=기본키값) # 위와 동일하나, 1개도 쿼리셋으로 가져온다. get처럼 쓰려면 맨 뒤에 .first() 혹은 .last()로 하나만 뽑아내자.
객체 = 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 쿼리셋에서 제외하기편집
필터가 아니라 외부에서 얻은 정보를 토대로 쿼리셋에서 지워야 하는 경우가 있다.
그럴 땐 쿼리셋 자체를 리스트로 만든 후 리스트에서 remove(객체)를 통해 제거하는 방법이 있다.
3.8 다른 모델 불러오기편집
3.8.1 외래키 연결편집
모델에서 외래키로 1:N 연결을 한 경우.
외래키가 연결된 모델의 경우, 외래키 필드에 해당 키의 아이디(pk)를 넣어주면 된다.
ex) answer(question=질문키, 기타등등 필드 채우기)
이후 answer.save()를 하면 해당 질문에 대한 답변이 저장된다.
answer.question 을 사용하면 어느 질문에 달린 것인지, 질문의 id를 얻어올 수 있다.
하위에서 상위모델로 갈 땐 모델.상위모델
형태로 접근. 하위모델에서 자신과 연결된 상위모델을 조회할 수 있다.(다른 모델을 연결할 땐 대문자를 소문자로 바꾸어주어야 한다.)
상위에서 하위모델로 갈 땐 모델.하위모델_set.all()
형태로 접근.(_set은 아래로 간다는 방향을 지정해주기 위한 것)
3.8.1.1 DB에 접근하는 경우편집
DB의 칼럼에 접근하여 뽑아내는 경우, 상위모델을 뽑아낼 땐 '모델.상위모델__속성명
' 형태로 접근할 수 있다.(모두 소문자로)
3.8.2 질문에서 답변 뽑아내기편집
반대로 질문에서 여러 답변들이 어떤 게 달렸는지 추출할 수도 있다.
모델.연결모델_set.all() 를 실행하면 모델에 foreign키로 연결모델들 객체를 얻을 수 있다.
모델.연결모델_set.count() 는 몇 개가 있는지 세어주고.
이처럼 속성을 가져오는 것은 탬플릿에서도 사용이 가능하다.
3.8.2.1 잘 안될 때편집
굳이 또 다른 모델을 임포트 할 필요는 없다.(연결된 모델이 다른 앱에 있다 하더라도)
- 유의할 점. 연결모델의 이름은 대문자가 들어갔다 하더라도 전부 소문자로 바꾸어 가져와야 한다.
- 혹시 related_name속성이 지정되어 있다면... 연결모델_set 형태가 안된다면,
모델.related_name.all()
형태로 가져오기도 한다.
편집
기본적으로 모델명_set으로 역조회를 할 수 있지만 이는 기본옵션이고, related_name을 설정해두면 모델명.related_name
으로 접근할 수 있다.(모델.하위모델_set.all 이 아니라 바로 모델.related_name으로 접근이 가능해진다.)
같은 모델을 참조하는 모델 전체에 related_name옵션을 주어야 한다.
related_name='이름' 형태로.
이런 역참조가 필요치 않은 경우엔 related_name='+'
를 주면 된다.(혹은 맨 마지막에만 +를 넣어주어도 된다.)
3.8.3 연결된 모델 조작하기편집
기능 | 설명 | 코드 |
---|---|---|
불러오기 | 연결된 모델을 해당 모델의 이름을 통해 불러올 수 있다. | 모델.objects.filter(연결한모델명__속성명__예약어)
Publication.objects.filter(article__headline__startswith="NASA")
|
관계더하기(상위) | 하위모델에서 상위모델을 지정하는 것. | 모델.상위모델로연결된속성.set([상위모델객체를 담은 리스트])
|
관계더하기(하위) | 상위모델에서 하위모델을 지정하는 것. | 모델.하위모델_set.add(하위모델객체1, 하위모델객체2, ...)
|
관계제거(상위) | 상위로 연결된 관계를 제거한다. | 모델.상위모델로연결되는속성.remove(상위모델객체)
|
관계제거(하위) | 하위로 연결된 관계를 제거한다. | 모델.하위모델명_set.remove(하위모델객체)
|
3.9 다대다 관계에서편집
예컨대 posting에서 tag 속성이 주어져 있다면 tag에선 하위속성에 접근하듯 tag.posting_set.all()로 posting객체에 접근할 수 있다.
posting에선 posting.tag.all() 형태로 연결된 객체셋을 얻을 수 있다.
posting.tag.add(tag객체) 형태로 태그와의 연결을 추가할 수 있다.
3.10 데이터 조작하기편집
3.10.1 객체 정렬편집
모델명.objects.order_by('속성') 형태로 정렬한다. 작은 것부터 보여주고 싶다면 속성 앞에 -를 붙이면 된다.
이미 불러온 객체들을 정렬하고 싶다면 객체목록.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('?')
로 두면 객체들을 랜덤하게 배치한다.order_by('속성', '속성2', ...)
로 두면 여러 개의 기준으로 정렬할 수 있다.- 속성이 다른 모델과 연결된 경우,
order_by('모델__속성')
형태로 연결된 모델의 속성을 사용할 수도 있다. - 하위속성을 가져와 정렬하는 경우
school.homeroom_set.all().order_by('name')
형태로 사용한다.
3.10.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.11 유의편집
탬플릿에선 위 속성들을 그대로 사용할 수 있지만, 괄호는 빼주고 기입한다.
4 요약편집
4.1 모델 조회편집
기능 | 설명 |
---|---|
all() | 모든 데이터셋을 가져온다. |
get() | 조건에 맞는 것 하나. |
filter() | 조건에 맞는 것 다. |
exclude() | 조건에 맞는 것 빼고 다. |
first() | 처음 하나. |
last() | 마지막 하나. |
exists() | 있나 없나 여부만 True, False로 반환.
모델.objects.filter().exists() 형태로 활용. |
order_by() | 조건에 따라 정리한다. |