期末作品检查:总结Python+Flask+MysqL的web建设技术过程

一、个人学期总结

  在一学期里我们学习并实现了基于Python的Flask框架web建设项目,要在一学期里入门一个新的语言并且完成相应的框架项目建,对我这个代码“小白”来说还是非常有难度的。

  首先让我们来了解一下Python的一些优势和目前的发展情况,python是一种面向对象的解释型计算机程序设计语言,语法简洁清晰,目前已超越java成为最热门的编程语言之一。作为以后有可能向IT方向发展的学生来说,紧跟潮流进行学习和自我提升是非常重要的事情,也许老师也是考虑到这一点,所以让我们接触了最新最热门的Python以及Pycharm开发工具。

  学期初始,我们学习了Python的基础语法,输入、输出、交互、数字计算的方法、字符串基本操作、凯撒密码、自制九九乘法表、中英文词频统计等,还学习了import turtle库,并利用这个库绘制出多种多样的图形,海龟图标有趣可爱,课堂氛围活泼许多,从而激发了我们学习Python的兴趣,提升了我们对编程语言的思维能力,为构建Flask框架制作网页的学习打下基础。

   在学习Python+Flask+MysqL的web建设时,需要安装数据库(mysql)、开发工具(pycharm)和开发需要用到的第三方库等。

  一开始,我们学习网页前端的制作,第一次知道五花八门的网页原来是由许许多多的标签对组成的,每一对都有它特定的一些功能,包含了标签对里的众多参数,每个参数都有不同的含义,给页面前端带来不同的效果。刚开始接触html+css+js的时候会想各种办法去把网页做好看,尝试了各种各样的样式和标签对,或者从网页上cope别人做好的样式代码去修改,碰到不会的代码就问百度解答或同学探讨,在这过程中又学会了许多课堂上没有教过的知识,但是最终做出的页面也不尽人意,这才感悟做出漂亮好看的前端如此不易。老师在课上推荐了菜鸟教程这个平台(http://www.runoob.com/),里面的bookstrap样式简洁明了,很是好看,为我们做出一个好看的页面提供了便捷的途径。

  在后端建设过程中,我们引入了flask库,用于创建一个Flask对象以及页面的跳转,引入flask_sqlalchemy库进行数据库的关联映射等,学习了对数据的增删改查等操作,利用对数据库的查询、添加功能实现了页面的登陆、注册以及发布功能,这些功能的实现根据前端页面的name属性名,后台请求接收同名name的值,再对接收到的值做一系列的操作。在对这些name属性命名时,要注意前后端对应,且同一页面不能出现相同命名,否则会出现数据传递出错,造成一系列的麻烦,所以在编程过程中要时刻注意代码的唯一性、对应性、尽量用更少更优化的代码实现功能。

  说到代码,讲了唯一性和对应性,就不得不提简洁性和清晰性了,打代码时可以多用“Ctrl+Alt+L”快捷键进行格式化代码,以便我们清晰的观察和修改代码。养成良好的习惯还在于多用“Ctrl+/”打注释,把个人的理解和思路整理成简单的注释,不仅方便自己复习和修改还有利于使用者及他人查看学习。

  一般来说,在着手写代码前,应先明确目标和功能,理请原理和思路,再开始编写,遵循小步快走的原则,在写好每个功能代码后,按原理检查是否出错, 再运行页面验证功能,如此渐渐的把整个系统实现。出错时也不必惊慌,先用F12打开页面控制台查看数据发送、接收情况和红色报错项目,或者到pycharm后台里找相应的报错字眼、提示等等去解决问题。

   总之,借用老师的一句话,“编程是一门艺术活”,像做建筑一般,字母是它的钢筋水泥和砖块,只有实打实的基础,地基牢固,才能成就崛起的名胜古迹。

   本学期学习了python+flask web开发,我觉的自己真正的学到了东西,从菜鸟到会独立完成自己的项目,过程中遇到很多问题,查阅资料,与同学讨论后一起解决。 虽然这个学期python课程学习结束了,但是我的学习不会止于此,我还会继续学习python语言,不断提升自己的能力。

 

 

二、Python+Flask+MysqL的web建设技术过程总结

  1、使用工具

  工具:pycharm64.exe + Python 3.6 64-bit + MySQL + Navicat for MySQL

  2、基本页面展示

  (1)导航条

 

 

  (2)登录页面

 

  (3)注册页面

 

  (4)发布页面

 

  (5)首页

 

  (6)评论页面

 

(7)个人页面

 

 

3、第三方库导入、Flask初始概览与数据库链接

  主py文件:

  config:数据库连接

 

app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app)


