티스토리 뷰
Model Manager
- 데이터베이스 질의 인터페이스를 제공
- 디폴트 Manager 로서 ModelCls.objects 가 제공
ModelCls.objects.all() # 특정 모델의 전체 데이터 조회 ModelCls.objects.all().order_by('-id')[:10] # 특정 모델의 최근 10개 데이터 조회 , order_by절을 통해 id필드기준으로 정렬 ModelCls.objects.create(title="New Title") # 특정 모델의 새 Row 저장 |
1. QuerySet
- SQL 을 생성해주는 인터페이스
- Model Manager 를 통해, 해당 Model 에 대한 QuerySet 을 획득
- Post.objects.all() 는 "SELECT * FROM post;" 와 같은 SQL 을 생성하여, 데이터베이스로의 질의를 수행
- Post.objects.create(...) 는 "INSERT INTO ...;" 와 같은 SQL을 생성하여, 데이터베이스로의 질의를 수행
- Chaining 지원 : QuerySet 수행 리턴값이 다시 QuerySet
from blog.models import Post as Blog_Post from django.db import connection > Blog_Post.objects.all().order_by('-id')[:10] > connection.queries[-1] {'sql': 'SELECT "blog_post"."id", "blog_post"."user_id", "blog_post"."title", "blog_post"."content", "blog_post"."created_at", "blog_post"."updated_at", "blog_post"."tags", "blog_post"."status", "blog_post"."lnglat" FROM "blog_post" ORDER BY "blog_post"."id" DESC LIMIT 10', 'time': '0.000'} # 마지막에 실행한 쿼리를 가져온다. |
1-1. QuerySet을 통한 AND 조회 조건 (Chaining, Lazy)
queryset = ModelCls.objects.all() queryset = queryset.filter(조건필드1=조건값1, 조건필드2=조건값2) # , = and queryset = queryset.filter(조건필드3=조건값3) queryset = queryset.filter(조건필드4=조건값4, 조건필드5=조건값5) 조건 필드 모두 AND 지정 # 실제 데이터 Row에 접근 할 때, 데이터베이스 쿼리 (Lazy) for model_instance in queryset: print (model_instance) |
1-2. QuerySet을 통한 OR 조건 지정
from django.db.models import Q queryset = ModelCls.objects.all() queryset.filter(Q(조건필드1=조건값1) | Q(조건필드2=조건값2)) # OR 조건 # Q를 통해 OR지정 가능 queryset.filter(Q(조건필드1=조건값1) & Q(조건필드2=조건값2)) # AND 조건 |
1-3. blog.views.post_list뷰에서 간단한 검색 구현
#blog/views.py def post_list(requests): qs = Post.objects.all() # Post 모델클래스의 전체 데이터 저장 q = requests.GET.get('q','') # get파라미터중 q라는 값 저장 if q: # 만약 값이 있을 경우 qs = qs.filter(title__icontains=q) # 대소문자 구별없이, title에 값을 찾는다. return render(requests, 'blog/post_list.html', { 'post_list' : qs, 'q':q,}) #blog/templates/blog/post_list.html <form action="" method="get"> <input type="text" name="q" /> <input type="submit" value="검색" /> </form> |
1-4. 특정 필드 정렬 조건
queryset내 기본정렬은 모델내 Meta.ordering설정을 따름
class Post(models.Model): # 필드 정의 생략 class Meta: ordering = ['id'] # id 필드오름차순 정렬, (-id입력시 내림차순 정렬) |
필드명만 지정시 오름차순 정렬 요청, "-필드명" 지정시 내람차순 정렬 요청
정렬 미지정시에는 데이터베이스 측에서 임의정렬
# 모델 Meta.ordering 을 무시하고, 직접 정렬조건 지정
queryset = queryset.order_by('field1') # 지정 필드 오름차순 요청
queryset = queryset.order_by('-field1') # 지정 필드 내림차순 요청
queryset = queryset.order_by('field2', 'field3') # 1차기준, 2차기준
2. 지정 조건 (get, first, last)
- 지정 조건으로 DB로부터 데이터를 Fetch
1. queryset.get
• 해당 조건에 해당되는 데이터가 1개임을 기대
• 0개 매칭 : ModelCls.DoesNotExist 예외 발생
• 1개 매칭 : 정상적으로 처리
• 2개이상 매칭 : ModelCls.MultipleObjectsReturned 예외 발생
# 지정 조건의 데이터 Row를 순회 from model_instance in queryset: print (model_instance) # 특정 조건의 데이터 Row 1개 Fetch model_insatnce = queryset.get(title='제목') |
2. qureyset.first() 혹은 queryset.last()
• 지정 조건 내에서 첫번째/마지막 데이터 Row를 Fetch
• 지정 조건에 맞는 데이터 Row가 없더라도, DoesNotExist 예외가 발생하지 않고, None을 반환
model_instance = queryset.first() # model instance 또는 None model_instance = queryset.last() # model instance 또는 None |
3. DB 데이터 추가(Create)
- 필수 필드1를 모두 지정을 하고, 데이터 추가가 이뤄져야함
그렇지 않으면, IntegrityError 예외 발생
- shell을 통해, 모델 import 후 모델명?? 을 입력하면 상세 필드 옵션 확인이 가능 함
> Post?? class Post(models.Model): STATUE_CHOICE = ( ('d', 'Draft'), ('p', 'Published'), ('w', 'Withdrawn'), ) user = models.ForeignKey(settings.AUTH_USER_MODEL) #author = models.CharField(max_length=20) title = models.CharField(max_length=100, verbose_name='제목', help_text='포스팅 제목을 입력해주세요. 최대 100자 내외.') # choices = (('',''),('',''))를 통해 항목을 선택할수 있게 가능함 content = models.TextField(verbose_name='내용') created_at = models.DateField(auto_now_add=True) updated_at = models.DateField(auto_now=True) tags = models.CharField(max_length=50, blank=True) tag_set = models.ManyToManyField('Tag',blank=True) status = models.CharField(max_length=1, choices=STATUE_CHOICE) lnglat = models.CharField(max_length=50, blank=True, validators=[lnglat_validator],help_text='위도/경도') class Meta: ## 정렬 (오름차순/내림차순) ordering = ['-id'] def __str__(self): ## 오브젝트 이름을 레코드값으로 지정함. return self.title def get_absolute_url(self): return reverse('blog:post_detail', args=[self.id]) |
CREATE
3.1 model instance의 save 함수
model_instance = Post(author=User.objects.all()[0], title='title', text='content') model_instance.save() |
3.2 model instance의 create 함수
new_post = Post.objects.create(author=User.objects.get(id=1), title='title', text='content') |
tip. 데이터베이스 Insert SQL로 전달
UPDATE
3.3 방법1. 각 Model 인스턴스 속성을 변경하고, save함수를 통해 저장
- 각 Model 인스턴스 별로 SQL이 실행
- 다수 Row 에 대해서 수행 시에는 성능 저하 발생
> post = Post.objects.get(id=1) > post.tags = 'Python, Django' > post.save() > queryset = Post.objects.all() > for post in queryset: > post.tags = 'Python, Django' > post.save() # 각 Model Instance 별로 DB에 update 요청 |
3.4 방법2. QuerySet의 update 함수에 업데이트할 속성값을 지정하여 일괄 수정
- 하나의 SQL로서 동작하므로, 동작이 빠르다.
> queryset = Post.objects.all() > queryset.update(tags="Python, Django") # 일괄 update 요청 # Tip : 데이터베이스에는 UPDATE SQL이 전달 UPDATE blog_post SET tags='Python, Django'; |
DELETE
3.5 방법1. 각 Model인스턴싀 delete함수를 호출하여, 데이터 베이스 측의 관련 데이터를 삭제
- 각 Model 인스턴스 별로 SQL이 수행
- 다수 Row에 대해서 수행시 성능 저하가 발생
> post = Post.objects.get(id=1) > post.delete() > queryset = Post.objects.all() > for post in queryset: > post.delete() # 각 Model Instance 별로 DB에 delete 요청 |
3.6 방법2. QuerySet의 delete함수를 호출하여, 데이터베이스 측의 관련 데이터 삭제
- 하나의 SQL로서 동작하므로, 동작이 빠르다.
> queryset = Post.objects.all() > queryset.delete() # 일괄 delete 요청 # Tip : 데이터베이스에는 DELETE SQL이 전달 DELETE FROM blog_post; |
3. 웹서비스, 각 요청 반응속도에서의 병목
• 데이터베이스 : 아주 중요
• DB로 전달/실행되는 SQL갯수를 줄이고
• 각 SQL의 성능/처리속도 최적화가 필요
• 로직의 복잡도 : 중요
• 프로그래밍 언어의 종류 : 대개는 미미
4. django-debug-toolbar
- 현재 request/response에 대한 다양한 디버깅 정보를 보여준다.
- SQLPanel을 통해 각 요청 처리 시에 발생한 SQL 내역 확인 가능
- 웹서비스 성능과 직결 = 응답 속도
# 설치 > pip install django-debug-toolbar # setting.py INSTALLED_APPS = [..., "debug_toolbar"] MIDDLEWARE = ["debug_toolbar.middleware.DebugToolbarMiddleware", ...] INTERNAL_IPS = ["127.0.0.1"] # urls.py if settings.DEBUG: # setting.py의 DEBUG = True인 경우 import debug_toolbar urlpatterns += [ url(r'^__debug__/', include(debug_toolbar.urls)), ] |
(중요) : 해당 페이지의 템플릿에 <body>태그가 존재 해야된다.
5. requirements.txt 작성
- 현재까지 사용한 라이브러리 목록을 정리한다.
# vi requirements.txt django==1.10.5 django-debug-toolbar django-extensions ipython[notebook] |
- pip install -r requirements.txt를 통해 한번에 설치가 가능함
"""본 내용은 AskDjango VOD, "장고 차근차근 시작하기" 강의내용을 참고하여 작성했습니다.(https://nomade.kr/)"""
'Python > * Django' 카테고리의 다른 글
9. Model Relationship Fields (2) | 2017.12.13 |
---|---|
8. Http Status Code 404 (0) | 2017.12.13 |
6. Django Admin (0) | 2017.12.12 |
5. Migration (0) | 2017.12.12 |
4. Django Model과 Model Fields (0) | 2017.12.12 |