DAY56
DAY56

flask 로그분석기 사이트 만들기

0. 기본설정
경로
c:\projects\flask\security\templates\syslog
index.html에 내용 붙이기
(d:\jyb\syslog내용.txt 참고)
후 구조 정리해주기

c:\projects\flask\security\templates\sensor에도 동일하게 구조 정리

c:\projects\flask\security\templates
base.html에서
components에 경로 지정해주기
{{url_for('syslog.index')}}
{{url_for('sensor.index')}}

1. 로그인 기능 만들기


ci4 > mvc (model, view, controller)
flask, django > mtv (model)

c:\projects\flask\security
models.py 생성 #설계도 역할------------
기본틀
class User(db.Model):
	id=db.Column()
	username=db.Column()
	password=db.Column()
	email=db.Column()

구조정리
from security import db

class User(db.Model):
	id=db.Column(db.Integer,primary_key=True) #숫자
	username=db.Column(db.String(150),unique=True,nullable=False) #아이디
	password=db.Column(db.String(200),nullable=False) #비밀번호
	email=db.Column(db.String(120),unique=True,nullable=False)


class Syslog(db.Model):
	id=db.Column(db.Integer,primary_key=True) #숫자
	recievedat=db.Column(db.String(150),nullable=False) 
	fromhost=db.Column(db.String(200),nullable=False) 
	message=db.Column(db.String(120),nullable=False)


class Sensor(db.Model):
	id=db.Column(db.Integer,primary_key=True) #숫자
	distance=db.Column(db.String(150),nullable=False) 
	temperature=db.Column(db.String(200),nullable=False) 
	humidity=db.Column(db.String(120),nullable=False)
	regdate=db.Column*db.DateTime(120),nullable=True)

2. 데이터베이스 연결하기


로그 데이터 : 192.168.0.118 (우분투 > syslog)
센서 데이터 : 192.168.0.98 (Raspbian GNU ; 라즈베리파이)

c:\projects\flask\security
__init__.py에 추가
from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy

db= SQLAlchemy()
migrate = Migrate()

def create_app():
	#ORM(Object Relational Mapping) (데이터베이스 연결)
	#sql > insert,delete,update,select 데이터베이스의 데이터를 처리할 수 있는 기술
	db.init_app(app)
	migrate.init_app(app,db)
	rom . import models

SQLALchemy()
AndoridServer에 동일하게 존재

cmd
pip install Flask-Migrate
flask run

c:\projects\flask\config
default.py
development.py 이해하기


새로운 cmd
set APP_CONFIG_FILE=C:\projects\flask\config\development.py
mysite
#데이터베이스 관련 명령어
flask db init #초기화
flask db migrate #모델로 새로 생성하거나 변경할 때 사용
=>security.db 생성 
flask db upgrade #실제 데이터베이스에 적용
=> db browser for sqlite 프로그램 사용
security.db 열기
테이블 생성 확인가능

#데이터베이스에 접근
flask shell
from security.models import User
(User.query.all() 해보면 [] 확인 가능)
#유저 추가
from datetime import datetime
from security import db
u = User(username='admin',password='123456',email='test@test.com')
db.session.add(u)
db.session.commit()
=> [< User 1>] 확인
=> db sqlite 데이터베이스 탐색란에서도 확인가능


#검색 시
User.query.all() #확인
User.query.filter(User.id==1).all()
User.query.get(1)
User.query.filter(User.username.like("%ad%")).all()

수정
db.session.commit()
삭제
db.session.delete(u)
db.session.commit()

결론
mysql에서 배운 DML(select, update, delete, insert)문을 몰라도 사용할 수 있다.



로그인 페이지 만들기
c:\projects\flask\security\templates\auth
login.html
로그인 처리 부분에 추가
< form class="user" method="post">
#{{form.csrf_token}}
< div class="form-group">
< input type="text" class="form-control form-control-user"
id="username" name="username"
aria-describedby="계정 입력"
placeholder="계정 입력">
< /div>


cmd
flask run
jinja2.exceptions.UndefinedError: 'form' is undefined 에러시
forms.py 만들어주기

c:\projects\flask\security
forms.py
from flask_wtf import FlaskForm
from wtforms import StringField,TextAreaField, PasswordField
from wtforms.validators import DataRequired,Length

class UserLoginForm(FlaskForm):
   username=StringField('아이디',validators=[DataRequired(),Length(min=3,max=15)]) 
   password=PasswordField('비밀번호',validators=[DataRequired()])
=> 유효성 검사
빈칸 안됨, 아이디 최소 3자리, 최대 15자리

c:\projects\flask\security\views
auth.py에 추가
from flask import Blueprint,render_template
from flask import url_for
from flask import flash
from flask import request
from flask import session

from werzeug.security import generate_password_hash
from werzeug.security import check_password_hash

from werkzeug.utils import redirect

from security import db
from security.forms import UserLoginForm


bp = Blueprint('auth',__name__,url_prefix='/auth')

@bp.route('/login',methods=('GET', 'POST'))
def login():
	form = UserLoginForm()
	if request.method== 'POST':
		return render_template('auth/login.html')
	else:
		return render_template('auth/login.html')