class User(db.Model):  # 创建类User
    __tablename__ = 'user'  # 类对应的表名user
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)  # autoincrement自增长
    username = db.Column(db.String(20), nullable=False)  # nullable是否为空
    _password = db.Column(db.String(200), nullable=False) #内部使用
    nickname = db.Column(db.String(20), nullable=True)

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self,row_password):
        self._password=generate_password_hash(row_password)

    def check_password(self,row_password):
        result=check_password_hash(self._password,row_password)
        return  result


class Fabu(db.Model):
    __tablename__ = 'fabu'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    detail = db.Column(db.Text, nullable=False)
    creat_time = db.Column(db.DateTime, default=datetime.now)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    author = db.relationship('User', backref=db.backref('fabu'))

class Comment(db.Model):
    __tablename__ = 'comment'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    author_id = db.Column(db.Integer,db.ForeignKey('user.id'))
    fabu_id = db.Column(db.Integer, db.ForeignKey('fabu.id'))
    creat_time = db.Column(db.DateTime, default=datetime.now)
    detail = db.Column(db.Text, nullable=False)
    fabu = db.relationship('Fabu',backref=db.backref('comments',order_by=creat_time.desc))
    author = db.relationship('User', backref=db.backref('comments'))

db.create_all()

# 使用装饰器,设置路径与函数之间的关系。
#使用Flask中render_template,用不同的路径,返回首页、登录员、注册页。
# 用视图函数反转得到URL,url_for(‘login’),完成导航里的链接。
@app.route('/')
def daohang():

    context={
        'fabus': Fabu.query.order_by('-creat_time').all()

    }
    return render_template('daohang.html',**context)

if __name__ == '__main__':
    app.run(debug=True)

 

4、增删改查功能

# 插入功能
user = User(username='15',password='12')
db.session.add(user)
db.session.commit()

# 查询功能
user=User.query.filter(User.username=="15").first()
print(user.username,user.password)

# 修改功能
user=User.query.filter(User.username=="15").first()
user.password='888'
db.session.commit()

# 删除功能
user=User.query.filter(User.username=="15").first()
db.session.delete(user)
db.session.commit()

 

5、加载静态文件、父模板与其他页面继承

  url_for运用:

  from flask import url_for

  跳转后端请求:

 

  加载静态文件:(css、js、image)

 

  继承父模板:

 

6、注册功能:

  (1)html文件:

{% extends 'daohang.html' %}

{% block zhucetitle %}注册{% endblock %}
{% block zhucehead %}
    <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/denglu.css') }}">
    <script src="{{ url_for('static',filename='js/denglu.js') }}"></script>
{% endblock %}
{% block daohangbody %}

    <div class="center-block" id="zhucebox">
    <div class="panel panel-primary" id="zhucebox1_1">
        <div class="panel-heading">
            <h2 class="panel-title">注册</h2>
        </div>
        <br>
        <form class="bs-example bs-example-form" role="form" action="{{ url_for('zhuce') }}" method="post">
            <div class="input-group">
                <span class="input-group-addon"></span>
                <input type="text" class="form-control" name="user" id="user" placeholder="请输入用户名">
            </div>
            <br>
            <div class="input-group">
                <span class="input-group-addon"></span>
                <input type="password" class="form-control" name="pass" id="pass" placeholder="请设置密码" >
            </div>
            <br>
            <div class="input-group">
                <span class="input-group-addon"></span>
                <input type="password" class="form-control" id="again" placeholder="请再次输入密码">
            </div>
            <div id="error_box1">
                <br>
            </div>
            <br>
            <label><input type="submit" class="btn btn-default" value="注册" onclick="fnRegistration()"></input></label>
        </form>
    </div>
