ASP.NET 课程设计报告

  • 网站地址 nightmare.xin
  • 支持注册和登录功能, 有后台数据库, 登陆成功会跳转。

  • 前端UI 秦瑞哲

  • 后端处理 程斌
  • 2017/12/11

前言

本次课程要求设计一个网站,这就涉及到编程语言和框架的选取问题,之前只是粗略的学了一些 bootstrap,甚至连 jQuery 都没怎么用过,短时间内应该做不出什么太大的进展,索性专注于后端的设计。学过一点 php 和 python,但都是一些简单的 php 页面,在 thinkphp 和 flask 之间最终选择了 flask (听说要比 Django 轻量级很多)

python + flask + apache + mysql

静态网站比如 hexo 是没有后台的,不具备处理请求的能力,而我也不打算使用这些一键建站(lamp甚至wordpress之类)的框架。因此需要自己设计一些接口供前端调用。下面是服务器的一些配置:主机(ubuntu 16.04 LTS),web 服务器(apache 2.4),数据库(mysql 5.7),编程语言选择 python 和它的 web 框架 flask。

配置

首先是 apache 的配置,apache 负责接收和处理请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<VirtualHost *:80>
ServerName nightmare.xin
WSGIScriptAlias / /var/www/web/flaskapp.wsgi
<Directory /var/www/web/app/>
Order allow,deny
Allow from all
</Directory>
Alias /static /var/www/web/app/static
<Directory /var/www/web/app/static/>
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

apache 接收请求后转发给 wsgi 处理,由 wsgi 传给应用程序,wsgi 是一套 apache, flask 都支持的标准,因此用作 web 服务器和应用程序之间的接口来简化后端设计。(首先载入 wsgi 模块,wsgi 的配置则基本不需要更改)(静态文件目录和错误/访问日志目录很重要)

该接口定义为如下 flaskapp.wsgi

1
2
3
4
import sys
sys.path.insert(0, "/var/www/web")
from app import app
application = app

除了将网站根目录加入 path,该接口将 apache 请求处理转发到 app 对象(app 可以理解为一个 flask 应用程序对象)

该配置在 app/init.py 文件中,定义了如何处理请求的具体方法(建立路由表并编写处理代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from flask import Flask, request, render_template, abort, redirect, url_for, send_from_directory
#from flask_bootstrap import Bootstrap
#from flask_moment import Moment
#from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
from models import User
app = Flask(__name__)
#bootstrap = Bootstrap(app)
#moment = Moment(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://web_python:web_python@localhost/web_python'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
db.create_all()
@app.route('/', methods=['GET'])
def index():
return app.send_static_file('Login/index.html')
@app.route('/signin', methods=['POST'])
def signin():
username = request.form['username']
password = request.form['password']
if User.query.filter_by(username=username, password=password).first() != None:
return app.send_static_file('Backstage/tables.html')
else:
return app.send_static_file('Login/index.html')
@app.route('/signup', methods=['POST'])
def signup():
username = request.form['username']
password = request.form['password']
email = request.form['email']
u = User(username=username, password=password, email=email)
db.session.add(u)
db.session.commit()
return app.send_static_file('Login/index.html')
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html')
if __name__ == '__main__':
app.run(debug=True)

其中用到了 Mysql 数据库,这里新建一个 web_python 的数据库,并新建一个名为 web_python 的用户,密码设置为 web_python,权限设置为允许任意ip登录,但只授权操作 web_python 数据库。

sqlalchemy 模块提供了非常简便的方法使 flask 程序 mysql 交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
app = Flask(__name__)
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
password = db.Column(db.String(80), unique=True)
email = db.Column(db.String(80), unique=True)
def __init__(self, username, password, email):
self.username = username
self.password = password
self.email = email
def __repr__(self):
return '<User %r>' % self.username

以上代码将 python 类对象抽象为一个数据库,该类的变量作为字段名。

对数据库的操作被封装为以下函数

1
2
3
4
5
6
db.create_all() 创建数据库和初始化
db.session.add() 添加一条记录
db.session.update() 更新
db.session.delete() 删除
db.session.commit() 将修改提交到远程数据库
... ...

一些问题

中途服务器出现过几次问题,比如网页请求502呀,资源请求404呀,apache无法启动呀,无法定向到指定的url呀。 通过google和stackoverflow解决了,一个惨痛的教训是,一定记得看错误日志(在/var/log/下相应子目录)…

结语

对 web 知识了解又加深了一些