티스토리 뷰

Developer

[Django#4] Digging up Django

rocksea 2015. 10. 10. 17:35

Django 파헤치기.



Django ORM을 이용하여 서비스를 개발 중에 필수적으로 알아야할 기능들에

대해 정리해보고자 한다. 다양한 플랫폼과 프레임웍을 사용해 봤지만 Django

의 파워풀한 기능에 감탄을 연발 할 수 밖에 없었다. 기본적으로 User와 Group,

Permission에 대한 구조가 미리 생성되기 때문에 설계에 대한 고민을 할 필요가 

없었다. ( Java의 Spring Security등에 비해 Simple하게 설계 되어있다 )


1. 인증

CSRF(CrossSite Request Forgery) Token에 대한 인증, SessionID에 대한 인증이

굉장히 심플하게 구현이 가능하다. 아래 예제를 통해 확인해 보도록 하자.


Client(HTML Template)

<form action="/users/login_action" method="POST">     
{% csrf_token %}
</form>


Server

from django.views.decorators.csrf import csrf_exempt @csrf_exempt #csrf token 체크 Decorator def loginAction(request): return render(request,'page.html')


유저 Session 인증 또한 심플하다.

Username/Password를 이용한 Login인증

from django.contrib.auth import authenticate, login

def loginAction(request):                                                                
  if request.POST:
    username = request.POST.get('username')
    password = request.POST.get('password')

    user = authenticate(username=username, password=password) #인증 함수
    if user is not None:
      if user.is_active:  
        login(request, user) #로그인 처리
    ...


Login 체크 Decorator 및 Logout 처리

from django.contrib.auth import logout

@login_required #로그인 체크 Decorator
def logoutAction(request):
  logout(request) 
  ...


2. Middleware


Middleware에 대한 구조를 이해하고 잘 활용 한다면, 좀 더 효과적인 어플리케이션 

설계가 가능하다.

Request, Response에 처리 시 거치는 Middleware에 대한 이해를 돕기위한 예제하나를

설명한다.

setting.py의 Middleware Class 추가

MIDDLEWARE_CLASSES = (
    'app.middleware.CustomMiddleware', #Adding Custom Middleware
    'django.contrib.sessions.middleware.SessionMiddleware',                               
    'django.middleware.common.CommonMiddleware',                                          
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',                               
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
)       


Custom Middleware를 이용하여,  필터등에 대한 처리를 구현 할 수 있다.

Request에 대한 처리는 process_request(self, request)

Response에 대한 처리는  process_response(self, request, response)

Exception 처리는 process_excpetion(self, request, exception) 함수에서 처리가 

가능하다.


CustomMiddleware.py

class CustomMiddleware(object):
  def __init__(self):    
    #...   
    pass

  def process_request(self, request):
    #...
    pass

  def process_exception(self, request, exception):
    #...
    pass

  def process_response(self, request, response):
    #...
    return response


3. Logger

모든 Application 개발 시 빠질 수 없는 Logging에 대한 부분도 탄탄하게 지원한다.

Java, Node.js등 개발시 log4j, winston등과 별반 다를건 없지만, 기본적으로 내장되어

있다는 점에서 매우 편리하다고 볼 수 있다.

setting.py 설정

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(asctime)s %(module)s %(message)s' },
    },
    'filters': {
        'special': {
            #'()': 'project.logging.SpecialFilter',
            'foo': 'bar',
        }
    },
    'handlers': {
        'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },                                                                                
        'mail_admins': {                                                                  
            'level': 'ERROR',                                                             
            'class': 'django.utils.log.AdminEmailHandler',                                
            'filters': ['special']                                                        
        },                                                                                
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'formatter': 'simple',
            'filename': LOG_PATH,
            'class':'logging.handlers.RotatingFileHandler',
            'maxBytes': 1024*1024*50, # 50MB 
            'backupCount': 7,
        },
    },
    'loggers': {
        'django': {
            'handlers': ['null'],
            'propagate': True,
            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
        },
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': False,
        },
        'trabi': {
            'handlers': ['console','file'],
            'level': 'INFO',
            #'filters': ['special'],
            'propagate': True,
        }
    }
}
import logging.config
logging.config.dictConfig(LOGGING)