</div>
{% endblock %}

 

  (2)js文件:

function fnRegistration() {
    var uSer = document.getElementById("user");
    var pAss = document.getElementById("pass");
    var aGain = document.getElementById("again");
    var oError = document.getElementById("error_box");
    var isError = true;

    oError.innerHTML = "<br>";

    // 验证用户名
    if (uSer.value.length < 6 || uSer.value.length > 20) {
        oError.innerHTML = "用户名只能6-20位";
        isError = false;
        return isError;
    } else if ((uSer.value.charCodeAt(0) >= 48) && (uSer.value.charCodeAt(0) <= 57)) {
        oError.innerHTML = "用户名首字母不能是数字";
        isError = false;
        return isError;
    } else for (var i = 0; i < uSer.value.length; i++) {
        if ((uSer.value.charCodeAt(i) < 48) || (uSer.value.charCodeAt(i) > 57) && (uSer.value.charCodeAt(i) < 97) || (uSer.value.charCodeAt(i) > 122)) {
            oError.innerHTML = "用户名只能由数字和字母组成";
            isError = false;
            return isError;
        }
    }

    // 验证密码
    if (pAss.value.length < 6 || pAss.value.length > 20) {
        oError.innerHTML = "密码只能6-20位";
        isError = false;
        return isError;
    }

    // 验证再次输入的密码
    if (aGain.value != pAss.value) {
        oError.innerHTML = "密码不一致";
        isError = false;
        return isError;
    }
    // 验证弹框
    window.alert("注册成功!");
    return true;
}

  (3)py文件:

@app.route('/zhuce/', methods=['GET', 'POST'])
def zhuce():
    if request.method == 'GET':
        return render_template('zhuce.html')
    else:
        username = request.form.get('user')  # post请求模式,安排对象接收数据
        password = request.form.get('pass')
        nickname = request.form.get('nickname')
        user = User.query.filter(User.username == username).first()  # 作查询,并判断
        if user:
            return u'该用户已存在'
        else:
            user = User(username=username, password=password, nickname=nickname)  # 将对象接收的数据赋到User类中,即存到数据库
            db.session.add(user)  # 执行操作
            db.session.commit()
            return redirect(url_for('denglu'))  # redirect重定向

 

 

7、登录功能:

(1)html文件:

{% extends 'daohang.html' %}

{% block denglutitle %}登陆{% endblock %}
{% block dengluhead %}
    <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/denglu.css') }}">
    <script src="{{ url_for('static',filename='js/denglu.js') }}"></script>
{% endblock %}
{% block daohangbody %}

<div class="center-block" id="loginbox">
    <div class="panel panel-primary" id="loginbox1_1">
        <div class="panel-heading">
            <h2 class="panel-title">登陆</h2>
        </div>
        <br>
        <form class="bs-example bs-example-form" role="form" action="{{ url_for('denglu') }}" method="post">
            <div class="input-group">
                <span class="input-group-addon"></span>
               <input class="form-control"  type="text" name="user" id="user" placeholder="请输入用户名">
            </div>
            <br>
            <div class="input-group">
                <span class="input-group-addon"></span>
                <input class="form-control" type="password"  name="pass" id="pass" placeholder="请输入密码" >
            </div>
            <div id="error_box">
                <br>
            </div>
            <div class="checkbox">
                <label>
                    <input type="checkbox">记住我
                </label>
            </div>
            <br>
            <label><input type="submit" class="btn btn-default" onclick="fnLogin()" value="登陆"> </input> </label>

        </form>
    </div>
</div>
{% endblock %}

(2)js文件:

