个人学期总结

1.个人学期总结

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

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

 经过一个学期的对Python的学习,在老师的带领下完成了一个网站的基本网页的制作,包括:登录、注册、首页、问答页、问答详情页、用户中心等基本页面。现对这一学期学习的内容进行简单的梳理:

1、首先是使用标签制作基本网页(包括头部导航条、内容、页脚)

①头部导航条

<nav class="nav1">
</nav>

②内容

   <div>
内容
</div>

③页脚

2、对页面进行CSS样式设计 

CSS盒子模型的应用,

css样式设计的方法有三种:(1)新建相应CSS文件,并link到html文件中;(2)图片文字用div等元素布局形成HTML文件;(3)在HTML中的head标签使用style标签块

3、JS前段验证

<script></script>的三种用法:(1)放在<body>中;(2)放在<head>中;(3)放在外部JS文件中

登录界面实现:HTML+CSS+JS

4、基础页面制作完成之后,进行功能的实现:开始flask项目

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

@app.route('路径')
def 函数名():
    return render_template('返回页面')
<nav>#导航条里的链接
<a href="{{ url_for('index') }}">首页</a>
<a href="{{ url_for('login') }}">login</a>
<a href="{{ url_for('register')}}">register</a>
</nav>

5、夜间模式的开启与关闭,放置点击的按钮或图片,定义开关切换函数,onclick函数调用。制作网站网页共有元素的父模板html,包括顶部导航,中间区块划分,底部导航,底部说明等,汇总相关的样式形成独立的css文件,汇总相关的js代码形成独立的js文件,形成完整的base.html+css+js

function mySwitch() {
     var myele = document.getElementById("on_off");
     if (myele.src.match("bulbon")){
         myele.src="http://www.runoob.com/images/pic_bulboff.gif";
         document.getElementById("myBody").style.background="black";
         document.getElementById("myBody").style.color="white";
     }
     else {
         myele.src="http://www.runoob.com/images/pic_bulbon.gif";
         document.getElementById("myBody").style.background="white";
         document.getElementById("myBody").style.color="black";

     }

 }

6、用url_for加载静态文件

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

以及子模板继承父模板

  {% extends 'base.html’ %}

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

<title>{% block title %}{% endblock %}标题</title>

{% block head %}{% endblock %}

{% block main %}{% endblock %}

子模板中写代码实现自己的需求。block

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

7、连接MySQL数据库,创建用户模型

SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@127.0.0.1:3306/mis_db?charset=utf8'
SQLALCHEMY_TRACK_MODIFICATIONS = False
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import config

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

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)
    nickname = db.Column(db.String(20), nullable=False)


db.create_all()

@app.route('/')
def hello_world():
    return 'Hello World!'


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

8、完成注册功能

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

function fnRegister() {
    var oUname = document.getElementById("uname");
    var oNumber = document.getElementById("number");
    var oUpass = document.getElementById("upass");
    var oError = document.getElementById("error_box");
    var isError = true;
    oError.innerHTML = "<br>";
    //uname
    if (oUname.value.length == 0) {
        oError.innerHTML = "用户名不能为空!";
        isError = false;
        return isError;
    }
    if (oUname.value.length > 10 || oUname.value.length < 6) {

        oError.innerHTML = "用户名必须是6-10位!";
        isError = false;
        return isError;

    } else if ((oUname.value.charCodeAt(0) >= 48) && (oUname.value.charCodeAt(0)) <= 57) {
        oError.innerHTML = "用户名首字母不能是数字!";
        isError = false;
        return isError;
    } else for (var i = 0; i < oUname.value.length; i++) {
        if ((oUname.value.charCodeAt(i) < 48 || oUname.value.charCodeAt(i) > 57) && (oUname.value.charCodeAt(i) < 97 || oUname.value.charCodeAt(i) > 122)) {
            oError.innerHTML = "用户名只能为数字和字母";
            isError = false;
            return isError;
        }
    }
        //tel
        if (oNumber.value.length == 0) {
            oError.innerHTML = "手机号不能为空!";
            isError = false;
            return isError;
        }
        if (oNumber.value.length != 11) {
            oError.innerHTML = "手机号必须是11位!";
            isError = false;
            return isError;
        } else for (var j = 0; j < oNumber.value.length; j++) {
            if ((oNumber.value.charCodeAt(j) < 48) && (oNumber.value.charCodeAt(j)) > 57) {
                oError.innerHTML = "手机号只能为数字!";
                isError = false;
                return isError;
            }
        }

        //upass
        if (oUpass.value.length == 0) {
            oError.innerHTML = "密码不能为空!";
            isError = false;
            return isError;
        }
        if (oUpass.value.length > 10 || oUpass.value.length < 6) {
            oError.innerHTML = "用户密码6-10位!";
            isError = false;
            return isError;
        }
        if (document.getElementById("upass").value != document.getElementById("chpass").value) {
            oError.innerHTML = "密码不一致";
            isError = false;
            return isError;
        }

        //window.alert("注册成功!")
        return isError;
    }

