html

<textarea id="textarea_summernote" name="textarea_summernote">
  textarea 내용 입력
</textarea>

javascript

html에서 생성한 textarea_summernote textarea를 summernote()를 사용하여 초기화 진행

이미지 파일 처리를 위해 onImageUpload 함수 등록

uploadSummernoteImageFile 함수에서 첨부한 파일 정보를 ajax를 이용하여 flask로 전달하여 저장소에 저장

setSummernoteValue 함수는 Summernote에 값을 추가하는 예시

// summernote 초기화
$(function () {
    // Summernote
    $('#textarea_summernote').summernote({
        callbacks : {
            // 이미지 첨부하는 부분
            onImageUpload : function(files){
                uploadSummernoteImageFile(files[0],this);
            },
            onPaste : function(e) {
                var clipboardData = e.originalEvent.clipboardData;

                if(clipboardData && clipboardData.items && clipboardData.items.length){
                    var item = clipboardData.items[0];
                    if(item.kind === 'file' && item.type.indexOf('image/') !== -1){
                        e.preventDefault();
                    }
                }
            }
        }
    });  
});


// summernote - 이미지 파일 업로드
function uploadSummernoteImageFile(file, editor){

    // 프로젝트 코드
    var project_code = 'test'
    
    var data = new FormData();
    data.append('file',file);
    data.append('project_code', project_code);

    //file 정보를 python으로 전달
    $.ajax({
        data: data,
        type : "POST",
        url : "/test/uploadSummernoteImageFile",
        contentType : false,
        processData : false,
        success : function(data){
            alert('File Upload Success')
            $(editor).summernote('insertImage', data.filepath);
        }
    });
}


function setSummernoteValue(value) {

    // value가 문자열인 경우
    $('#textarea_summernote').summernote('insertText', value);
    
    // value가 html 태크 형태인 경우
    $('#textarea_summernote').summernote('pasteHTML', value);
}

python

프로젝트 코드(또는 메뉴등의 그룹)별 파일을 저장하기 위해 폴더에 서비스 코드 추가

파일명이 겹치지 않도록 파일명 앞에 현시간을 추가

@project_blueprint.route('test/uploadSummernoteImageFile', methods =['POST'])
@login_required
def project_test_uploadSummernoteImageFile():

    try :
        file = request.files['file']
        project_code = request.form['project_code']
        default_path = 'test/img/'

        host_path = default_path + project_code + '/'
        if not os.path.exists(host_path):
            os.mkdir(host_path)

        now_date = datetime.datetime.now()
        prefix_date = now_date.strftime('%Y%m%d_%H%M%S_')

        img_name = host_path + prefix_date + file.filename
        file.save(img_name)

        return jsonify(filepath = img_name[3:])

    except (RuntimeError, TypeError, NameError, SQLAlchemyError) as e:
        print("#### img upload Failed !! " + str(e))

        return jsonify(message=str(e))

참고

https://summernote.org/deep-dive/#pastehtml

조건

flask 환경에서 in 을 사용하여 검색

방법

