个人学期总结

1.本人在这学期中学习了管理信息系统这门科目,这门科目主要讲解了基于Python的Flask框架web建设项目。学习用html元素制作web网页,观察常用网页的HTML元素,在实际的应用场景中,用已学的标签模仿制作。制作自己的导航条,认识css的盒子模型,用div等元素布局形成html文件。完成了登录与注册页面的html+css+js, 夜间模式的开启和关闭,制作网站网页共有元素的父模板html,包括顶部导航,中间区块划分,底部导航,底部说明等。汇总相关的样式形成独立的css文件,使用 js代码形成独立的js文件,形成完整的base.html+css+js。 后期,进行flask项目,理解flask项目主程序,使用装饰器,设置路径与函数之间的关系。加载静态文件,父模板的继承和扩展。连接mysql数据库,创建用户模型,通过用户模型,对数据库进行增删改查,完成登录、注册、发布评论等功能,继续对我们的项目进行完善。

2、总结Python+Flask+MysqL的web建设技术过程,标准如下:

  1. 即是对自己所学知识的梳理
  2. 也可作为初学入门者的简单教程
  3. 也可作为自己以后复习的向导
  4. 也是一种向外展示能力的途径

一.开发工具:主要工具有:pycharm64.exe + Python 3.6 64-bit + MySQL + Navicat for MySQL(辅助工具)

二.界面的实现

1.导航条base.html,其他页面在编写的时候可以通过{% extends 'base.html' %}去调用

<!DOCTYPE HTML>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>{% block title %}首页{% endblock %}</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous">

<script src="{{ url_for('static',filename='js/base.js') }}"></script>

{% block head %}{% endblock %}
<body
    background="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1514551681109&di=4e795153c9660db74ff06c1463180876&imgtype=0&src=http%3A%2F%2Fimg.ph.126.net%2FlCFW6F0A46eced8IjrhWOQ%3D%3D%2F2570148012361858430.jpg"
    style="background-repeat: no-repeat; background-size: 100% 100%; background-attachment: fixed;">
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav mr-auto">
                <li class="nav-item"><a class="navbar-brand"
                    href="{{ url_for('index') }}">首页&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a></li>
                <li class="nav-item active"><a class="navbar-brand"
                    href="{{ url_for('question') }}">问题&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a></li>
                <form action="{{url_for('search')}}" method="get" class="form-inline" >
                    <input name="q" class="form-control mr-sm-2" type="search"
                        placeholder="请输入关键字" >
                    <button class="btn btn-outline-success my-2 my-sm-0" type="submit">搜索</button>
                </form>
            </ul>
            <nav class="navbar navbar-light bg-light">
                {% if username %} <a class="navbar-brand" href="{{ url_for('usercenter',user_id=session.get('userid'),tag=1) }}">{{ session.get('user')
                    }}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a>
                <a class="navbar-brand" href="{{ url_for('logout') }}">注销&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a>
                    {% else %} <a class="navbar-brand" href="{{ url_for('login') }}">登陆&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a>
                <a class="navbar-brand" href="{{ url_for('regist') }}">注册&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a>
                {% endif %} <img
                    src="{{ url_for('static',filename='image/on.jpg') }}" width="14"
                    height="14">



            </nav>
        </div>
    </nav>
    {% block main %} {% endblock %}
<div class="copyRight" style="background:skyblue;text-align: center;position:fixed; left:0px; bottom:0px; width:100%; height:30px; z-index:9999">
   Copyright huiyi版权所有
</div>
    <footer class="copyright"> </footer>
</body>
</html>

2.登陆页面(登录与注册页面的HTML+CSS+JS)

1通过用视图函数反转得到URL,{{url_for(‘login’)}},完成导航条里的链接。

(1)<script src="{{ url_for('static',filename='js/login.js') }}"></script>

(2)flask 从static文件夹开始寻找

(3)可用于加载css, js, image文件

2通过login.js实现(用户名6-12位,首字母不能是数字,只能包含字母和数字,密码6-12位,注册页两次密码是否一致)

3.对父模版的继承和扩展

(1)把一些公共的代码放在父模板中,避免每个模板写同样的内容。base.html

