56일차

56일차

홈으로 돌아가기


개발자모드
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)