Django, 저는 이렇게 씁니다.

46
Django, 저는 이렇게 씁니다. 알파카코믹스를 개발하면서.

Transcript of Django, 저는 이렇게 씁니다.

Page 1: Django, 저는 이렇게 씁니다.

Django, 저는 이렇게 씁니다.알파카코믹스를 개발하면서.

Page 2: Django, 저는 이렇게 씁니다.

안녕하세요. 풀 스택 개발자 파이입니다.

스마트스터디에서 일하고 있습니다.

진짜로 서버 조립에서 디자인까지 해봄

Page 3: Django, 저는 이렇게 씁니다.

Django로 먹고 살아온 세월 5년

5년이면 많이 알겠네요?!

해본 것도 기억 못해요…

Page 4: Django, 저는 이렇게 씁니다.

발표 왜 하세요?

일 만하다 보니 제가 뭐하고 있나 싶었어요.

기억력이 안 좋아서 방금 짠 코드도 까먹습니다.

잊기 전에 뭐라도 남기고 싶었습니다.

아는 것도 별로 없지만 막상 적으려면 더 없어요. OTL

해본 거

아는 거

발표

탐험이 필요한미지의 영역

Page 5: Django, 저는 이렇게 씁니다.

Django 왜 쓰나요?

할 일은 많고 사람은 없을 때.

시간도 없을 때.

귀찮을 때.

Page 6: Django, 저는 이렇게 씁니다.

알파카코믹스를 개발하면서

만들면서 겪은 문제들을

어떻게 해결(땜빵)했는지

간략하게 이야기해보겠습니다.

Page 7: Django, 저는 이렇게 씁니다.

프로젝트를 시작할 때신경 쓰는 게 신상에 이롭습니다.

Page 8: Django, 저는 이렇게 씁니다.

모델이 제일 중요합니다.

모든 것의 근원, 데이터의 흐름

가장 오랫동안 고민해도 부족하지 않습니다.

많은 연습을 필요로 합니다.

Page 9: Django, 저는 이렇게 씁니다.

모듈을 용도 별로 나누세요.

천 줄 짜리 코드를 나중에 다시 열면

내가 짠 거 알면서도 욕이 나옵니다.

모델에 기초해서 어떻게 하든 나누세요.

Page 10: Django, 저는 이렇게 씁니다.

예) 프로젝트 레이아웃

/alpaca/comic/profile/...

/conf/production

/settings.py/testing

앱 내부

배포 환경에 따른 세팅

Page 11: Django, 저는 이렇게 씁니다.

Python 가상 환경은 선택이 아닌 필수

pyenvhttps://github.com/yyuu/pyenv

virtualenv wrapperhttps://pypi.python.org/pypi/virtualenvwrapper

Page 12: Django, 저는 이렇게 씁니다.

{ "name": "alpacacomics", "dependencies": { "jquery": "1.9.1", ….. }}

Front-end는 Bower로 관리

bower.json

{"directory":"alpaca/static/components"}

.bowerrc

$ bower update

Page 13: Django, 저는 이렇게 씁니다.

User에 cash 넣을래요.

Page 14: Django, 저는 이렇게 씁니다.

Profile Model과 OneToOneField

profile/models.py class Profile(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL) cash = models.IntegerField(defalut=0)

user.profile.cash 로 접근

http://perhapsspy.wordpress.com/2013/02/18/a-simple-way-how-to-extend-user-model-in-django-1-5/

Page 15: Django, 저는 이렇게 씁니다.

Profile 모델에 관련 함수 모으기

캐시 충전캐시 환불스토어 별 캐시

ex) user.profile.cash_charge(...)

Page 16: Django, 저는 이렇게 씁니다.

장점

다른 라이브러리와 충돌 걱정 없다.관리도 쉽다.구현이 제일 쉽다.

2가지 방법이 더 있으나 쉬운 게 최고…..는 아니고 상황에 맞게 찾아 쓰세요.

Page 17: Django, 저는 이렇게 씁니다.

소셜 로그인이 필요해요.