function fnLogin() {
    var uSer = document.getElementById("user");
    var pAss = document.getElementById("pass");
    var oError = document.getElementById("error_box");
    var isError = true;

    oError.innerHTML = "<br>";

    // 验证用户名
    if (uSer.value.length < 6 || uSer.value.length > 20) {
        oError.innerHTML = "用户名只能6-20位";
        isError = false;
        return isError;
    } else if ((uSer.value.charCodeAt(0) >= 48) && (uSer.value.charCodeAt(0) <= 57)) {
        oError.innerHTML = "用户名首字母不能是数字";
        isError = false;
        return isError;
    } else for (var i = 0; i < uSer.value.length; i++) {
        if ((uSer.value.charCodeAt(i) < 48) || (uSer.value.charCodeAt(i) > 57) && (uSer.value.charCodeAt(i) < 97) || (uSer.value.charCodeAt(i) > 122)) {
            oError.innerHTML = "用户名只能由数字和字母组成";
            isError = false;
            return isError;
        }
    }

    // 验证密码
    if (pAss.value.length < 6 || pAss.value.length > 20) {
        oError.innerHTML = "密码只能6-20位";
        isError = false;
        return isError;
    }
    // 验证弹框
    window.alert("登陆成功!");
    return true;
}

(3)py文件:

  内有session功能

@app.route('/denglu/', methods=['GET', 'POST'])
def denglu():
    if request.method == 'GET':
        return render_template('denglu.html')
    else:
        username = request.form.get('user')  # post请求模式,安排对象接收数据
        password = request.form.get('pass')
        user = User.query.filter(User.username == username).first()  # 作查询,并判断
        if user:  # 判断用户名
            if user.check_password(password):# 判断密码
                session['user'] = username  # 利用session添加传回来的值username
                session.permanent = True  # 设置session过期的时间
                return redirect(url_for('daohang'))
            else:
                return u'用户密码错误'
        else:
            return u'用户不存在,请先注册'

  处理器模板:

 

8、发布功能:

(1)html文件:

{% extends 'daohang.html' %}
{% block fabutitle %}发布{% endblock %}
{% block fabuhead %}
    <link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
{% endblock %}

{% block daohangbody %}
<style>
.center {
    margin: auto;
    width: 60%;
    border: 3px solid #73AD21;
    padding: 10px;
}
</style>

<div class="panel panel-default center" style="height:450px;width:500px">
    <div class="panel-body">
        <div class="form-group">
        <form role="form" action="{{ url_for('fabu') }}" method="post">
          <div class="form-group">
                <label for="name" style="color: black">选择列表</label><br>
                <select class="form-control" style="height:35px;width:400px">
                    <option>1</option>
                    <option>2</option>
                    <option>3</option>
                    <option>4</option>
                    <option>5</option>
                </select>
                  <br>
                <label for="title" style="color:black">标题</label><br>
                <textarea class="form-control" rows="1" cols="50" id="title" name="title" style="height:35px;width:400px"></textarea><br>
                <label for="detail" style="color: black">详情</label><br>
                <textarea class="form-control" rows="5" cols="50" id="detail" name="detail" style="height:100px;width:400px"></textarea><br>
                <input style="color: whitesmoke" type="checkbox" name="c1" id="c1" value="">记住我<br>

                <div id=""><br></div>
                <input type="submit" value="发布" class="btn btn-default" onclick="">
            </div>
        </form>
    </div>
</div>
</div>
{% endblock %}

 

(2)py文件:

class Fabu(db.Model):
    __tablename__ = 'fabu'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    detail = db.Column(db.Text, nullable=False)
    creat_time = db.Column(db.DateTime, default=datetime.now)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    author = db.relationship('User', backref=db.backref('fabu'))


def loginFirst(fabu):
    @wraps(fabu)  # 加上wraps,它可以保留原有函数的__name__,docstring
    def wrapper(*args, **kwargs):  # 定义wrapper函数将其返回,用*args, **kwargs把原函数的参数进行传递
        if session.get('user'):  # 只有经过登陆,session才能记住并get到值
            return fabu(*args, **kwargs)
        else:
            return redirect(url_for('denglu'))
    return wrapper