flask에서 변수를 받을때 리스트 형태( getlist('ip_group[]' )로 받음

sql 쿼리에 매개변수 전달 시, 리스트 형태를 전달

[html]

<select class="select2" multiple="multiple" name="ip_group[]" id="ip_group" />
  <option value="127.0.0.1">127.0.0.1</option>
  <option value="127.0.0.2">127.0.0.2</option>
</select>


[js]

var ip_group = $('#ip_group').val();

$.ajax({
        url:'/project/server_info',
        type:'POST',
        data: {ip_group:ip_group},
        success: function(data){
           showAlert('Server Info', data.info, 2, 2000);
       }     


[python + flask]

@project_blueprint.route('project/server_info', methods=['POST'])
@login_required
def project_server_info():
    ip_group = request.form.getlist('ip_group[]')
    
    ql = text('select a, b, c, d, e from tblServer where ip in :ip_group')
    connection = db.session.connection()
    results = db.engine.execute(sql, ip_group=ip_group)
    
    if results != None:
        details = []
        
        for r in results:
            details.append(r[0])
            details.append(r[1])
            details.append(r[2])
            details.append(r[3])
            details.append(r[4])
            
        return jsonify(details=details)

참고

https://stackoverflow.com/questions/8603088/sqlalchemy-in-clause

Python flask

test edit : db 데이터 수정 이후, 실행 결과를 리턴

test list : db의 table 조회 이후, 여러 행을 리스트 형태로 리턴

test detail : db 데이터 조회 결과가 1건인 경우, json 형태로 리턴

from flask import render_template, request, flash, redirect, url_for, Blueprint, Markup, jsonify, session, make_response
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text, update
from sqlalchemy.exc import SQLAlchemyError

@bts_blueprint.route('test/edit', methods=['POST'])
def test_edit():

    print("## test_edit ##")

    try:
        # 처리 변수
        numId = request.form['id']
        strName = request.form['name']

        # 처리 로직
        sql = text('update tblTest set name = :strName where id = :numId')
        connection = db.session.connection()
        db.engine.execute(sql, numId=numId, strName=strName)
                
        return jsonify(message="Edit Success"), 200

    except (RuntimeError, TypeError, NameError, SQLAlchemyError) as e:
        print("#### Edit Failed !! " + str(e))
        db.session.rollback()

        return jsonify(message=str(e)), 1000
        
        
@bts_blueprint.route('test/list', methods=['POST'])
def test_list():

    print("## test_list ##")

    # 처리 변수
    numId = request.form['id']

    # 처리 로직
    sql = text('select a, b, c, d, e from tblTest where id > :numId')
    connection = db.session.connection()
    results = db.engine.execute(sql, numId=numId)
                
    return render_template('test.html', results=list(results))


@bts_blueprint.route('test/detail', methods=['POST'])
def test_detail():

    print("## test_detail ##")

    # 처리 변수
    numId = request.form['id']

    # 처리 로직
    sql = text('select a, b, c from tblTest where id = :numId')
    connection = db.session.connection()
    results = db.engine.execute(sql, numId=numId)

    if results != None:
        results_detail = {}
        for r in results:
            results_detail['a'] = r[0]
            results_detail['b'] = r[1]
            results_detail['c'] = r[2]
            
    return jsonify(results_detail=results_detail)

javascript

funtion test_edit()
{
    // Test edit
    $.ajax({
        url:'/test/edit',
        type:'POST',
        data: {id:id, name:name},
        success: function(data){
            //Success
            showAlert('Edit Successful!!!', '', 2, 2000);
        },
        error: function(xhr, ajaxOptions, thrownError) {
            var err_msg = JSON.parse(xhr.responseText);

            if (thrownError == 'UNKNOWN'){
                fail_msg = err_msg.message + ' (' + xhr.status + ')'
            } else {
                fail_msg = err_msg.message + ' (' + thrownError + ',' + xhr.status + ')';
            }
            showAlert('Edit Fail...','', 4, 3000);
        }
    });
}


funtion test_list()
{
    // Test list
    $.ajax({
        url:'/test/list',
        type:'POST',
        data: {id:id},
        success: function(data){
            //Success
            for(var key in data){
                console.log(key, data[key]);
            }
            
            showAlert('detail Successful!!!', '', 2, 2000);
        },
        error: function(xhr, ajaxOptions, thrownError) {
            var err_msg = JSON.parse(xhr.responseText);

            if (thrownError == 'UNKNOWN'){
                fail_msg = err_msg.message + ' (' + xhr.status + ')'
            } else {
                fail_msg = err_msg.message + ' (' + thrownError + ',' + xhr.status + ')';
            }
            showAlert('list Fail...','', 4, 3000);
        }
    });
}


funtion test_detail()
{
    // Test detail
    $.ajax({
        url:'/test/detail',
        type:'POST',
        data: {id:id},
        success: function(data){
            //Success
            detail_a = data.results_detail.a
            detail_b = data.results_detail.b
            detail_c = data.results_detail.c
            
            showAlert('detail Successful!!!', '', 2, 2000);
        },
        error: function(xhr, ajaxOptions, thrownError) {
            var err_msg = JSON.parse(xhr.responseText);

            if (thrownError == 'UNKNOWN'){
                fail_msg = err_msg.message + ' (' + xhr.status + ')'
            } else {
                fail_msg = err_msg.message + ' (' + thrownError + ',' + xhr.status + ')';
            }
            showAlert('detail Fail...','', 4, 3000);
        }
    });
}

기능

- yyyy-mm-dd HH:mm:ss 형태로 날짜 데이터 입/출력

- python flask에서 get, post 형태로 날짜 데이터 처리

 

js

<!-- jQuery -->
<script src="/ path /plugins/jquery/jquery.min.js"></script>
<!-- Select2 -->
<script src="/ path /plugins/select2/js/select2.full.min.js"></script>
<!-- InputMask -->
<script src="/ path /plugins/moment/moment.min.js"></script>
<!-- Tempusdominus Bootstrap 4 -->
<script src="/ path /plugins/tempusdominus-bootstrap-4/js/tempusdominus-bootstrap-4.min.js"></script>

css

<!-- Font Awesome -->
<link rel="stylesheet" href="/ path /plugins/fontawesome-free/css/all.min.css">
  
<!-- Select2 -->
<link rel="stylesheet" href="/ path /plugins/select2/css/select2.min.css">
<link rel="stylesheet" href="/ path /plugins/select2-bootstrap4-theme/select2-bootstrap4.min.css">
  
<!-- Tempusdominus Bootstrap 4 -->
<link rel="stylesheet" href="/ Path /plugins/tempusdominus-bootstrap-4/css/tempusdominus-bootstrap-4.min.css">

html

datetimepicker ID : search_start_time, search_end_time

datetime text ID : search_start_input, search_end_input

 

<!-- Start Time -->
<div class="form-group col-md-4">
  <div class="input-group">
	<div class="input-group date" id="search_start_time" data-target-input="nearest">
	  <span class="btn btn-warning iw-100">Start Time</span>
	  <input type="text" data-date-format='yyyy-mm-dd' class="form-control datetimepicker-input" id="search_start_input" name="search_start_input" data-target="#search_start_time"/>
	  <div class="input-group-append" data-target="#search_start_time" data-toggle="datetimepicker">
		  <div class="input-group-text"><i class="fa fa-calendar"></i></div>
		</div>
	</div>
  </div>
</div>

<!-- End Time -->
<div class="form-group col-md-4">
  <div class="input-group">
	<div class="input-group date" id="search_end_time" data-target-input="nearest">
	  <span class="btn btn-warning iw-100">End Time</span>
	  <input type="text" data-date-format='yyyy-mm-dd' class="form-control datetimepicker-input" id="search_end_input" name="search_end_input" data-target="#search_end_time"/>
	  <div class="input-group-append" data-target="#search_end_time" data-toggle="datetimepicker">
		  <div class="input-group-text"><i class="fa fa-calendar"></i></div>
		</div>
	</div>
  </div>
</div>

javascript

datetimepicker ID에 icon 및 format 적용

<script type="text/javascript">
    $(function () {
    
        //값 확인
        start_time = $('#search_start_input').val();
        end_time = $('#search_end_input').val();
    
        //Date and time picker
        $('#search_start_time').datetimepicker({ icons: { time: 'far fa-clock' }, format: 'yyyy-MM-DD HH:mm:ss' });
        $('#search_end_time').datetimepicker({ icons: { time: 'far fa-clock' }, format: 'yyyy-MM-DD HH:mm:ss' });
    });
</script>

python flask

datetime text ID로 값을 조회

#get 방식
@bts_blueprint.route('search/datetime_ex', methods=['GET'])
@login_required
def search_datetime_ex(name=''):
    
    #get 방식
    search_start_time = request.args.get('search_start_input')
    search_end_time = request.args.get('search_end_input')

    # 처리 로직
    var results = 0

    return results

#post 방식
@bts_blueprint.route('search/datetime_ex', methods=['POST'])
@login_required
def search_datetime_ex(name=''):

    search_start_time = request.form['search_start_input']
    search_end_time = request.form['search_end_input']
    
    # 처리 로직
    var results = 0
    
    return results

to Top