(2)子模板继承父模板  {% extends 'base.html’ %}

(3)父模板提前定义好子模板可以实现一些自己需求的位置及名称。

<title>{% block title %}{% endblock %}-MIS问答平台</title>

{% block head %}{% endblock %}

{% block main %}{% endblock %}

(4)子模板中写代码实现自己的需求。

  {% block title %}登录{% endblock %}

{% extends 'base.html' %}
{% block title %}
    登录
{% endblock %}

{% block head %}

    <link href="{{ url_for('static',filename='css/login.css') }}" rel="stylesheet" type="text/css">
    <script src="{{ url_for('static',filename='js/login.js') }}"></script>
{% endblock %}

{% block main %}
<br>
    <br>
    <br>
    <div class="login" >

          <h1>登录</h1>
        <form action="{{ url_for('login') }}" method="post">
        <p><input id="umane"type="text" name="username" placeholder="请输入用户名"></p>
        <p><input id="upass"type="password"  name="password" placeholder="请输入密码"></p>
          <div id="error_box"><br></div>
<p class="submit">
    <input  onclick="return myLogin()" type="submit" name="commit" value="登录">
     <input  onclick=window.alert("是否取消登录?") type="submit" name="commit" value="取消">
</p>
            </form>
    </div>


{% endblock %}

 3.评论页面

 

三.Flask项目

1.使用Flask中render_template,用不同的路径,返回首页、登录员、注册页。

2.实现注册

(1)js文件: onclick函数return True时才提交表单,return False时不提交表单。

(2)html文件:<form>中设置 action和method="post",<input> 中设置 name

(3)主py文件中:from flask import  request, redirect, url_for;@app.route('/regist/', methods=['GET', 'POST’])

@app.route('/regist/',methods=['GET','POST'])
def regist():
    if request.method=='GET':
        return render_template('regist.html')
    else:
        usern=request.form.get('username')
        passw=request.form.get('password')
        nickn=request.form.get('nickname')
        user=User.query.filter(User.username==usern).first()
        if user:
            return u'username existed'
        else:
            user=User (username=usern,password=passw,nickname=nickn)
            db.session.add(user)
            db.session.commit()
            return redirect(url_for('login'))

3.实现登录

(1)js:设置return

(2)html:设置form;input;onclick="return fnLogin()"

(3)py:@app.route设置methods;GET;POST(读取表单数据查询数据库:用户名密码对:记住用户名,跳转到首页;用户名密码不对:提示相应错误。)

@app.route('/login/',methods=['GET','POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        usern = request.form.get('username')
        passw = request.form.get('password')
        user = User.query.filter(User.username == usern).first()
        if user:
            if user.check_password(passw):
                session['user'] = usern
                session['userid'] = user.id
                session.permanent = True
                return redirect(url_for('base'))
            else:
                return u'password error'
        else:
            return u'password is not existed'

4.python装饰器

@loginFirst#发布前登录,python装饰器

def loginFirst(func):
    @wraps(func)
    def wrapper(*args, ** kwargs):
        if session.get('user'):
            return func(*args, ** kwargs)
        else:
            return redirect(url_for('login'))
    return  wrapper

 

5获取数据库

# 调用数据库把用户评论放在首页
@app.route('/index/')
def index():
    context = {
            'questions':Question.query.all()
        }
    return render_template('index.html',**context)

 

6实现搜索功能

(1)准备视图函数search()
(2)修改base.html 中搜索输入框所在的

<form action="{{ url_for('search') }}" method="get">

  <input name="q" type="text" placeholder="请输入关键字">

(3)完成视图函数search()

获取搜索关键字
q = request.args.get('q’)

条件查询
qu = Question.query.filter(Question.title.contains(q)).order_by('-creat_time’)

加载查询结果:
return render_template('index.html', question=qu)

组合条件查询

from sqlalchemy import or_, and_ 

 

7.密码保护

(1)更新User对象,设置对内的_password

class User(db.Model):

    __tablename__ = 'user' 

    _password = db.Column(db.String(200), nullable=False) #内部使用

 

(2)编写对外的password

from werkzeug.security import generate_password_hash, check_password_hash

    @property

    def password(self):  #外部使用,取值

        return self._password

    @password.setter

    def password(self, row_password):#外部使用,赋值

        self._password = generate_password_hash(row_password)

 

(3)密码验证的方法:

    def check_password(self, row_password): #密码验证

        result = check_password_hash(self._password,row_password)

        return result

 

(4)登录验证:

        password1 = request.form.get('password')

        user = User.query.filter(User.username == username).first()

        if user:

            if user.check_password(password1):

 

8评论页的导航

(1)个人中心—视图函数带标签页面参数tag
@app.route('/usercenter/<user_id>/<tag>')
def usercenter(user_id, tag):
   if tag == ‘1':
       return render_template('usercenter1.html', **context)

(2)个人中心—导航标签链接增加tag参数

<li role=“presentation”><a href=“{{ url_for(‘usercenter’,user_id = user.id,tag = ‘1’) }}">全部问答</a></li>

(3)个人中心—有链接到个人中心页面的url增加tag参数

 <a href="{{ url_for('usercenter',user_id = session.get('userid'), tag=1) }}">{{ session.get('user') }}</a>

#个人信息页
@app.route('/usercenter/<user_id>/<tag>')
@loginFirst#发布前登录,python装饰器
def usercenter(user_id,tag):
    user=User.query.filter(User.id== user_id).first()
    context={
      'user':user
    }

    if tag=='1':
        return render_template('user1.html',**context)
    elif tag=='2':
        return render_template('user2.html',**context)
    else:
        return render_template('user3.html',**context)

 

 

 

 

四.Mysql数据库

1.models.py

from datetime import datetime
from werkzeug.security import check_password_hash
from werkzeug.security import generate_password_hash

from exts import db
#登录的数据库
class User(db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(20), nullable=False)
    #password = db.Column(db.String(20), nullable=False)
    _password = db.Column(db.String(200), nullable=False)#内部使用
    nickname = db.Column(db.String(20))

    @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

#db.create_all()


#问题页的数据库
class Question(db.Model):
    __tablename__ = 'question'
    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('questions'))
#db.create_all()

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'))
    question_id=db.Column(db.Integer, db.ForeignKey('question.id'))
    detail = db.Column(db.Text, nullable=False)
    creat_time = db.Column(db.DateTime, default=datetime.now)
    question=db.relationship('Question',backref=db.backref('comments',order_by=creat_time.desc))
    author = db.relationship('User', backref=db.backref('comments'))

#db.create_all()

2.用户模型

config.py

import  os
SECRET_KEY = os.urandom(24)
# SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@127.0.0.1:3306/misdb1?charset=utf8'
# SQLALCHEMY_TRACK_MODIFICATIONS = False

SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123456@127.0.0.1:3306/misdb1?charset=utf8'
SQLALCHEMY_TRACK_MODIFICATIONS = False