2021년 11월 21일 일요일

[Java] Java Swing Application Example

 1. Java Swing Application Example



package com.home.app;

import com.formdev.flatlaf.FlatLightLaf;
import com.home.swing.JS;
import com.home.swing.JSTable;
import com.home.swing.JSText;
import com.home.swing.JSTree;

import javax.swing.*;
import java.awt.*;
import java.io.IOException;

public class SwingListViewer {

    JFrame frame;
    JSplitPane mainSp;
    JSplitPane leftSp;
    JTabbedPane leftBottom;
    JSTable list;
    JSTree detail;
    JSText hexdump;
    JLabel status;

    String[] tableCols = {"index", "time", "info"};
    int[] tableWidth = { 50, 200, 480 };
    int[] tableAlign = { 1, 0, -1 };

    public static void main( String[] args) throws IOException {
        FlatLightLaf.install(); //Must be called first of all Swing code.
        new SwingListViewer().start();
    }

    private void setTestData() {
        list.addRow(new String[] {"1", "2020.01.01 12:00:00", "Information 1" } );
        list.addRow(new String[] {"2", "2020.01.01 12:01:00", "Information 2" } );
        list.addRow(new String[] {"3", "2020.01.01 12:02:00", "Information 3" } );
        list.setRowColor(0, Color.BLUE, Color.LIGHT_GRAY);
        list.setRowColor(1, Color.WHITE, Color.BLACK);

        detail.addTreeToRoot("Tree1");
        detail.addTreeToRoot("Tree2");
    }
    private void start() throws IOException {

        frame = new JFrame("Swing Application Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JS.setWindowIconRes(frame, "res/appicon.ico");
        list = new JSTable(tableCols, tableWidth, tableAlign, this::listHandler );
        detail = new JSTree("Packet Details", this::treeHandler );
        hexdump = new JSText();
        leftBottom = JS.getTabbedPane();
        JS.addTab( leftBottom, "Hexdump", hexdump.ctrl);
        leftSp = JS.getVSplitPane(new JScrollPane(list.ctrl), leftBottom);
        mainSp = JS.getHSplitPane(leftSp, new JScrollPane(detail.ctrl));
        status = new JLabel("Ready");

        frame.getContentPane().add(JS.getMenuBar(), BorderLayout.NORTH);
        frame.getContentPane().add(mainSp, BorderLayout.CENTER);
        frame.getContentPane().add(status, BorderLayout.SOUTH);
        frame.pack();
        frame.setSize( new Dimension(600, 600));
        frame.setLocationRelativeTo(null);

        setTestData();
        frame.setVisible(true);
    }

    public void listHandler() {
        String[] paths = list.getSelectedRow();
        if( paths != null && paths.length > 0 ) {
            for( String path : paths )
                System.out.println( path + " -> " );
        }
    }
    public void treeHandler() {
        String[] paths = detail.getSelectedTreePath();
        if( paths != null && paths.length > 0 ) {
            for( String path : paths )
                System.out.println( path + " -> " );
        }
    }
}

2021년 9월 25일 토요일

[Python| Markdown file merge

Markdown File Merge

import os
import sys

def text_merge(folder):
    files = sorted(os.listdir(folder))
    with open( folder + ".md", "w", encoding="utf-8" ) as w:
        for f in files:
            path = os.path.join(folder,f)
            with open( path, "r", encoding='utf-8') as r:
                w.write(r.read())
                w.write('\n\n<div style="page-break-after: always;"></div><br>\n\n')
                print(path)
        
if __name__ == "__main__":
    if len(sys.argv) > 1:
        text_merge(sys.argv[1])

2021년 8월 22일 일요일

[Java] Change Encoding to UTF-8


Change Encoding to UTF-8

package com.zdiv.jlib.app.CharConv;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import org.apache.commons.io.IOUtils;

public class CharConv {

    public static void main(String[] args) {
        String directory = "d:\\Ebook\\가림토txt\\객주\\";
        File dir = new File(directory);
        if( dir.exists() ) {
            File[] files = dir.listFiles();
            for( File f : files ) {
                if( ! f.isDirectory() ) {
                    String outFileName = f.getAbsolutePath() + ".out";
                    System.out.println(outFileName );
                    try {
                        String dataStr = IOUtils.toString(new FileInputStream(f), "CP949");
                        byte[] dataByte = dataStr.getBytes("UTF-8");
                        Files.write(Paths.get(outFileName), dataByte, StandardOpenOption.CREATE);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

2021년 8월 18일 수요일

[Python] Any to UTF-8

 Any codec to UTF-8

#-*- coding: utf-8 -*-

import sys    
import os

def file_enc(path):
    import chardet
    with open( path, "rb" ) as f:
        return chardet.detect(f.read()).get('encoding')
    
def py2_euc2utf(in_file, out_file):
    with open(in_file, "r") as f:
        euc = f.read().decode('cp949') #encode('cp949').decode('cp437')
        #euc = f.read().decode('euc_kr') #encode('cp949').decode('cp437')
        utf = euc.encode('utf-8')
        with open(out_file, "w") as w:
            w.write(utf)

def py3_euc2utf(in_file, out_file):
    with open(in_file, "r", encoding=file_enc(in_file)) as f:
        utf = f.read()
        with open(out_file, "w", encoding="utf-8") as w:
            w.write(utf)

def euc2utf(in_file, out_file):
    if sys.version_info.major == 3: py3_euc2utf(in_file,  out_file + '.py3')
    else: py2_euc2utf(in_file, out_file + '.py2')

    
def filelist(path):
    from os import listdir
    from os.path import isfile, join
    return [f for f in listdir(path) if isfile(join(path, f))]

if __name__ == "__main__":
    in_dir = r"d:/Ebook/가림토txt"
    out_dir = r"d:Ebook/가림토txt_utf"
    if not os.path.exists(out_dir):
        os.mkdir(out_dir)
    files = filelist(in_dir)
    for f in files:
        print(f, file_enc(os.path.join(in_dir,f)))
        try:
            euc2utf(os.path.join(in_dir,f),os.path.join(out_dir,f))
        except:
            print(f, "--------------> ERROR")
    

2021년 6월 13일 일요일

GIT Quick Guide

 1. Git 저장소 만들기

  - 기존 디렉토리를 Git 저장소로 만들기

    $ cd /home/user/project

    $ git init

    $ git add *.c

    $ git commit -m 'comment'

  - 기존 저장소를 Clone 하기

    $ git clone https://github.com/project

    $ git clone pi@github.com:/home/pi/project

    $ git remote -v

      origin  pi@zdiv.iptime.org:/home/pi/git (fetch)

      origin  pi@zdiv.iptime.org:/home/pi/git (push)


2. 수정하고 저장소에 저장하기

    (untracked) (unmodified) (modified) (staged)
         |--------------(add)--------------->|
         |           |--(edit)-->|           |
         |           |---------------(rm)--->|
         |           |           |---(rm)--->|
         |           |           |---(add)-->|
         |<-(remove)-|           |<--(edit)--|     
         |           |<-------(commit)-------|

  - 파일의 상태 확인하기

    $ git status

    $ git status -s (짧게확인)

  - 파일을 새로 추적하기

    $ git add <file>

  - Modified 상태의 파일을 Stage 하기

    $ git add <file>

  - 파일 무시하기 (.gitignore)

    . 아무것도 없는 라인이나, `#`로 시작하는 라인은 무시한다.

    . 표준 Glob 패턴을 사용한다. 이는 프로젝트 전체에 적용된다.

    . 슬래시(/)로 시작하면 하위 디렉토리에 적용되지(Recursivity) 않는다.

    . 디렉토리는 슬래시(/)를 끝에 사용하는 것으로 표현한다.

    . 느낌표(!)로 시작하는 패턴의 파일은 무시하지 않는다.

    . 애스터리스크 2개를 사용하여 디렉토리 안의 디렉토리 까지 지정할 수 있다

    $ cat .gitignore 

      *.[oa]

      *~

  - Staged와 Unstaged 상태의 변경 내용을 보기 

    $ git diff

    $ git diff --cached  (Stage된 파일 비교)

    $ git diff --staged  (Stage된 파일 비교)

    $ git difftool (외부 비교 툴 사용)

    $ git difftool --tool-help

  - 변경사항 커밋하기

    $ git commit

    $ git commit -m <comment>

    $ git config --global core.editor (편집기 설정)

  - Staging Area 생략하기

    $ git commit -a (모든 파일을 stage함)

  - 파일 삭제하기

    $ git rm <file>

    $ git rm -f <file>       (Stage된 파일도 삭제)

    $ git rm --cached <file> (Stage된 파일만 삭제)

  - 파일 이름 변경하기

    $ git mv <file_from> <file_to> (아래 세 동작과 동일)

    $ mv README.md README

    $ git rm README.md

    $ git add README



3. 커밋 히스토리 조회하기

    $ git log

  

4. 되돌리기

  - 마지막 commit 덮어쓰기

    $ git commit --amend 

    $ git commit -m 'initial commit'

    $ git add forgotten_file

    $ git commit --amend

  - 파일 상태를 Unstage로 변경하기

    $ git reset HEAD <file>

  - Modified 파일 되돌리기

    $ git checkout -- <file>



5. 리모트 저장소

  - 리모트 저장소 확인하기

    $ git remote 

    $ git remote -v 

  - 리모트 저장소 추가하기

    $ git clone <url> (origin 추가됨)

    $ git remote add <alias> <url>

    $ git fetch <remote>

    $ git pull (fetch + merge 수행)

  - 리모트 저장소에 Push 하기

    $ git push <remote> <branch>

    $ git push origin master

    $ git config --bool core.bare true 

  - 리모트 저장소 살펴보기

    $ git remote show <remote>

  - 리모트 저장소 이름을 바꾸거나 리모트 저장소를 삭제하기

    $ git remote rename <old> <new>

    $ git remote remove <remote>

    # git remote rm <remote>

    


2021년 5월 22일 토요일

[Bootstrap] Board Template

 1. Board Template


<head>
<title>home</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="./css/bootstrap-3.3.2.css" >
</head>
<body>

<nav class="navbar navbar-default">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu" role="menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left" role="search">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu" role="menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>


<div class="panel panel-primary" style="margin: 25px 25px 25px 25px;">
  <div class="panel-heading">Panel heading</div>
  <div class="panel-body">
    <p>...</p>
	<table class="table table-bordered table-striped" border='0'>
		<thead><tr class="info">
			<th>element1</th>
			<th>data</th>
			<th>junk here</th>
			<th>last column</th>
		</tr></thead>
		<tbody><tr>
			<td class="shrink">elem</td>
			<td class="shrink">more data</td>
			<td class="shrink">other stuff</td>
			<td class="expand">again, last column</td>
		</tr>
		<tr>
			<td class="shrink">more</td>
			<td class="shrink">of </td>
			<td class="shrink">these</td>
			<td class="expand"><center><span class="label label-primary">Primary</span></center></td>
		</tr></tbody>
	</table>
	
	<div style="display: flex; justify-content: flex-end"> 
	<nav>
	  <ul class="pagination">
		<li>
		  <a href="#" aria-label="Previous">
			<span aria-hidden="true">&laquo;</span>
		  </a>
		</li>
		<li><a href="#">1</a></li>
		<li><a href="#">2</a></li>
		<li><a href="#">3</a></li>
		<li><a href="#">4</a></li>
		<li><a href="#">5</a></li>
		<li>
		  <a href="#" aria-label="Next">
			<span aria-hidden="true">&raquo;</span>
		  </a>
		</li>
	  </ul>
	</nav>
	</div>
  </div>
</div>


<script src="./js/jquery-3.6.0.js" ></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" ></script>
<script src="./js/bootstrap-3.3.2.js" ></script>
</body>
</html>

2021년 4월 15일 목요일

[Python] Flask Example

1. File Server

fileserver.py

import logging
import time
import os

import requests
from flask import Flask, url_for, render_template, request, redirect, session
from flask_sqlalchemy import SQLAlchemy
from flask import send_from_directory

ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
home_dir = r"D:\Temp"
app = Flask(__name__, instance_path=home_dir)
db = SQLAlchemy(app)

#
# FILE SERVER
#
        
def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

def strip_root(filename):
    if len(filename) == 0: return ""
    elif len(filename) == 1: return "" if filename[0] == '/' else filename
    else: return filename[1:] if filename[0] == '/' else filename
        
def send_list_directory(file_path):
    dirs  = []
    files = []
    abs_path = os.path.join( home_dir, file_path )
    if len(file_path) > 0:
        if file_path[0] != '/':  file_path = "/" + file_path
        if file_path[-1] != '/': file_path = file_path + "/"
    else:
        file_path = "/"
    dirs.append( ("..", 0) ) 
    for f in os.listdir( abs_path ):
        full_name = os.path.join( abs_path, f )
        size = os.path.getsize( full_name )
        date = time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime(os.path.getctime( full_name )))
        if os.path.isdir(full_name): dirs.append( (f, size, date) )
        else: files.append( (f, size, date) )
    print('send_list_directory [', file_path, ']', dirs, files)
    return render_template("fileserver.html", folder=file_path, dirs=dirs, files=files)

@app.route('/home', methods=['GET', 'POST'])
@app.route('/', methods=['GET', 'POST'])
def Home():
    if not session.get('logged_in'):
        return render_template('login.html')
    if request.method == 'GET':
        return send_list_directory("")
 
@app.route('/upload', methods=['POST'])
def Upload():
    if not session.get('logged_in'):
        return render_template('login.html')
    file = request.files['file']
    folder = strip_root(request.form['folder'])
    if file and allowed_file(file.filename):
        file.save(os.path.join( home_dir, folder, file.filename))
    return send_list_directory(folder)
        
@app.route('/delete', methods=['GET'])
def Delete():
    if not session.get('logged_in'):
        return render_template('login.html')
    file = strip_root(request.args['file'])
    folder = strip_root(os.path.dirname(file))
    full_path = os.path.join( home_dir, file)
    if file and allowed_file(file):
        print( full_path, home_dir, file )
        os.remove(full_path)
    else:
        print(f"permission error : delete {full_path}")
    return send_list_directory(folder)
 
@app.route('/<path:filePath>', methods=['GET'])
def ServeFile(filePath):
    if not session.get('logged_in'):
        return render_template('login.html')
    print('ServeFile()', filePath)
    if os.path.isdir(os.path.join(home_dir,filePath)):
        return send_list_directory(filePath)
    else:
        return send_from_directory(home_dir, filePath)

def warning(text):
    logger.warning(text)


#
# SESSION
#

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    password = db.Column(db.String(80))
    def __init__(self, username, password):
        self.username = username
        self.password = password

def create_user(username,password):
    new_user = User(username=username, password=password)
    db.session.add(new_user)
    db.session.commit()
    print(User.query.filter_by(username=username, password=password).first())
      
@app.route('/login', methods=['GET', 'POST'])
def login():
    if not session.get('logged_in'):
        if request.method == 'GET':
            return render_template('login.html')
        username = request.form['username']
        password = request.form['password']
        print( '/login', username, password )
        try:
            data = User.query.filter_by(username=username, password=password).first()
            if data is not None:
                #if username == 'admin' and password == 'admin1234':
                session['logged_in'] = True
                return redirect(url_for('Home'))
            else:
                return  render_template('login.html', message="Login Fail [1] !")
        except:
            return  render_template('login.html', message="Login Fail [2] !")
    else:
        return send_list_directory("")

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        new_user = User(username=request.form['username'], password=request.form['password'])
        db.session.add(new_user)
        db.session.commit()
        return render_template('login.html')
    return render_template('register.html')

@app.route("/logout")
def logout():
    session['logged_in'] = False
    return redirect(url_for('Home'))

#
# Application
#
    
if __name__ == "__main__":
    app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024    
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///fileserver.db'
    app.secret_key = "3123"
    db.create_all()
    logger = logging.getLogger(__name__)
    #create_user(username='admin', password='admin1234')
    app.run(debug=True, host="0.0.0.0", port=8000) 


fileserver.html

<!DOCTYPE html>
<html>
    <head>
        <title>home</title>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">        
    </head>
    <body>
        <div style="margin-right:50px" width="600">
            <div style="float: right"><a href="/logout"> logout </a></div>
            <h1>UpLoad</h1>
            <!--div style="border: 3px solid gold; float: left; height: auto; width: 200px; margin: 15px 25px 15px 0px;"-->
            <table border='1' class="table table-dark" style="margin: 25px 25px 25px 25px; width:600px;" >
            {% autoescape false %}
              <form action = "/upload" method = "POST"
                  enctype = "multipart/form-data">
              <tr>
              <td><input type = "file" name = "file" />
              <input type = "hidden" name = "folder" value="{{folder}}" /></td>
              <td><input type = "submit"/></td>
              </tr>
            </form> 
            {% endautoescape %}
            </table>
        <h1>File List</h1>
        <div style="margin-left:25px"> <h4> {% block title %}  {{folder}}{% endblock %} </h4></div>
        <table border='1' class="table table-striped table-responsive" style="margin: 25px 25px 25px 25px;"> <!-- border='1'  -->
            <thead><tr> <th width="1%" style="text-align: center;"> File/Dir </th>
                 <th style="text-align: center;"> Filename </th> 
                 <th width="1%" style="text-align: center;"> Size </th> 
                 <th width="200px" style="text-align: center;"> Date </th>
                 <th width="1%" style="text-align: center;"> Operation </th>
             </tr></thead><tbody>
        {% if dirs %}
            {% for dirName in dirs %}
                <tr>
                <td>[DIR]</td> 
                <!--td onclick="window.location='{{folder}}{{dirName[0]}}';" style='cursor: pointer;'-->
                <td><a href="{{folder}}{{dirName[0]}}">[ {{ dirName[0] }} ]</a></td> 
                <td style="text-align: right;"> {{ dirName[1] }} </td>
                <td style="text-align: center;"> {{ dirName[2] }} </td>
                <td></td>
                </tr>
            {% endfor %}
        {% endif %}
        {% if files %}
            {% for fileName in files %}
                <tr>
                <td>[FILE]</td>
                <!--td onclick="window.location='{{folder}}{{fileName[0]}}';" style='cursor: pointer;'-->
                <td><a href="{{folder}}{{fileName[0]}}"> {{ fileName[0] }}</td> 
                <td style="text-align: right;">{{ fileName[1] }} </a></td>
                <td style="text-align: center;"> {{ fileName[2] }} </td>
                <td style="text-align: center;"> <a href="/delete?file={{folder}}{{fileName[0]}}">Delete</a></td>
                </tr>
            {% endfor %}
        {% endif %}
        </tbody></table>
        </div>
        <p />
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>        
    </body>
</html>

base.html

<html>
<head>
<title>home</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" >
</head>
<body>
{% block content %}{% endblock %}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" ></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" ></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" ></script>
</body>
</html>

register.html

{% extends "base.html" %}
{% block content %}
{% if session['logged_in'] %}
<p>Oh no Dont show page</p>
{% else %}
<h2>Register</h2>
<form action="/register" method="POST">
  <input type="username" name="username" placeholder="Username">
  <input type="password" name="password" placeholder="Password">
  <input type="submit" value="Log in">
</form>
{% endif %}
{% endblock %}

login.html

{% extends "base.html" %}
{% block content %}
{% if session['logged_in'] %}
<script>window.location.href = "/"</script>
{% else %}
<center>
<h2>Login</h2>
<form action="/login" method="POST">
  <input type="username" name="username" placeholder="Username">
  <input type="password" name="password" placeholder="Password">
  <input type="submit" value="Log in">
</form>
<div><font color="red"> {{message}} </font></div>
</center>
{% endif %}
{% endblock %}