@app.route('/fabu/', methods=['GET', 'POST'])
@loginFirst
def fabu():
    if request.method == 'GET':
        return render_template('fabu.html')
    else:
        title = request.form.get('title')
        detail = request.form.get('detail')
        author_id = User.query.filter(
            User.username == session.get('user')).first().id
        fabu = Fabu(title=title, detail=detail, author_id=author_id)
        db.session.add(fabu)
        db.session.commit()
        return redirect(url_for('daohang'))

 

9、评论功能:

(1)html文件:

{% extends 'daohang.html' %}
{% block fabu_viewtitle %}发布{% endblock %}
{% block fabu_viewhead %}
    <link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
{% endblock %}
{% block daohangbody %}

    <h2 href="#" class="text-center" style="color: oldlace">{{ ques.title }}</h2>
    <br>
    <p class="text-center">
        <a href="#">
            <small>{{ ques.author.username }}</small>
        </a>&nbsp&nbsp&nbsp
        <span class="pull-center" style="color: oldlace"><small>{{ ques.creat_time }}</small></span>
    </p>
    <hr>
    <div style="width: 700px;margin: auto">
     <p style="color: oldlace">{{ ques.detail }}</p>
    </div>
      <hr>
<form action="{{ url_for('comment') }}" method="post">
        <div class="form-group" style="height: 180px;width: 700px;margin: auto">
                    <textarea name="pinglun" class="form-control" rows="5" id="pinglun"
                              placeholder="请输入评论"></textarea>
            <input type="hidden" name="hidden_id" value="{{ ques.id }}">
            <br>
            <input type="submit" value="发送" class="btn btn-default" onclick="">
        </div>
        <div style="width: 700px;margin: auto">
                    <h4 style="color: oldlace">评论:({{ ques.comments|length }})</h4>
            <ul class="list-unstyled">
                {% for foo in comments %}
                    <li class="list-group-item">
                        <a>{{ foo.author.username }}</a>
                        <span class="badge pull-right">{{ foo.creat_time }}</span>
                        <p>{{ foo.detail }}</p>
                        <br>
                    </li>
                {% endfor %}
            </ul>
        </div>
</form>
{% endblock %}

(2)py文件:

class Comment(db.Model):
    __tablename__ = 'comment'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    author_id = db.Column(db.Integer,db.ForeignKey('user.id'))
    fabu_id = db.Column(db.Integer, db.ForeignKey('fabu.id'))
    creat_time = db.Column(db.DateTime, default=datetime.now)
    detail = db.Column(db.Text, nullable=False)
    fabu = db.relationship('Fabu',backref=db.backref('comments',order_by=creat_time.desc))
    author = db.relationship('User', backref=db.backref('comments'))


@app.route('/detail/<question_id>')
def detail(question_id):
    quest=Fabu.query.filter(Fabu.id==question_id).first()
    comments = Comment.query.filter(Comment.fabu_id == question_id).all()
    return render_template('fabu_view.html',ques=quest,comments=comments)


@app.route('/comment/',methods=['POST'])
@loginFirst
def comment():
    detail = request.form.get('pinglun')
    author_id = User.query.filter(User.username == session.get('user')).first().id
    fabu_id = request.form.get('hidden_id')
    comment = Comment(detail=detail,author_id=author_id,fabu_id=fabu_id)
    db.session.add(comment)  # 执行操作
    db.session.commit()  # 提交到数据库
    return redirect(url_for('detail',question_id=fabu_id))

 

10、个人中心实现:

html文件:

(1)user模板:

{% extends 'daohang.html' %}
{% block title %}个人中心{% endblock %}
{% block head %}

{% endblock %}

{% block daohangbody %}

