zoukankan      html  css  js  c++  java
  • Flask + flask_sqlalchemy + jq 完成书籍展示、新增、删除功能

    后端代码

    from flask import Flask, render_template, request, jsonify
    from flask_wtf.csrf import CSRFProtect
    from flask_sqlalchemy import SQLAlchemy
    
    
    app = Flask(__name__)
    
    # 使用防csrf保护APP
    csrf = CSRFProtect(app)
    
    
    class Config(object):
        # sqlalchemy的配置参数
        SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:123456@192.168.3.58:3306/test"
    
        # 设置sqlalchemy自动更跟踪数据库
        SQLALCHEMY_TRACK_MODIFICATIONS = True
    
        SECRET_KEY = "doiso7fd89fyd9^(fsd"
    
    
    app.config.from_object(Config)
    db = SQLAlchemy(app)
    
    
    # 定义作者模型类
    class Author(db.Model):
        __tablename__ = "tbl_author"
    
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(50))
    
    
    # 定义书籍模型类
    class Book(db.Model):
        __tablename__ = "tbl_book"
    
        id = db.Column(db.Integer, primary_key=True)
        book_name = db.Column(db.String(50))
        author_id = db.Column(db.Integer)
    
    
    @app.route("/")
    def index():
        book_num = db.session.query(Book).all()
        if not book_num:
            return render_template("book.html", books=[], page_list=[])
        page_num = len(book_num)//10
        if len(book_num) % 10 > 0:
            page_num += 1
        page_list = range(1, page_num + 1)
        page = request.args.get("page")
        if not page:
            page = 1
        else:
            page = int(page)
    
        # 查询数据
        ret_list = db.session.query(Book.id, Book.book_name, Author.name)
            .outerjoin(Author, Book.author_id == Author.id).order_by(Book.id)
            .slice((page-1)*10, page*10)
            .all()
        return render_template("book.html", books=ret_list, page_list=page_list)
    
    
    @csrf.exempt      # 取消csrf保护
    @app.route("/del", methods=["POST"])
    def delete():
        """删除书籍"""
        # 提取参数
        # 如果前端发送的请求体数据是json格式,get_json会解析成字典
        # get_json 要求前端传送的数据的Content-Type: application/json
        req_dict = request.get_json()
        book_id = int(req_dict.get("book_id"))
        if book_id == '':
            resp_data = {"code": 1, "msg": "传入的id为空", "data": {}}
            return jsonify(resp_data)
    
        books_id = db.session.query(Book.id).all()
    
        if (book_id,) not in books_id:
            resp_data = {"code": 1, "msg": "删除的书籍不存在", "data": {}}
            return jsonify(resp_data)
    
        # 删除数据
        book = db.session.query(Book).get(book_id)
        db.session.delete(book)
        db.session.commit()
    
        # 构造响应数据
        resp_data = {"code": 0, "msg": "删除成功", "data": {}}
        return jsonify(resp_data)
    
    
    @app.route("/add", methods=["POST"])
    def add():
        """增加书籍"""
        # 获取请求信息
        req_dict = request.get_json()
        book_name = req_dict.get("name")
        author_name = req_dict.get("author")
        # 检查请求信息是否为空
        if not all([book_name, author_name]):
            # 为空则提示
            resp_data = {"code": 1, "msg": "输入的数据不能为!", "data": {}}
            return jsonify(resp_data)
    
        # 检查作者名称是否存在
        authors_name = db.session.query(Author.name).all()
        new_author = None
        new_id = None
        if (author_name,) not in authors_name:
            # 不存在就创建
            new_id = db.session.query(Author.id).order_by(-Author.id).first()[0] + 1
            new_author = Author(id=new_id, name=author_name)
            # 将新增数据加入会话中,等待最后一起提交
            db.session.add(new_author)
    
        # 获取作者的id
        if new_author:
            author_id = new_id
        else:
            author_id = db.session.query(Author.id).filter(Author.name == author_name).one()[0]
    
        # 检查请求的书名
        books_name = db.session.query(Book.book_name).filter(Book.author_id == author_id).all()
        if (book_name,) in books_name:
            # 存在则提示
            resp_data = {"code": 1, "msg": "书籍已存在", "data": {}}
            return jsonify(resp_data)
    
        new_book = Book(book_name=book_name, author_id=author_id)
        db.session.add(new_book)
    
        # 留个长度超长BUG,验证该异常
        try:
            db.session.commit()
            resp_data = {"code": 0, "msg": "创建成功", "data": {}}
            return resp_data
        except Exception as e:
            db.session.rollback()
            resp_data = {"code": 1, "msg": F"提交失败:{e}", "data": {}}
            return resp_data
    
    
    if __name__ == '__main__':
        # 删除所有表格(慎用)
        # db.drop_all()
        # db.create_all()
    
        app.run()

    模板代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <!--  如果开启csrf保护,需要定义如下代码  -->
       <meta name="csrf-token" content="{{ csrf_token() }}">
        <title>book_info</title>
        <script src="/static/js/jquery-1.12.4.min.js"></script>
        <script>
            $(function(){
                var book_name = $("#book_name")
                var book_author = $("#book_author")
                var csrftoken = $('meta[name=csrf-token]').attr('content')
                $.ajaxSetup({
                    beforeSend: function(xhr, settings) {
                        if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
                            xhr.setRequestHeader("X-CSRFToken", csrftoken)
                        }
                    }
                });
    
                // 获取URL后参数的值,name为参数名
                $.getUrlParam = function (name) {
                    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
                    var r = window.location.search.substr(1).match(reg);
                    if (r != null) return unescape(r[2]); return null;
                }
                var current_page = $.getUrlParam("page")
                
                // 定义ajax请求函数
                var req_post = function(url, data){
                    // 将js中的对象转换为 json字符串
                    var req_json = JSON.stringify(data);
                    $.ajax({
                        url: url,
                        type: "post",
                        // 申明传给后端的字符类型
                        contentType: "application/json",
                        dataType: 'json',
                        data: req_json
                    }).done(function(resp){
                        if (resp.code == 0)
                        {
                            if ( current_page != null){
                                if (url == "/del" && $(".del").length == 1 && current_page > 1){
                                    current_page = current_page - 1
                                    location.href = "/?page=" + current_page
                                }else{
                                    location.href = "/?page=" + current_page
                                }
                            }else{
                                location.href = "/"
                            }
                        }
                        alert(resp.msg)
                    }).fail(function(){
                        console.log("请求失败")
                    });
                };
    
                // 创建书籍
                $("#book_create").click(function(){
                    b_name = book_name.val();
                    b_author = book_author.val();
                    var data = {'name': b_name, 'author': b_author};
                    req_post("/add", data)
                });
    
                // 删除书籍
                $(".del").click(function(){
                    var id = $(this).siblings()[0].innerHTML;
                    var data = {'book_id': id}
                    console.log("删除id为:" + id)
                    req_post("/del",data)
                });
    
                // 分页
                $(".page div").click(function(){
                    var page_num = $(this)[0].innerHTML;
                    var data = "page=" + page_num
                    location.href = "/?" + data
                });
            })
        </script>
        <style>
            * {
                font-size: 16px;
            }
            #add {
                margin-top: 50px;
                margin-left: 100px;
                float: left;
            }
    
            #add div {
                width: 400px;
                margin: 10px auto 0px;
            }
    
            #book_name, #book_author {
                width: 200px;
                border: 1px solid #000;
            }
            
            #book_create {
                width: 100px;
                margin: auto;
            }
    
            #book {
                width: 500px;
                background-color: rgba(113, 255, 161, 0.952);
                margin-left: 50px;
                float: left;
            };
    
            .th, .tr {
                width: 500px;
                height: 20px;
            }
    
            .th div, .tr div{
                width: 200px;
                height: 30px;
                float: left;
                text-align: center;
                line-height: 30px;
            }
    
            .clearfix:before,.clearfix:after{
                content:"";
                display:table;
            }
            .clearfix:after{
                clear:both;
            }
            .clearfix{
                zoom:1;
            }
    
            div.del{
                width: 100px;
                color: rgb(49, 0, 185);
            }
    
            div.th3 {
                width: 100px;
            }
    
    
            .del:hover, .page div:hover{
                cursor: pointer;
            }
    
            .page {
                width: 280px;
                height: 20px;
                margin: 20px;
            }
    
            .page div {
                width: 20px;
                height: 20px;
                float: left;
                margin: 0px 5px;
                text-align: center;
                line-height: 20px;
            }
    
        </style>
    </head>
    <body>
    <div id="app">
        <div id="add">
            <div>书籍名称:<input type="text" id="book_name"></div> 
            <div>书籍作者:<input type="text" id="book_author"></div>
            <div><input type="submit" id="book_create" value="新增"></div>
        </div>
        <div id="book">
            <div class="th clearfix">
                <div>书籍名称</div>
                <div>作者</div>
                <div class="th3">操作</div>
            </div>
            {% for book in books %}
            <div class="tr clearfix">
                <div style="display: none;">{{ book[0] }}</div>
                <div>{{ book[1] }}</div>
                <div>{{ book[2] }}</div>
                <div  class="del" >删除</div>
            </div>
            {% endfor %}
            <div class="page">
                {% for page in page_list %}
                    <div>{{ page }}</div>
    
                {% endfor %}
            </div>
        </div>
    </div>
    </body>
    </html>

    界面效果

     
  • 相关阅读:
    高精度乘除运算优化
    高精度除法
    高精度乘法
    期末考试
    P2341 [HAOI2006]受欢迎的牛[SCC缩点]
    P2002 消息扩散[SCC缩点]
    神奇搜索算法A*
    P3205 [HNOI2010]合唱队[区间dp]
    P4170 [CQOI2007]涂色
    P1220 关路灯[区间dp]
  • 原文地址:https://www.cnblogs.com/testlearn/p/14136218.html
Copyright © 2011-2022 走看看