Page 18: Django, 저는 이렇게 씁니다.

Django-allauth

이름처럼 모든 것을 해줌.

일반 가입, 소셜 로그인 및 관리,이메일 인증, 비밀번호 찾기, 등.

단, 한글은 직접 .po 파일을 만들어야...(or template)잘 쓰려면 adepter도 고치고...

Page 19: Django, 저는 이렇게 씁니다.

template을 적당히 고쳐서 쓰면 그럴 듯합니다.

Page 20: Django, 저는 이렇게 씁니다.

ajax 지옥...

스크롤을 내리면 이어지게

Page 21: Django, 저는 이렇게 씁니다.

HTML을 조각조각 따따따

template_name = ‘item_list.html’if request.is_ajax():

template_name = ‘_item.html’

javascript는 최대한 단순하게.하지만 아무래도 귀찮다.

맘에 들게 널 다시 조립할거야

Page 22: Django, 저는 이렇게 씁니다.

CBV로 한번 만들고 계속 쓰자.

반복 작업을 싫어하시는 당신을 위한CBV - Class Based View만들어둔 Class를 조립해서 쓴다.

https://docs.djangoproject.com/en/1.7/topics/class-based-views/

Page 23: Django, 저는 이렇게 씁니다.

Mixin을 써보자class ChangeTemplateMixin(object):

# ajax 요청이 들어오면 template 변경

class MoreListMixin(ChangeTemplateMixin): # 무한 스크롤 구현

class CashUseLogView(MoreListMixin, ListView):# 위의 믹스인을 합쳐서 날로 먹기

class CashChargeLogView(MoreListMixin, ListView):# 계속해서 날로 먹기

Page 24: Django, 저는 이렇게 씁니다.

이렇게 됩니다.

Page 25: Django, 저는 이렇게 씁니다.

RESTful API가 필요한데요.

Page 26: Django, 저는 이렇게 씁니다.

Django REST framework

기능이 엄청 많습니다.CBV로 API를 만들 수 있습니다.즉, 모델만 잘 짜두면 순식간에 만듭니다.단순한 API는 1~2시간이면 뚝딱.

하지만 속도가 느리다는 게 함정.

자세한 설명은 문서 참고하세요 . 최근에 3.0까지 나왔습니다 .http://www.django-rest-framework.org/

Page 27: Django, 저는 이렇게 씁니다.

DB와 Cache로 해결해봅시다.

사이트가 느려요.

Page 28: Django, 저는 이렇게 씁니다.

DB 쿼리 최적화

두 가지만 기억하세요.

select_related - Foreign-key 관계prefetch_related - Many to Many 관계

여러 쿼리를 join으로 합쳐줍니다.

222쿼리가 2쿼리로 줄어드는 마법이 벌어집니다.

Page 29: Django, 저는 이렇게 씁니다.

예) DB 쿼리 최적화

Comic.objects.all().select_related(‘author’) \.prefetch_related(‘tags’)

Product.objects.get(id=1).select_related(‘episode’, ‘episode__comic’)

Page 30: Django, 저는 이렇게 씁니다.

CBV는 어떻게 쿼리 최적화 하나요.class CashUseLogView(MoreListMixin, UserFilterMixin, ListView): model = CashUseLog template_name = 'cash/use_log.html' ajax_template_name = 'cash/_use_log.html' def get_queryset(self): return super(CashUseLogView, self).get_queryset() \ .select_related('product', 'product__episode__comic', 'product__episode')

class ComicDetail(MoreListMixin, ProductsMixin, SingleObjectMixin, ListView): def get(self, request, *args, **kwargs): queryset = Comic.objects.all() \ .select_related('author', 'category') \ .prefetch_related('tags') self.object = self.get_object(queryset=queryset) return super(ComicDetail, self).get(request, *args, **kwargs)

이렇게

Page 31: Django, 저는 이렇게 씁니다.

Cache를 바릅니다.

View, Template 등을 상황에 맞춰 적당히(!?!)

Cache의 핵심어느 타이밍에 갱신할 것인가?