<div style="width: 700px;margin: auto">
    <ul class="nav nav-pills ">
    <li class="active"><a href="{{ url_for('usercenter',user_id=user_id,tag=1) }}">个人信息</a></li>
    <li class="active"><a href="{{ url_for('usercenter',user_id=user_id,tag=2) }}">全部评论</a></li>
    <li class="active"><a href="{{ url_for('usercenter',user_id=user_id,tag=3) }}">全部发布</a></li>
    </ul>

{% block user %}{% endblock %}
</div>
{% endblock %}

(2)usercenter1:

{% extends 'user.html' %}
{% block user %}
<div class="page-header">
     <ul class="page-header">
        <h3 style="color: whitesmoke"><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{ username }}<br>
            <small style="color: azure">个人资料信息<span class="badge"></span></small>
        </h3>

        <div class="panel panel-default" style="height:180px;width:400px">
            <ul class="list-group" style="...">
                <li class="list-group-item">用户名:{{ username }}</li>
                <li class="list-group-item">昵称:</li>
                <li class="list-group-item">性别:</li>
                <li class="list-group-item">年龄:</li>
            </ul>
        </div>
    </ul>
</div>
{% endblock %}

(3)usercenter2:

{% extends 'user.html' %}
{% block user %}
    <div class="page-header">
        <ul class="page-header">
            <h3 style="color: whitesmoke" ><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{ username }}<br>
                <small style="color: azure">全部评论<span class="badge"></span></small>
            </h3>

        <div class="panel panel-default" style="width:700px">
            <ul class="list-group" style="...">
                {% for foo in comments %}
                    <li class="list-group-item">
                        <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span>
                        <a href="{{ url_for('usercenter',user_id=foo.author_id,tag=1) }}">{{ foo.author.username }}</a>
                        <span class="badge">{{ foo.creat_time }}</span>
                        <p style="...">{{ foo.detail }}</p>
                    </li>
                {% endfor %}
            </ul>
        </div>
        </ul>
    </div>
{% endblock %}

(4)usercenter3:

{% extends 'user.html' %}
{% block user %}
<div class="page-header">
    <ul class="page-header">
    <h3 style="color: whitesmoke"><span class="glyphicon glyphicon-user" aria-hidden="true"></span>{{ username }}<br>
    <small style="color: azure">全部问答<span class="badge"></span></small></h3>

    <ul class="list-group" style="height:300px;width:700px">
        {% for foo in fabus %}
          <li class="list-group-item">
             <span class="glyphicon glyphicon-heart-empty" aria-hidden="true"></span>
              <a href="{{ url_for('usercenter',user_id=foo.author_id,tag=1) }}">{{ foo.author.username }}</a>
              <span class="badge">{{ foo.creat_time }}</span>
              <p style="...">{{ foo.detail }}</p>
          </li>
        {% endfor %}
        </ul>
    </ul>
    </div>
{% endblock %}

py文件:

@app.route('/usercenter/<user_id>/<tag>')
@loginFirst
def usercenter(user_id,tag):
    user=User.query.filter(User.id==user_id).first()
    context={
        'user_id':user.id,
        'username': user.username,
        'fabus': user.fabu,
        'comments': user.comments
    }
    if tag=='1':
        return render_template('usercenter1.html',**context)
    elif tag=='2':
        return render_template('usercenter2.html', **context)
    else:
        return render_template('usercenter3.html', **context)

11、搜索功能:

@app.route('/search/')
def search():
    qu = request.args.get('q')
    ques = Fabu.query.filter(
        or_(
            Fabu.title.contains(qu),
            Fabu.detail.contains(qu)
        )
    ).order_by('-creat_time')
    return render_template('daohang.html', fabus=ques)

12、密码保护功能:

@property
    def password(self):
        return self._password

    @password.setter
    def password(self,row_password):
        self._password=generate_password_hash(row_password)

    def check_password(self,row_password):
        result=check_password_hash(self._password,row_password)
        return  result

 

 

 

posted on 2018-01-03 21:34  152陈斯璐  阅读(824)  评论(1编辑  收藏  举报