cmd
#form을 쓰기 위해 필요
pip install Flask-WTF

기본설치
pip install flask
pip install Flask-Migrate
pip install Flask-WTF
pip install email_validator

c:\projects\flask\security\templates
form_errors.html에 추가
{% for field, errors in form.errors.items() %}
< div>
{{form[field].label}}
< /vid>
{%endfor%}
{% for message in get_flashed_messages() %}
< div>
{{message}}
< /div>
{%endfor%}


***
이해하기
실질적 내용(코딩)
c:\projects\flask\security\view
auth.py
main.py
sensor.py
syslog.py
그외 전부 셋팅 파일
***

3. 로그인 시 특정 페이지를 보이지 않도록 설정


c:\projects\flask\security\templates
base.py

기본틀
{% if g.user %}
{% else %}
{% endif %}

#로그아웃 숨기기							{% if g.user %}
                                < div class="dropdown-divider">
< a class="dropdown-item" href="#" data-toggle="modal" data-target="#logoutModal"> < i class="fas fa-sign-out-alt fa-sm fa-fw mr-2 text-gray-400"> Logout < /a> {% endif %} #목차 숨기기 {% if g.user %} < a class="collapse-item" href="{{url_for('syslog.index')}}">syslog < a class="collapse-item" href="{{url_for('sensor.index')}}">sensor {% endif %} django는 로그인 페이지를 따로 만들지 않아도 기본값으로 설정되어있다. c:\projects\flask\security\views\ auth.py에 추가 from flask import g #로그인한 사용자 정보를 조회하는 기능 구현 @bp.before_app_request def load_logged_in_user(): username = session.get('username') if username is None: g.user = None else: g.user = User.query.get(username) auth.py의 username을 user_id로 변경 c:\projects\flask\config development.py #SQLALCHEMY_DATABASE_URI='sqlite:///{}'.format(os.path.join(BASE_DIR,'security.db')) SQLALCHEMY_DATABASE_URI='mysql+pymysql://master:123456@192.168.0.98/your_database' #app.config('SQLALCHEMY_DATABASE_URI'] = 'mysql+pmysql://master:123456@192.168.0.98/your_database' pip install pymysql flask migration 폴더삭제 flask db init flask db migrate flask db upgrade workbench {{sensor}} #센서 페이지 로그인 후 보이도록 설정 c:\projects\flask\security\views sensor.py datas = Sensor.query.order_by(Sensor.regdate.desc())추가 c:\projects\flask\security\templates\sensor index.html추가 {% if sensor %} {% for data in sensor%} < tr {% if data.distance | float < 500 %}style="background-color: red; color: white;"{% endif %}> < td>{{ data.id }}< /td> < td>{{ data.distance }}< /td> < td>{{ data.temperature }}< /td> < td>{{ data.humidity }}< /td> < td>{{ data.regdate }}< /td> < /tr> {% endfor %} {% else %} < tr> < td colspan=5>데이터 없음< /td> < /tr> {% endif %} 페이징!! c:\projects\flask\security\views sensor.py from flask import Blueprint,render_template, request from security.models import Sensor bp = Blueprint('sensor',__name__,url_prefix='/sensor') @bp.route('/') def index(): page = request.args.get('page', 1, type=int) per_page = 10 datas = Sensor.query.order_by(Sensor.regdate.desc()).paginate(page=page, per_page=per_page, error_out=True) return render_template('sensor/index.html',sensor=datas) c:\projects\flask\security\templates\sensor index.html추가 < !-- 페이지네이션 --> < div class="pagination"> {% if sensor.has_prev %} < a href="{{ url_for('sensor.index', page=sensor.prev_num) }}">이전< /a> {% endif %} < span>페이지 {{ sensor.page }} / {{ sensor.pages }}< /span> {% if sensor.has_next %} < a href="{{ url_for('sensor.index', page=sensor.next_num) }}">다음< /a> {% endif %} < /div>

4. 검색기능 만들기


c:\projects\flask\security\views
sensor.py 추가
@bp.route('/search', methods=('GET','POST'))
def search():
	#STEP1 검색하어를 확인해라

	#STEP2 검색 실행

	#STEP3 검색된 단어를 페이지에 전송하라
   page = request.args.get('page', 1, type=int)
   per_page = 100

   datas = Sensor.query.order_by(Sensor.regdate.desc()).paginate(page=page, per_page=per_page, error_out=True)

   return render_template('sensor/index.html',sensor=datas)

c:\projects\flask\security\templates
base.html 수정
< !-- Topbar Search -->
                    < form
                        class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search" method="get" action="{{url_for('sensor.search')}}">

						< input type="hidden" id="kw" value="{{ kw or ''}}">
						< input type="hidden" id="kw" value="{{ page }}">

                        < div class="input-group">
                            < input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
                                aria-label="Search" aria-describedby="basic-addon2">
                            < div class="input-group-append">
                                < button class="btn btn-primary" type="button">
                                    < i class="fas fa-search fa-sm">< /i>
                                < /button>
                            < /div>
                        < /div>
                    < /form>