티스토리 뷰

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
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함