主py文件中:判断用户名是否存在:存在则报错,不存在,存到数据库中,redirect重定向到登录页

@app.route('/register/',methods=['GET','POST'])
def register():
    if request.method =='GET':
        return  render_template('register.html')
    else:
        usern = request.form.get('uname')
        teln = request.form.get('number')
        passw = request.form.get('upass')
        user = User.query.filter(User.username==usern).first()
        if user:
            return 'username existed'
        else:
            user1= User(username=usern,tel=teln,password=passw)
            db.session.add(user1)
            db.session.commit()
            return redirect(url_for('login'))

9、完成登录功能,用session记住用户名

@app.route('/login/',methods=['GET','POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        usern = request.form.get('uname')
        passw = request.form.get('upass')
        user = User.query.filter(User.username==usern).first()
        if user:
            if user.password == passw:
                session['user'] = usern;
                return redirect(url_for('index'))
            else:
                return 'password error!'
        else:
            return 'username is not exister!'

10、登录功能实现后,用上下文处理器app_context_processor定义函数,获取session中保存的值,返回字典,在父模板中更新导航,插入登录状态判断代码。(注意用{% ... %}表示指令,{{ }}表示变量),完成注销功能,(清除session,跳转页面)。

@app.context_processor
def mycontext():
    usern = session.get('user')
    if usern:
        return{'username':usern}
    else:
        return {}

@app.route('/logout')
def logout():
    session.clear()
    return redirect(url_for('index'))

11、完成发布功能

 编写要求登录的装饰器
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

应用装饰器,要求在发布前进行登录,登录后可发布。建立发布内容的对象关系映射。完成发布函数,保存到数据库,重定向到首页。

@app.route('/question/',methods=['GET','POST'])
@loginFirst
def question():
    if request.method =='GET':
        return  render_template('question.html')
    else:
        biaoti = request.form.get('biaoti')
        detail = request.form.get('detail')
        author_id = User.query.filter(User.username==session.get('user')).first().id
        question = Question(title=biaoti,detail=detail,author_id=author_id)

        db.session.add(question)
        db.session.commit()
    return redirect(url_for('index'))

 

12、制作首页的显示列表

<ul class="news-list">
           <li style="padding-left: 0px; padding-right: 10px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 0px 0px;">
                    <span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>
                    <a href="#">username</a>
                    <br>
                    <a href="#">title</a>
                    <span class="badgs">creat_time</span>
                    <p>detail{{ questions }}</p>
                </li>
            </ul>

13、首页列表显示全部问答:将数据库查询结果传递到前端页面 Question.query.all(),前端页面循环显示整个列表,问答排序,完成问答详情页布局:包含问答的全部信息,评论区,以往评论列表显示区,在首页点击问答标题,链接到相应详情页。

@app.route('/question/',methods=['GET','POST'])
@loginFirst
def question():
    if request.method =='GET':
        return  render_template('question.html')
    else:
        biaoti = request.form.get('biaoti')
        detail = request.form.get('detail')
        author_id = User.query.filter(User.username==session.get('user')).first().id
        question = Question(title=biaoti,detail=detail,author_id=author_id)

        db.session.add(question)
        db.session.commit()
    return redirect(url_for('index'))
@app.route('/questionDetail/')
def questionDetail():
    return render_template('questionDetail.html')
         <ul class="news-list">
                {% for foo in questions %}
                    <li style="padding-left: 0px; padding-right: 10px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 0px 0px;">
                        <span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>
                        <a href="#">{{ foo.author.username }}</a>
                        <br>
                        <a href="#" onclick="window.location.replace({{ url_for("questionDetail") }})">{{ foo.title }}</a>
                        <span class="badgs">{{ foo.creat_time }}</span>
                        <p>{{ foo.detail}}</p>
                    </li>
                {% endfor %}
            </ul>

14、从首页问答标题跳转到问答详情页

@app.route('/questionDetail/<question_id>')
def questionDetail(question_id):
    quest=Question.query.filter(Question.id==question_id).first()
    return render_template('questionDetail.html',ques=quest)
<div class="list-container">
            <ul class="news-list">
                {% for foo in questions %}

                    <li style="padding-left: 0px; padding-right: 10px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 0px 0px;">
                        <span class="glyphicon glyphicon-leaf" aria-hidden="true"></span>
                        <a href="#">{{ foo.author.username }}</a>
                        <br>
                        <a href=" {{ url_for('questionDetail',question_id=foo.id)}}">{{ foo.title }}</a>
                        <span class="badgs">{{ foo.creat_time }}</span>
                        <p>{{ foo.detail}}</p>
                    </li>
                {% endfor %}
            </ul>
</div>

15、实现评论功能:

定义评论的视图函数,读取前端页面数据,保存到数据库中

@app.route('/comment/',methods=['POST'])
@loginFirst
def comment():
    comment=request.form.get('new_comment')
    ques_id=request.form.get('question_id')
    auth_id=User.query.filter(User.username==session.get('user')).first().id
    comm=Comment(author_id=auth_id,question_id=ques_id,detail=comment)
    db.session.add(comm)
    db.session.commit()
    return redirect(url_for('questionDetail',question_id=ques_id))
<form action="{{ url_for('comment') }}" method="post">
        <div class="pinglun">
            <textarea name="new_comment" class="form-control" rows="3" id="new-comment" placeholder="write your comment">
            </textarea>
            <input name="question_id" type="hidden" value="{{ ques.id }}"/>
        </div>
        <button type="submit" class="btn btn-default">发送</button>
    </form>
    <hr>

    <h4>评论:({{ ques.comments|length }})</h4>
    <hr>


    <ul class="news-list">
        {% for foo in ques.comments %}
            <li style="padding-left: 0px; padding-right: 10px; box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 0px 0px;">
                <span class="glyphicon glyphicon-leaf" aria-hidden="true" ></span>
                <a href="{{ foo.author.username }}"></a>
                <br>
                <a href=" {{ url_for('questionDetail',question_id=foo.id)}}">{{ foo.title }}</a>
                <span class="badgs">{{ foo.creat_time }}</span>
                <p>{{ foo.detail}}</p>
            </li>
        {% endfor %}

16、评论列表显示,个人中心显示:

显示所有评论,所有评论排序,显示评论条数

#用户中心
@app.route('/usercenter/<user_id>/')
@loginFirst
def usercenter(user_id):
    user = User.query.filter(User.id==user_id).first()
    context={
        'username1':user.username,
        'questions':user.question,
        'comments':user.comments
    }
    return render_template('usercenter.html',**context)
{{ ques.comments|length }}

17、实现评论列表显示及排序。

完成个人中心:个人中心的页面布局(html文件及相应的样式文件),定义视图函数向前端页面传递参数,页面显示相应数据:发布的全部问答、发布的全部评论、个人信息;各个页面链接到个人中心。

实现标签页导航:利用嵌套继承,制作个人中心的三个子页面,重写userbase.html中定义的user块,分别用于显示问答、评论、个人信息。个人中心—视图函数、导航标签与HTML页面链接增加tag参数。

#用户中心
@app.route('/usercenter/<user_id>/<tag>')
@loginFirst
def usercenter(user_id,tag):
    user = User.query.filter(User.id==user_id).first()
    context={
        'username_id': user.id,
        'username1':user.username,
        'questions':user.question,
        'comments':user.comments
    }
    if tag == '1':
        return render_template('usercenter.html',**context)
    elif tag == '2':
        return render_template('all_question.html', **context)
    else:
        return render_template('all_comment.html', **context)

18、实现搜索功能

#搜索
@app.route('/search/')
def search():
    qu=request.args.get('q')
    # ques=Question.query.filter(Question.title.contains(qu))#单一条件查询
    ques = Question.query.filter(
        or_(
            Question.title.contains(qu),
            Question.detail.contains(qu)
        )
    ).order_by('-creat_time')
    return render_template('index.html',questions=ques)
{#搜索#} 
<form action="{{ url_for('search') }}" method="get">
    <div class="b">
    <input id="search" type="text" name="q" placeholder="请输入关键字">
     <button id="button1" type="submit" >查找</button></div>
        {#<input id="button1" type="button" name="sousuo" value="搜索"></div>#}
</form>

19、密码保护

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(200), nullable=False)#内部使用
    nickname = db.Column(db.String(20))
    tel = 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

 

20、模型分离

模型分离--让代码更方便管理:新建models.py,将模型定义全部放到这个独立的文件中。

from datetime import datetime
from werkzeug.security import generate_password_hash,check_password_hash
from exts import db

class User(db.Model):
    __tablename__ = 'user'
    # __tablename__ = 'user_test'
    id=db.Column(db.Integer,primary_key=True,autoincrement=True)
    username=db.Column(db.String(20),nullable=False)
    _password = db.Column(db.String(200), nullable=False)#内部使用
    nickname = db.Column(db.String(20))
    tel = 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

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('question'))

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'))
    author = db.relationship('User',backref=db.backref('comments'))

新建exts.py,将db = SQLAlchemy()的定义放到这个独立的文件中。

from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

models.py和主py文件,都从exts.py中导入db。

在主py文件中,对db进行始化,db.init_app(app)。

db.init_app(app)

21、数据迁移

新建manage.py

from flask_script import Manager
from flask_migrate import Migrate,MigrateCommand
from first import app
from exts import db
from models import User,Comment,Question
manager=Manager(app)
migrate = Migrate(app,db)
manager.add_command('aa',MigrateCommand)
if __name__ == '__main__':
    manager.run()#启动migrate

新建decorate.py

from functools import wraps
from flask import render_template, request, redirect, url_for,session
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

以上即使本学期所学内容。

posted @ 2018-01-06 16:04  091王卡  阅读(168)  评论(0编辑  收藏  举报