404 혹은 500의 오류 페이지를 불러올 경우, 우리가 만들어둔 화면이 나오도록 설정할 수 있는 기능을 Flask에서 지원한다.

 

 

 

1. 사용자 정의 오류 처리기 추가

가장 일반적인 404 & 500 에러에 대한 오류 페이지를 정의해보겠다.

# vim app/errors.py

# Flask는 자체 오류 페이지를 설정할 수 있는 메커니즘을 제공한다.

from flask import render_template
from app import app, db

@app.errorhandler(404)
def not_found_error(error):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_error(error):
    # 사용자 이름이 중복되는 등의 DB와 연결 중 500 에러 발생시, 정상적으로 이전 작업이 종료되지 않을 수 있어 rollback을 추가
    db.session.rollback()
    return render_template('500.html'), 500

 

 

 

2. 템플릿 만들어주기

<!-- vim app/templates/404.html -->

<!-- 템플릿 찾을 수 없음 -->

{% extends "base.html" %}

{% block content %}
    <h1>File Not Found</h1>
    <p><a href="{{ url_for('index') }}">Back</a></p>
{% endblock %}
<!-- vim app/templates/500.html -->

<!-- 내부 서버 오류 템플릿 -->

{% extends "base.html" %}

{% block content %}
    <h1>An unexpected error has occurred</h1>
    <p>The administrator has been notified. Sorry for the inconvenience!</p>
    <p><a href="{{ url_for('index') }}">Back</a></p>
{% endblock %}

 

 

 

3. 오류 처리기를 Flask에 등록하기 위해 app에서 errors 모듈 불러오기

# vim app/__init__.py

# ...
# 오류 처리 기능 호출
from app import errors

 

 

 

4. 이메일 구성 설정

# vim config.py

class Config(object):
    # ...
    # 이메일 구성
    MAIL_SERVER = os.environ.get('MAIL_SERVER')
    MAIL_PORT = int(os.environ.get('MAIL_PORT') or 25)
    MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None
    MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
    MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
    ADMINS = ['your-email@example.com']

 

 

 

5. 이메일로 오류 기록

# vim app/__init__.py

# ...

# 웹서버에서 발생하는 Log 정보를 지정해둔 메일로 발송하는 기능을 추가해, 모니터링함
import logging
from logging.handlers import SMTPHandler

if not app.debug:
    if app.config['MAIL_SERVER']:
        auth = None
        if app.config['MAIL_USERNAME'] or app.config['MAIL_PASSWORD']:
            auth = (app.config['MAIL_USERNAME'], app.config['MAIL_PASSWORD'])
        secure = None
        if app.config['MAIL_USE_TLS']:
            secure = ()
        # SMTPHandler 인스턴스 추가하여 이메일 전송 설정
        mail_handler = SMTPHandler(
            mailhost=(app.config['MAIL_SERVER'], app.config['MAIL_PORT']),
            fromaddr='no-reply@' + app.config['MAIL_SERVER'],
            toaddrs=app.config['ADMINS'], subject='Microblog Failure',
            credentials=auth, secure=secure)
        mail_handler.setLevel(logging.ERROR)
        app.logger.addHandler(mail_handler)

 

 

 

6. python의 smtp 디버깅 서버로 TEST

$ python -m smtpd -n -c DebuggingServer localhost:8025

 

 

 

7. Gmail 계정 이메일 서버 사용하여 TEST

아래 커맨드를 서버에 직접 입력해도 되고, /etc/profile 파일에 입력해준 후 적용해주는 방법으로도 대체 가능하다.

$ source /etc/profile

export MAIL_SERVER=smtp.googlemail.com
export MAIL_PORT=587
export MAIL_USE_TLS=1
export MAIL_USERNAME=<your-gmail-username>
export MAIL_PASSWORD=<your-gmail-password>

 

 

 

8. 파일에 로깅하는 기능 추가

# vim app/__init__.py

# 웹서버에서 발생하는 Log 정보를 지정해둔 메일로 발송하는 기능을 추가해, 모니터링함
import logging
from logging.handlers import SMTPHandler
from logging.handlers import RotatingFileHandler
import os
if not app.debug:
    
    # ...

    # 파일에 로깅
    if not os.path.exists('logs'):      # logs 디렉토리 없을 경우 생성
        os.mkdir('logs')
    # log 파일 정보 설정 : log파일 크기 10KB 제한, 최근 10개 로그 파일을 백업으로 유지
    file_handler = RotatingFileHandler('logs/microblog.log', maxBytes=10240,
                                       backupCount=10)
    # log 메시지에 대한 사용자 정의 형식 제공
    file_handler.setFormatter(logging.Formatter(
        '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
    # DEBUG, INFO, WARNING, ERROR, CRITICAL
    file_handler.setLevel(logging.INFO)
    app.logger.addHandler(file_handler)
    app.logger.setLevel(logging.INFO)
    app.logger.info('Microblog startup')

 

 

 

9. 프로필 편집 양식에서 사용자의 이름을 확인하는 절차 추가

# 프로필 편집기 양식
class EditProfileForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    about_me = TextAreaField('About me', validators=[Length(min=0, max=140)])
    submit = SubmitField('Submit')
    # 현재 사용자 정보를 가져옴
    def __init__(self, original_username, *args, **kwargs):
        super(EditProfileForm, self).__init__(*args, **kwargs)
        self.original_username = original_username
    # 프로필 편집 양식에서 사용자의 이름을 확인
    def validate_username(self, username):
        if username.data != self.original_username:
            user = User.query.filter_by(username=self.username.data).first()
            if user is not None:
                raise ValidationError('Please use a different username.')

 

 

 

10. 프로필 편집 양식에서 사용자의 이름을 확인하는 절차 추가

 

# vim app/routes.py

# ...

# 프로필 뷰 편집 기능
@app.route('/edit_profile', methods=['GET', 'POST'])
@login_required
def edit_profile():
    form = EditProfileForm(current_user.username)       # 프로필 편집 양식에서 사용자의 이름을 확인
    
    # ...

 

 

 

+ Recent posts