超简单全栈开发MVC架构web应用 - blog系统/Python&JS

这篇文章的内容是如何实现一个超级简单的MVC架构的web应用。受益于Python语言的简洁和功能丰富的库,所以代码相当少:包括后端和前端,总共几十行代码。这个系统适合初学web全栈开发尤其Python,可以参考实践,作为一个快速练习上手的项目。

这个web应用实现的功能包括:
1. 实时显示全部blog项
2. 提交新的blog项

界面如下:

架构简介

使用MVC(Model-View-Controller/模型-视图-控制器)架构,最大程度的使用已有库。

  • 后端
    • 控制器Python Flask:
      服务器端用到了Python的一个web开发框架:Flask。Flask对WSGI进行了进一步的抽象,使接口处理的代码结构更清晰。

      接口1(根路径GET方法):访问数据库得到所有blog内容,并返回渲染后的模版文件。
      接口2(/api/submit路径POST方法):在数据库中增加一条记录。
      #define controller, list all blog items when visit home page 
      @app.route('/')
      def home():
          # Render the home page with blog posts
          result = blogpost. query.all()
          return render_template('template.html', blog_list=result)
      
      #define controller, get the form data and insert the blog item into db
      @app.route('/api/submit',methods=['POST'])
      def new_post():  
          content=request.form['blogcontent']
          post = blogpost(createtime=datetime.now(), content=content)
          db.session.add(post)
          db.session.commit()
          return "done"

       
    • 数据库SQLite/模型SQLAlchemy:

      blog的提交时间和内容存储在SQLite数据库中。sqllite是一个轻量级的数据库,不需要额外的服务器。数据库文件以.db为后缀。

      使用SQLAlchemy库的模型功能来完成Python后端和数据库的交互。
      #create a Flask web application instance, and assign it to the app variable. The _name_ argument represents the name of the current module.
      app = Flask(__name__)
      # set the configuration for the Flask application to use a SQLite db named blog.db
      app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
      #create SQLAlchemy object db, and bind it to the Flask application. This object acts as the intermediary between the Flask application and the database, which allow you to interact with the db with SQLAlchemy's ORM functionality.
      db = SQLAlchemy(app)
      
      #create a blogpost model using SLQAlchemy's declarative syntax. It inherits from SQLAlchemy.Model, which is the base class for defining models
      class blogpost(db.Model):
          id = db.Column(db.Integer, primary_key=True)
          createtime = db.Column(db.String(100), nullable=False)
          content = db.Column(db.Text, nullable=False)

  • 前端视图
    • jinja模板

      在templates目录创建template.html文件。模板文件主要包括一个table用以显示所有的blog内容,一个form用以提交一个blog。

      Flask默认使用jinja模板通过render_template()函数来渲染网页。来在Jinja中,用{% ... %}表示指令。以下代码将列出所有的blog内容:
          <table id="myTable">
            <tr><td>timestamp</td><td>blog</td></tr>
            {% for i in blog_list %}
            <tr><td>{{ i.createtime }}</td><td>{{ i.content }}</td></tr>
            {% endfor %}
          </table>
    • JavaScript

      当用户提交form时,触发JavaScript调用后端API,存储成功后刷新页面以显示所有的blog内容。
              // Get the form and input element references
              const form = document.getElementById('myForm');
          
              // Add an event listener to the form submit event
              form.addEventListener('submit', function(event) {
                event.preventDefault(); // Prevent default form submission behavior
      
                // send POST request to /api/submit 
                const xhr = new XMLHttpRequest();
                xhr.open('POST', '/api/submit', true);
                xhr.send(new FormData(form))
                
                // Handle the response
                xhr.onreadystatechange = function() {
                  if (xhr.readyState === XMLHttpRequest.DONE) {
                    if (xhr.status === 200) {
                      //refresh the home page to get the latest blog items
                      window.location.reload();
                    }
                  }
                }
              });

完整代码

包括两个运行文件和一个数据库创建文件(github: https://github.com/lisaliyane/simpleblog):

  • blog.py (启动该文件以启动blog系统 比如 python3 blog.py)
  • create_db.py(用以创建数据库和Data Model相关的表)
  • templates/template.html(一定要使用templates目录,Flask的render_template()函数将从该目录寻找模版文件)

启动方法:

  1. 将代码准备好。
  2. 调用python create_db.py,生成SQLite数据库和Data Model相关的表。成功后,将项目下将生成一个新的目录instance,和一个以.db为后缀的数据库文件。
  3. 在项目根目录下,调用python blog.py。启动web应用,默认端口5000。
  4. 在浏览器下打开http://127.0.0.1:5000,即可打开页面体验系统。

blog.py:

from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

#create a Flask web application instance, assign it to the app variable. The _name_ argument represents the name of the current module.
app = Flask(__name__)
# set the configuration for the Flask application to use a SQLite db named blog.db
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
#create SQLAlchemy object db, and bind it to the Flask application. This object acts as the intermediary between the Flask application and the database, which allow you to interact with the db with SQLAlchemy's ORM functionality.
db = SQLAlchemy(app)

#create a blogpost model using SLQAlchemy's declarative syntax. It inherits from SQLAlchemy.Model, which is the base class for defining models
class blogpost(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    createtime = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)

#define controller, list all blog items when visit home page 
@app.route('/')
def home():
    # Render the home page with blog posts
    result = blogpost.query.all()
    return render_template('template.html', page_list=result)

#define controller, get the form data and insert the blog item into db
@app.route('/api/submit',methods=['POST'])
def new_post():  
    content=request.form['blogcontent']
    post = blogpost(createtime=datetime.now(), content=content)
    db.session.add(post)
    db.session.commit()
    return "done"

if __name__ == '__main__':
    #start web service, the default port is 5000
    app.run(debug=True)

create_db.py:

from blog import app, db

#create database and table
with app.app_context():
    db.create_all()

templates/template.html:

<html>
  <head>
    <title>My Blog</title>
  </head>
  <body>
    <h1>Welcome to My Blog</h1>
    <h2>blog posts list:</h2>
    <table id="myTable">
      <tr><td>timestamp</td><td>blog</td></tr>
      {% for i in page_list %}
      <tr><td>{{ i.createtime }}</td><td>{{ i.content }}</td></tr>
      {% endfor %}
    </table>

    <h2>submit new blog:</h2>
    <form id="myForm" method="post">
        <textarea type="text" name="blogcontent" placeholder="Enter your blog"></textarea><br>
        <button type="submit" name="submitButton">Submit</button>
    </form>
    <script>
        // Get the form and input element references
        const form = document.getElementById('myForm');
    
        // Add an event listener to the form submit event
        form.addEventListener('submit', function(event) {
          event.preventDefault(); // Prevent default form submission behavior

          // send POST request to /api/submit 
          const xhr = new XMLHttpRequest();
          xhr.open('POST', '/api/submit', true);
          xhr.send(new FormData(form))
          
          // Handle the response
          xhr.onreadystatechange = function() {
            if (xhr.readyState === XMLHttpRequest.DONE) {
              if (xhr.status === 200) {
                //refresh the home page to get the latest blog items
                window.location.reload();
              }
            }
          }
        });
      </script>
  </body>
</html>

----------------

版本历史:

2024/01/19: 初始版本
2024/01/22: 使用SQLAlchemy代替直接使用sqlite3,以实现MVC架构中的Model
                     去除Javascript中的渲染table的大段代码,用window.location.reload()刷新页面代替

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liyane

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值