개발자모드
flask run --host=192.168.0.21 --port=5000
CI4 > MVC (model, view, controller)
flask, django > MTV
syslog와 sensor의 데이터를 가져오자
데이터베이스 연결하기
security > models에 추가
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)
receivedat=db.Column(db.String(150),nullable=False)
fromhost=db.Column(db.String(200),nullable=False)
message=db.Column(db.String(500),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(),nullable=True)
security > init에 추가
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
migrate = Migrate()
#ORM (데이터베이스연결)
db.init_app(app)
migrate.init_app(app,db)
from .import models
윈도우에 추가 설치해주기
pip install Flask-Migrate
데이터베이스 관련 명령어
flask db init : 초기화
flask db migrate : 모델로 새로 생성하거나 변경할 때 사용
flask db upgrade : 실제 데이터베이스에 적용
데이터베이스에 접근
flask shell
from security.models import User
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.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 )문을 몰라도 사용할 수 있다.
이제 로그인 페이지를 수정
auth의 login
<form class="user" method="post">
{{form.csrf_token}}
<div class="form-group">
<input type="email" class="form-control form-control-user"
id="username" name="username" aria-describedby="계정입력"
placeholder="계정입력">
</div>
<div class="form-group">
<input type="password" class="form-control form-control-user"
id="password" name="password" placeholder="비밀번호">
form is undefiend
flask,Django에서는 form을 쓸때 알려줘야함
form > 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()])
[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 werkzeug.security import generate_password_hash
from werkzeug.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/loginx.html')
else:
return render_template('auth/login.html')
@bp.route('/mypage')
def mypage():
return render_template('auth/mypage.html')
#return 'init'
@bp.route('/logout')
def logout():
return render_template('auth/logout.html')
@bp.route('/signup')
def signup():
return render_template('auth/signup.html')
@bp.route('/find')
def find():
return render_template('auth/find.html')
[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%}
{% if g.user %}
{% else %}
{% endif %}
sensor 연결하기
development.py
from config.default import *
#SQLALCHEMY_DATABASE_URI='sqlite:///{}'.format(os.path.join(BASE_DIR,'security.db'))
SQLALCHEMY_DATABASE_URI='mysql+pymysql://master:123456@192.168.0.98/master'
#app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://your_user:your_password@localhost/your_database'
SQLALCHEMY_TRACK_MODIFICATIONS=False
SECRET_KEY="dev"
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)
index.html
{% extends 'base.html' %}
{% block content %}
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">실시간 서버실 센서 현황</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>번호</th>
<th>초음파</th>
<th>온도</th>
<th>습도</th>
<th>날짜</th>
</tr>
</thead>
<tbody>
{% 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 %}
</tbody>
<tfoot>
<tr>
<th>번호</th>
<th>초음파</th>
<th>온도</th>
<th>습도</th>
<th>날짜</th>
</tr>
</tfoot>
</table>
</div>
<!-- 페이지네이션 -->
<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>
</div>
</div>
{% endblock %}
검색만들기
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" id="searchForm" method="get" action="{{url_for('sensor.search')}}">
<input type="hidden" id="kw" value="{{ kw or ''}}">
<input type="hidden" id="page" 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="submit">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
sensor.py
@bp.route('/search',methods=('GET','POST'))
def search():
#step1 검색어를 확인해라
kw = request.args.get('kw',type=str,defualt='')
datas = Sensor.query.order_by(Sensor.regdate.desc())
#step2 검색해라
if kw:
search = ''.format(kw)
datas = datas.filter(Sensor.distance.ilike(search)|
Sensor.temperatue.ilike(search)|
Sensor.humidity.ilike(search)|
Sensor.regdate.ilike(search)
).distinct()
#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)
#@bp.route('/search', methods=['GET','POST'])
#def search():
#
# # GET 방식으로 받은 검색어
# query = request.args.get('query', '', type=str)
#
# # 페이지 번호 및 페이지당 항목 수
# page = request.args.get('page', 1, type=int)
# per_page = 10
#
# # 검색어가 있을 경우 해당하는 데이터를 필터링
# if query:
# datas = Sensor.query.filter(Sensor.distance.like(f"%{query}%"))
# else:
# datas = Sensor.query # 검색어가 없으면 모든 데이터를 가져옴
#
# # 페이지네이션 적용
# datas = datas.order_by(Sensor.regdate.desc()).paginate(page=page, per_page=per_page, error_out=True)
#
#
# return render_template('sensor/index.html', sensor=datas, query=query)