こんにちは。
プログラミングを勉強しているロペです。
SQLAlchemyでORMを利用してレコードを新規作成する方法を学習しましたので、
自分なりに纏めて記事にしました。
この記事が誰かの役に立ったら幸いです。
概要
まず、記事の概要を書いてきます。
データベースアクセスの基本は、「Create(新規作成)」、「Read(データ取得)」、「Update(更新)」、「Delete(削除)」の4つの操作なのですが、この記事では最初の「Create」のやり方を書いています。
ちなみに、ORMの説明とかは↓の記事に書いてますので、もしよければ覗いてみてください。
出力する画面
今回の記事で作成した画面は以下になります。
Name、Mail、Ageを記入する欄を作成して、Addを押すとサーバーに保存されて、
出力されるようにしています。
↓みたいな感じで、ID 14番に”サーバーに追加したユーザー名”が出力されています。
これから、このアプリの作成方法(コードとその解説)を書いてきます。
サマリー
コードのサマリーを先に書きます。
記入した値をそれぞれ変数に取り出す
name = request.form.get(‘name’)
mail = request.form.get(‘mail’)
age = int(request.form.get(‘age’))
Mydataモデルクラスのインスタンスを作る
mydata = Mydata(name=name, mail = mail, age=age)
セッションを用意する
Session = sessionmaker(bind=engine)
ses = Session()
mydataを追加して実行する
ses.add(mydata)
ses.commit()
セッションを閉める
ses.close
コードとその解説
この記事では、「Create(新規作成)」の方法を記載します。
そのコードと解説を書いていきます。
HTMLのmycompコンポーネントのテンプレート
created: function() {
this.getdata();
の部分でレコードを新規作成しています。
{% extends "layout2.html" %} {% block title %} login-app {% endblock %} {% block headline %} {{title}} {% endblock %} {% block content %} <div id="app" class="m-3"> <mycomp /> </div> {% raw %} <script type="text/x-template" id="mycomp-template"> <div> <h2>↓に追加したいユーザーの情報を書いて"Add"を押してください</h2> <br> <div class="form-group"> <label for = "id">Name</label> <input type="text" class="form-control" id="name" v-model="f_name"> </div> <div class="form-group"> <label for = "mail">Mail</label> <input type="mail" class="form-control" id="mail" v-model="f_mail"> </div> <div class="form-group"> <label for = "age">Age</label> <input type="number" class="form-control" id="age" v-model="f_age"> </div> <div class="form-group"> <button class="btn btn-primary" v-on:click="action">Add</button> </div> <table class="table"> <thead> <tr> <th>ID</th> <th>Name</th> <th>Mail</th> <th>Age</th> </tr> </thead> <tbody> <tr v-for= "item in data"> <th>{{item.id}}</th> <th>{{item.name}}</th> <th>{{item.mail}}</th> <th>{{item.age}}</th> </tr> </tbody> </table> </div> </div> </script> {% endraw %} <script> // mycomp_board object Vue.component('mycomp',{ template:'#mycomp-template', data: function(){ return{ f_name:'',f_mail:'',f_age:'', alert: 'This is SQLite3 Database sample', data:[(-1,'wait...','','')] } }, methods:{ getdata: function(){ let self = this; $.get("/ajax", function(data){ self.data=eval(data).reverse(); }); }, action: function(){ let formData = new FormData(); formData.append("name", this.f_name); formData.append("mail", this.f_mail); formData.append("age", this.f_age); let self = this; $.ajax({ type:'POST', url:'/form', data: formData, processData: false, contentType: false, success: function(data){ self.f_name=''; self.f_mail=''; self.f_age=''; self.getdata(); }, error: function(request, status, err) { console.log(err); } }); } }, created: function() { this.getdata(); } }); // start Vue. new Vue({ el:'#app', }); </script> {% endblock %} {% block footer %} <h6>Coryright 2020 Rope_blog </h6> {% endblock %}
↓で記入して値をv-on:clickで、’action’に紐づけています。
<div class="form-group"> <label for = "id">Name</label> <input type="text" class="form-control" id="name" v-model="f_name"> </div> <div class="form-group"> <label for = "mail">Mail</label> <input type="mail" class="form-control" id="mail" v-model="f_mail"> </div> <div class="form-group"> <label for = "age">Age</label> <input type="number" class="form-control" id="age" v-model="f_age"> </div> <div class="form-group"> <button class="btn btn-primary" v-on:click="action">Add</button> </div>
そして、↓でactionの処理をかいています。
action: function(){
let formData = new FormData();
formData.append(“name”, this.f_name);
formData.append(“mail”, this.f_mail);
formData.append(“age”, this.f_age);
let self = this;
$.ajax({
type:’POST’,
url:’/form’,
data: formData,
processData: false,
contentType: false,
success: function(data){
self.f_name=”;
self.f_mail=”;
self.f_age=”;
self.getdata();
},
error: function(request, status, err) {
console.log(err);
}
Flaskのコード
「add」メソッドでレコードの保存しています。
ただ、commitをしないと保存が実行されませんので、それが注意点になります。
この、「操作の追加」と「実行」を分けているのは、サーバーに限らず、GitやSVNなど、色々なところで採用されている仕組みだと思います。
(いちいちデータを書き換えてたら非効率なので)
ses.add(mydata)
ses.commit()
from flask import Flask, render_template, request, session, url_for, redirect, jsonify,g from flask.views import MethodView import sqlite3,pickle from sqlalchemy import create_engine from sqlalchemy import Column, Integer, String from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker # from sqlalch import (Table, Column, Integer, String) app = Flask(__name__) engine = create_engine('sqlite:///sample.sqlite3') Base = declarative_base() # get Database Object. def get_db(): if 'db' not in g: g.db = sqlite3.connect('sample.sqlite3') return g.db # close Database Object. def close_db(e=None): db = g.pop('db', None) if db is not None: db.close() #model class class Mydata(Base): __tablename__ = 'mydata' id = Column(Integer, primary_key=True) name = Column(String(255)) mail = Column(String(255)) age = Column(Integer) # get Dict data def toDict(self): return{ 'id':int(self.id), 'name':str(self.name), 'mail':str(self.mail), 'age':int(self.age) } # get List data def getByList(arr): res=[] for item in arr: res.append(item.toDict()) return res # get all mydata record def getAll(): Session = sessionmaker(bind=engine) ses = Session() res = ses.query(Mydata).all() ses.close() return res @app.route('/', methods=['GET']) def index(): return render_template('index5.html',\ title='This is smaple of ORM',) @app.route('/ajax', methods=['GET']) def ajax(): mydata = getAll() return jsonify(getByList(mydata)); @app.route('/form', methods=['post']) def form(): name = request.form.get('name') mail = request.form.get('mail') age = int(request.form.get('age')) mydata = Mydata(name=name, mail=mail, age=age) Session = sessionmaker(bind=engine) ses = Session() ses.add(mydata) ses.commit() ses.close() return'ok' if __name__ == '__main__': app.debug=True app.run()
レイアウトのHTML
vueとかのタグ等をかいているレイアウトのHTMLのコードを貼っておきます。
<!doctype html> <html lang="ja"> <head> <title>{%block title %}{% endblock %}</title> <meta charset="utf-8"/> <meta name="vieport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="{{url_for('static',filename='style.css')}}"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" ></script> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script> </script> </head> <body> <div class="test" style="background-color:rgba(169, 84, 177, 0.055);"> <div class="target"> <div class="container"style="max-width: 100%;"> <div style="display: table;width:100%;"> <div style="display:table-cell; vertical-align:middle;font-size: 30px;"> <div class="text-left" style="border-bottom:5px solid rgb(135, 250, 196);" > <h1 class="display-3"> <div style="font-size: 50px;"> {% block headline %}{% endblock %} </div> </h1> </div> <div style="border-bottom:5px solid rgb(135, 250, 196);" > {% block content %}{% endblock %} </div> <div class="text-right"> {% block footer %}{% endblock %} </div> </div> </div> </div> </div> </div> </body> </html>
コメント