logging 예제

import logging

def process_request(self, request):
  logger.info("REQUEST : %s " % request)


Filter 적용 방법

filter란 말그대로 logging handler의 내용을 필터링하여 남겨야 할 로그, 남기지 말하야할 

로그를 필터링할 수 있는 기능을 말한다. boolean값을 Return하여 True일경우 log를 

남기고 false일 경우 남기지 않는다. 또한 custom parameter를 생성하여 처리가 가능하다.


Log filter setting

LOGGING = { ... 'filters': { 'special': { '()': 'app.logfilter.SpecialFilter', 'foo' : 'bar', } }, 'loggers': { 'app': { 'handlers': ['console','file'], 'level': 'INFO', 'filters': ['special'], 'propagate': True, } }


logfilter.py  Class file

import logging 

class SpecialFilter(logging.Filter):
  def __init__(self, foo) :
    print foo
            
  def filter(self, record) :
    print "##### RECORD : %s " % str(record)
    if 'Not Found' in str(record) :
      print "##### Find it : %s " % str(record)
      return False            
    return True

 

Log 내용 중 'Not Found' 문자를 포함하고 있는 Log들에 대해 로그를

남기지 않는다.  또한 설정의 foo 인자를 init 함수에서 받아 처리 가능하다.


4. Cron Scheduler

django_crontab, django_cron 두가지 방법에 대해 테스트를 진행하였다.

이들은 실제 os상의 crontab에 등록하여 동작하도록 설계되어있다.

(개인적으로 django_crontab 사용이 간단하여 이방법을 사용한다.)


방법1. dango_crontab 설치

$ pip install django_crontab


cronjob 함수 작성

def testCronJob(self):

...

pass


setting.py

INSTALLED_APPS = [ # ... "django_crontab", ] CRONJOBS = [ ('*/5 * * * *','app.cron.testCronJob' )

]


cron 등록, 조회 및 삭제


(rocksea) $ python manage.py crontab add


(rocksea) $ python manage.py crontab show


(rocksea) $ python manage.py crontab remove




실제 add 후 crontab 명령을 통해 등록확인을 하도록 한다.


(rocksea) $ crontab -l


* * * * * /Users/rocksea/.virtualenvs/rocksea/bin/python /Users/rocksea/work/apps/manage.py crontab run 5f7d9731955a29bc1abcbbae576caef2 # django-cronjobs for apps



방법2. dango_cron 설치

$ pip install django_cron


app/cron.py
from django_cron import CronJobBase, Schedule

class MyCronJob(CronJobBase):
    RUN_EVERY_MINS = 1 # every 2 hours
    
    schedule = Schedule(run_every_mins=RUN_EVERY_MINS)
    code = 'app.my_cron_job'    # a unique code
    
    def do(self):
      print "### CRON_TEST"

 cron scheduler에 의해 동작 할 코드를 작성하고 시간을 등록한다.

setting.py
INSTALLED_APPS = [
    # ...
    "django_cron",
]

CRON_CLASSES = [
 "app.cron.MyCronJob",
]


마지막으로 cron scheduler에 실행 명령을 등록한다.

django scheduler는 다른 데몬 형태의 scheduler와 다르게 os상의 scheduler에 의해 

실행되고 cron 실행 시 등록 시간 범주에 들어올 경우에만 실행함수를 호출한다.

> crontab -e
*/5 * * * * source /home/ubuntu/.bashrc && source /home/ubuntu/work/your-project/bin/activate && python /home/ubuntu/work/your-project/src/manage.py runcrons > /home/ubuntu/cronjob.log


(rocksea) $ python manage.py runcrons


### CRON_TEST



이상 Django의 주요 패키지에 대해 알아보았다.


댓글