Page 32: Django, 저는 이렇게 씁니다.

class Comic(models.Model):…def save(....):

cash_update()

데이터가 변하면 갱신하자.

Page 33: Django, 저는 이렇게 씁니다.

class Comic(CacheDeleteModel, models.Model):…def save(....):

cash_update()

이것도 Class로 만들어 두고 조립.

Page 34: Django, 저는 이렇게 씁니다.

Django-compressor

staic 파일들을 압축해준다.

STATICFILES_FINDERS = ( ... "compressor.finders.CompressorFinder",)COMPRESS_OFFLINE = TrueCOMPRESS_CSS_FILTERS = {'compressor.filters.cssmin.CSSMinFilter',}COMPRESS_OFFLINE_CONTEXT = {'STATIC_URL': "/static/",}

$ python manage.py compress

https://github.com/django-compressor/django-compressor

Page 35: Django, 저는 이렇게 씁니다.

Admin 페이지 어떻게 써요?

Page 36: Django, 저는 이렇게 씁니다.

예) admin.pyclass ComicAdmin(admin.ModelAdmin): list_display = ['id', 'category', 'name', 'author', 'publisher', 'rating', 'view_count', 'purchase_count', 'active', 'end', release_display, 'recommended', 'weight', 'last_weight', 'login_required_episode', 'episode_count'] list_filter = ['active', 'category', 'rating', 'recommended', 'service_ext'] list_editable = ['recommended', 'weight', 'last_weight', 'login_required_episode'] raw_id_fields = ['author', 'publisher', 'tags'] readonly_fields = ['view_count', 'purchase_count', 'episode_count'] def get_queryset(self, request): return super(ComicAdmin, self).queryset(request) \ .select_related('category', 'author', 'publisher')

admin.site.register(Comic, ComicAdmin)

쿼리 최적화

def release_display(instance): if instance.release: return instance.release.strftime('%y.%m.%d %H:%M') return instance.releaserelease_display.admin_order_field = 'release'release_display.short_description = u'출시일시'

Page 37: Django, 저는 이렇게 씁니다.

예) Admin 화면

아래와 같이 대충 쓸 만해집니다.

Page 38: Django, 저는 이렇게 씁니다.

기타 다른 Admin 설정

list_display_links : 목록에서 누를 수 있는 링크가 되는 필드list_per_page : 목록의 아이템 수date_hierarchy : 지정한 날짜 필드 기준 필터 생성ordering : 순서search_fields : 검색 대상 필드

Page 39: Django, 저는 이렇게 씁니다.

배포는?

Page 40: Django, 저는 이렇게 씁니다.

제가 자주 씁니다.

OS : UbuntuWeb Server : NginxApp Server : uWSGIDjango Version : 1.7+Database : Mysql or Postgresql

설정하기 쉽다는 공통점이 있습니다.

Page 41: Django, 저는 이렇게 씁니다.

간단한 스크립트.

git pullcp nginx.conf /etc/nginx/site-enabled/apppip install -r requirements.txtbower updatepython manage.py collectstaticservice nginx reloadservice uwsgi reload

Page 42: Django, 저는 이렇게 씁니다.

사실 Docker 쓰고 있어요.

방금 전 스크립트는 Dockerfile 흉내.

Docker registry (회사 전용)

Gadget (배포 도구)

Page 43: Django, 저는 이렇게 씁니다.

힘들어서 여기까지만.

요약하겠습니다.

Page 44: Django, 저는 이렇게 씁니다.

그러니까,

● 모델이 제일 중요합니다.● User 모델 확장은 OneToOne● 소셜 로그인은 Django-allauth● 반복 작업은 CBV● DB최적화는 select_related, prefetch_related● Cache는 컨트롤이 중요● Admin는 django 핵심 기능입니다.

Page 45: Django, 저는 이렇게 씁니다.

더 많은 것을 담아보려다체력이 고갈 되어 질문으로 넘어갑니다.

질문 받습니다.

Page 46: Django, 저는 이렇게 씁니다.

끝.

감사합니다.