Optimization

SQL문 실행

  • Iteration

  • Slicing

    • 기본적으론 x

    • step을 활용할 때에만

      • [3:10:2]

  • repr

  • len

  • bool

Query 개선

필수 라이브러리 : django debug toolbar

installation

pip install django-debug-toolbar

Prerequisites

settings.py

INSTALLED_APPS = [
    ...
    'debug_toolbar',
]

Setting up URLconf

urls.py in the root directory

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

if settings.DEBUG:
    import debug_toolbar
    urlpatterns = [
        path('__debug__/', include(debug_toobar.urls)),
        path('admin/', admin.site.urls),
        path('posts/', include('posts.urls')),
        path('accounts/', include('accounts.urls')),
    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Enabling middleware

settings.py

MIDDLEWARE = [
 ...
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    ...
]

Configuring Internal IPs

settings.py

INTERNAL_IPS = [
    ...
    '127.0.0.1',
    ...
]

0. 관련 문서

1. 댓글 수 출력 - annotate() 활용

N+1 problem

개선 전 (11번)

# views.py
posts = Post.objects.order_by('-pk')
<p>댓글 수 : {{ aritcle.comment_set.count }}</p>

개선 후 (1번)

# views.py
Post.objects.annotate(comment_set_count=Count('comment')).order_by('-pk')
<!-- 주의! comment_set_count로 호출 -->
<p>댓글 수 : {{ post.comment_set_count }}</p>

select_related는 SQL JOIN을 통해 데이터를 가져온다

1:1, 1:N 관계에서 참조관계 (N -> 1, foreignkey가 정의되어 있는 곳)

개선 전 (11번)

# views.py
posts = Post.objects.order_by('-pk')
<h3>{{ article.user.username }}</h3>

개선 후 (1번)

# views.py
Post.objects.select_related('user').order_by('-pk')
<!-- 변경 없음 -->
<h3>{{ article.user.username }}</h3>

prefetch_related는 python을 통한 join으로 데이터를 가져온다

M:N, 1:N 관계에서 역참조 관계 (1->N)

개선 전 (11번)

# views.py
posts = Post.objects.order_by('-pk')

<div data-gb-custom-block data-tag="for">

 <p>{{ comment.content }}</p>

</div>

개선 후 (2번)

posts = Post.objects.prefetch_related('comment_set').order_by('-pk')
<!-- 변경 없음 -->

<div data-gb-custom-block data-tag="for">

 <p>{{ comment.content }}</p>

</div>

4. 게시글마다 작성자 이름과 댓글들 출력

개선 전 (111번)

# views.py
posts = Post.objects.order_by('-pk')

<div data-gb-custom-block data-tag="for">

 <p>{{ comment.user.username }} : {{ comment.content }}</p>

</div>

개선 후 (2번)

# views.py
from django.db.models import Prefetch

posts = Post.objects.prefetch_related(
     Prefetch('comment_set'),
  queryset=Comment.objects.select_related('user')
 ).order_by('-pk')

<div data-gb-custom-block data-tag="for">

 <p>{{ comment.user.username }} : {{ comment.content }}</p>

</div>

SQL Join

ex)

-- 게시글(A) + 댓글(B)
SELECT * FROM article
LEFT OUTER JOIN comment
ON article.id = comment.article_id;

-- 게시글(A) + 사용자
SELECT * FROM article
INNER JOIN user
ON article.user_id = user.id;

+

Gravata 활용하여 profile photo 설정하기

https://en.gravatar.com/site/implement/

방법 1) @property 설정

accounts > models.py

from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractUser
import hashlib

# Create your models here.
# model은 필요없다! Django package에 있는 User를 사용할 것이기 때문!

# 사용자 정의 모델 만들기
class User(AbstractUser):
    followers = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name = 'followings'
    )

    @property
    def gravatar_url(self):
        return f"https://s.gravatar.com/avatar/{hashlib.md5(self.email.encode('utf-8').strip().lower()).hexdigest()}?s=50&d=mp"

방법 2) templatetags 만들기

accounts > templatetags > gravatar.py

import hashlib
from django import template
from django.template.defaultfilters import stringfilter

register = template.Library()

@register.filter
@stringfilter
def profile_url(email):
    return f"https://s.gravatar.com/avatar/{hashlib.md5(email.encode('utf-8').strip().lower()).hexdigest()}?s=50&d=mp"
  • templatetags directory 안에 ___init__.py 만들어야 함!

Templates

templates > _nav.html


<div data-gb-custom-block data-tag="load"></div>

...
<!--방법 1-->                  
<img src="{{request.user.email|profile_url}}">

<!--방법 2-->
<img src="{{request.user.gravatar_url}}">
          
...          

Last updated