期末作品检查

  1. 个人学期总结
  2. 总结Python+Flask+MysqL的web建设技术过程,标准如下:
    1. 即是对自己所学知识的梳理
    2. 也可作为初学入门者的简单教程
    3. 也可作为自己以后复习的向导
    4. 也是一种向外展示能力的途径

 

 

   父模板的制作  

  1. 制作网站网页共有元素的父模板html,包括顶部导航,中间区块划分,底部导航,底部说明等。

    父模版导航栏

<nav class="navbar  navbar-expand-lg  bg-light ">
  <a class="navbar-brand" href="#"></a>
  <div class="collapse navbar-collapse  " id="navbarNav">
    <ul class="nav navbar-nav navbar-right">
      <li class="nav-item ">
        <a class="nav-link  " href="{{ url_for("shouye")}}">首页 <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item ">
        <a class="nav-link disabled " href="#">动画</a>
      </li>
      <li class="nav-item">
        <a class="nav-link disabled" href="#">音乐</a>
      </li>
      <li class="nav-item">
        <a class="nav-link disabled" href="">游戏</a>
      </li>

    </ul>
         <form class="form-inline" action="{{ url_for("search") }}" method="get">
        <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" name="q">
        <button class="btn btn-secondary" type="submit">搜索</button>
    </form>
  </div>


    <div style="float: right;width: 10%">
        {% if username%}
            <a class="navbar-link disabled"href="">{{ username }}</a>&nbsp;&nbsp;&nbsp;
            <a class="navbar-link disabled" href="{{ url_for("logout") }}">注销</a>
        {% else %}
                <a class="navbar-link disabled"href="{{ url_for("denglu") }}">登陆</a>&nbsp;&nbsp;&nbsp;
                <a class="navbar-link disabled" href="{{ url_for("zhuce") }}">注册</a>
        {% endif %}
    </div>
</nav>

  

  2首页、登录页、注册页

  登录页:denglu.html  继承父模版  text.html  

{% extends "text.html" %} 
{% block denglu %}{% endblock %}
<form id="b" method="post" action="{{ url_for('denglu') }}">
<div class="container-fluid " id="denglu">
    <div class="mt-5 pt-5" >
        <div class="card border-primary mb-3 m-auto" style="max-width: 20rem;">
            <div class="card-header text-center">wgd</div>
            <div class="card-body text-primary">
                <h4 class="card-title">用户登录</h4>
                <div class="input-group mb-2 mr-sm-2 mb-sm-0">
                    <div class="input-group-addon"><i class="fa fa-user"></i></div>
                    <input type="text" class="form-control" placeholder="Username" id="uname" required="true" name="username">
                </div>
                <p  id="errorbox1" class="m-0 p-0 text-danger"> &nbsp</p>
                <div class="input-group mb-2 mr-sm-2 mb-sm-0">
                    <div class="input-group-addon"><i class="fa fa-lock"></i></div>
                    <input type="password" class="form-control" placeholder="Password" id="upass"   name="password">
                </div>
                <p id="errorbox2" class="m-0 p-0 text-danger"> &nbsp</p>
                <div class="row">
                    <div class="col-3">
                        <button  class="btn btn-outline-primary" onclick=" MyLogin()" >登录</button>
                    </div>

 JS文件Mylogin.jsp中的 Mylogin()函数对登录行为进行检验。

function MyLogin() {

            var oUname=document.getElementById("uname");
            var oUpass=document.getElementById("upass");
            var oError1=document.getElementById("errorbox1");
            var oError2=document.getElementById("errorbox2");
            oError1.innerHTML="<br>";
            oError2.innerHTML="<br>";
            if(oUname.value.length<6 ||oUname.value.length>20){
                oError1.innerHTML='Usename必须属于6-20位';
                return false;
            }else if((oUname.value.charCodeAt(0)>=48)&&(oUname.value.charCodeAt(0)<=57)){
                oError1.innerHTML='Useman不得以数字开头';
                return false;
                }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)){
                    oError1.innerHTML='用户名必须由数字或字母组成'
                    return false;
                }

            }

            if(oUpass.value.length<6||oUpass.value.length>20) {
                oError2.innerHTML = "Password必须属于6-20位";
                return false;
            }else {
                oError2.innerHTML="&nbsp"
                return true;
            }

        }

后台 denglu()函数控制登录。

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

注册功能 zhuce.html

    <form id='a' action="{{ url_for("zhuce") }}" method="post">
        <div class="container-fluid">
            <div class="mt-5 pt-5">
                <div class="card border-primary mb-3 m-auto" style="max-width: 20rem;">
                    <div class="card-header text-center">wgd</div>
                    <div class="card-body text-primary">
                        <h4 class="card-title" align="center">注册</h4>
                        <div class="input-group mb-2 mr-sm-2 mb-sm-0">
                            <div class="input-group-addon"><i class="fa fa-user"></i></div>
                            <input type="text" class="form-control" placeholder="Username" id="uname" required
                                   name="username">
                        </div>
                        <p id="errorbox1" class="m-0 p-0 text-danger"> &nbsp</p>
                        <div class="input-group mb-2 mr-sm-2 mb-sm-0">
                            <div class="input-group-addon"><i class="fa fa-lock"></i></div>
                            <input type="text" class="form-control" placeholder="nickname" id="nickname" required
                                   name="nickname">
                        </div>
                        <br>
                        <div class="input-group mb-2 mr-sm-2 mb-sm-0">
                            <div class="input-group-addon"><i class="fa fa-lock"></i></div>
                            <input type="password" class="form-control" placeholder="Password" id="upass" required
                                   name="password">
                        </div>
                        <p id="errorbox2" class="m-0 p-0 text-danger"> &nbsp</p>
                        <div class="input-group mb-2 mr-sm-2 mb-sm-0">
                            <div class="input-group-addon"><i class="fa fa-lock"></i></div>
                            <input type="password" class="form-control" placeholder="Password_check" id="upass_check"
                                   required onblur="check()"/>
                        </div>
                        <span id="warning">   </span>


                        <div class="row">
                            <div class="col-3">
                                <button class="btn btn-outline-primary" onclick= "MyLogin()">注册</button>
                            </div>

 JS文件Mylogin.jsp中的 check()函数对登录行为进行检验。

function check(){
    var password1=document.getElementById("upass").value;
    var password2=document.getElementById("upass_check").value;

    if(password1!==password2)
    {
        document.getElementById("warning").innerHTML="   两次密码的输入不一致";
        return ;
    }
    document.getElementById('a').submit();
}

后台 denglu()函数控制登录。

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

控制内容发布页  函数:def fankui(): 发布的内容存储在数据库wgd的表question 中

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

验证只有登录状态才能进行内容的发布  def log(func)

def log(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        if session.get('user'):
            return  func(*args,**kwargs)
        else:
            return render_template('denglu.html')
    return wrapper

 

内容发布后显示在首页  def shouye():

@app.route('/')
def shouye():
    context={
        'question':Question.query.all()
    }
    return render_template('shouye.html',**context)

for循环遍历数据库wgd中question表中的每一条内容。

{% for foo in question %}
    <div class="card w-57"></div>
  <li class="list-group-item rounded m-1" style="height: 10ch">
    <span>
        <a href="{{ url_for("pre",user_id=foo.author.id,tag='1') }}">{{ foo.author.username }}</a>
        <span class="">{{ foo.creat_time }}</span><br>
        <a href="{{ url_for("pinglun",question_id=foo.id) }}">{{ foo.title }}</a>
        <p>{{ foo.detail }}</p>
    </span>
      </li>{% endfor %}

点击文章标题进入内容页进行评论。

@app.route('/commemt/',methods=['GET','POST'])
@log
def comment():
if request.method=='GET':
return render_template(url_for('pinglun'))
else:
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
comment=Comment(author_id=auth_id,question_id=ques_id,detail=comment)
db.session.add(comment)
db.session.commit()
return redirect(url_for('pinglun',question_id=ques_id))


@app.route('/pinglun<question_id>')
def pinglun(question_id):
quest = Question.query.filter(Question.id==question_id).first()
return render_template('pinglun.html',ques=quest)

通过

{{ ques.author.username }}
{{ ques.detail }}

等语句调用数据库user 和comment表的用户信息 和发布的内容

 

<div class="card" style="width: 65rem;margin-top:2% ; margin-left: 23%;">
<div style= >
  <h2 class="card-header" style="margin-bottom: 0" >{{ ques.title }}</h2>
</div>
  <div class="card-body"style="padding-bottom: 1%">
      <h4 class="card-title"><a href="{{ url_for('pre',user_id=ques.id,tag='1') }}"> {{ ques.author.username }}&nbsp;</a><small> {{ ques.creat_time }}</small></h4>
      <hr>
      <h5>{{ ques.detail }}</h5>
      <hr>
       <form action="{{ url_for('comment') }}" method="post">
      <div style="width: 50rem;margin-left:6%;margin-top: 3%">
    <textarea  name="new_comment" class="form-control"  rows="10" placeholder="请写下评论" ></textarea><br>
          <input name="question_id" type="hidden" value="{{ ques.id }}"/>
            <button type="submit" class="btn btn-outline-primary ">提交评论</button>
        </div>
       </form>
  </div>

发表评论   通过循环语句遍历出每一条存储与数据库库中的评论。

<h5 style="margin-left: 3.5%">评论:<p>内容篇幅:{{ ques.detail|length }}</p></h5>
<div class="" style="width:58rem;margin-left: 4%;height: auto;margin-top: 0.5% ">
    {% for com in ques.comment %}
    <a href="#" >{{ com.author.username }}</a>
    <small>{{ com.creat_time }}</small>
    <p class="">{{ com.detail }}</p>
    {% endfor %}
</div>

点击 用户名可以进入当点登录的用户的个人信息页。

userbase.html继承父模板并作为个人信息页面的父模板。 写入个人信息页的导航栏。

 <div align="center">
    <ol style="font-size: large;list-style-type: none;" >
  <li role="presentation" class="breadcrumb-item " aria-current="page"><a   href="{{ url_for('pre',user_id=user.id,tag='1') }}"> 全部问答</a></li>
  <li role="presentation" class="breadcrumb-item active" aria-current="page"><a  href="{{ url_for('pre',user_id=user.id,tag='2') }}">全部评论</a></li>
  <li role="presentation" class="breadcrumb-item active" aria-current="page"><a  href="{{ url_for('pre',user_id=user.id,tag='3') }}">个人资料</a></li>
</ol></div><br>

@app.route('/presonal_message/<user_id>/<tag>')
@log
def pre(user_id,tag):
    user=User.query.filter(User.id==user_id).first()
    context={
        'user':user
    }
    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)
usercenter1.html usercenter2.html usercenter3.html 继承userbase.html

usercenter1.html
<body background="/static/img/WeChat%20Image_20171027161942.png" style="background-attachment: fixed;background-size: 100% 100%">
    <div style="margin-left: 28%;margin-top: 1.5%">
<div class="card" style="width: 60rem;height:auto">
    <div class="card-header">
  <h2><a href="{{ url_for('pre',user_id=user.id,tag='1') }}"> {{ user.username }}</a></h2>
  </div>
  <div class="card-body">
  <ul style="font-size: large;list-style-type: none;">
     <p class="text-info"style="font-size: 30px">所有问答</p>
        {% for foo in user.question %}
        <div>  <li>
            <a href="{{ url_for('pre',user_id=user.id,tag='3') }}">{{ foo.author.username }}</a>
            <span class="">{{ foo.creat_time }}</span><br>
        <a href="{{ url_for("pinglun",question_id=foo.id) }}">{{ foo.title }}</a>
        <p>{{ foo.detail }}</p>
         </li></div>

usercenter2.html
{% block usercenter %}

    <div style="margin-left: 28%;margin-top: 1.5%">
<div class="card" style="width: 60rem;height:auto">
    <div class="card-header">
  <h2><a href="{{ url_for('pre',user_id=user.id,tag='1') }}"> {{ user.username }}</a></h2>
  </div>


<div class="card text-left" style="width: 60rem;height: auto">
  <div class="card-body">
      <ul style="font-size: large;list-style-type: none">
    <p class="text-info"style="font-size: 30px">所有评论</p>
          {% for foo in user.comment %}
          <li>
              <a href="#">{{ foo.author.username }}</a>
                <span>{{ foo.creat_time }}</span><br>
                <p>{{ foo.detail }}</p>
          </li>
          {% endfor %}

 

usercenter3.html
 <div style="margin-left: 28%;margin-top: 1.5%">
<div class="card" style="width: 60rem;height:auto">
    <div class="card-header">
  <h2><a href="{{ url_for('pre',user_id=user.id,tag='1') }}"> {{ user.username }}</a></h2>
  </div>

    <div class="card text-left" style="width: 60rem;height: auto">
  <div class="card-body">

      <ul style="font-size: large;list-style-type: none">
          <p class="text-info"style="font-size: 30px">个人信息</p>
      <li><p>用户名:{{ user.username }}</p></li>
            <li><p>Id:{{ user.id }}</p></li>
            <li><p>内容篇幅:{{ user.question|length }}</p></li>
      </ul>
  </div>

<a href="{{ url_for('pre',user_id=user.id,tag='1') }}"> {{ user.username }}</a>  
让用户名变成链接,点击用户名跳转到个人中心。
导航栏上的用户名先
if user.check_password(password):
    session['user'] = username
    session['id'] = user.id
    session.permanent = True
    return redirect(url_for('shouye'))

session获取'id'属性赋值给user.id

父模板调用

href="{{ url_for('pre',user_id=session.get('id'),tag='1') }} 实现链接到个人中心。

实现登录 注册和用户名 注销的变换。

 

 {% if username%}
            <a class="navbar-link disabled"href="{{ url_for('pre',user_id=session.get('id'),tag='1') }}">{{ username }}</a>&nbsp;&nbsp;&nbsp;
            <a class="navbar-link disabled" href="{{ url_for("logout") }}">注销</a>
        {% else %}
                <a class="navbar-link disabled"href="{{ url_for("denglu") }}">登陆</a>&nbsp;&nbsp;&nbsp;
                <a class="navbar-link disabled" href="{{ url_for("zhuce") }}">注册</a>
        {% endif %}

       

搜索功能。

无搜索条件时:显示所有问答内容

输入搜索条件(模糊查询) 问答标题(如:你好),筛选出相关问答

搜索框的的name设置为'q' 

<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" name="q">
request请求'q'获取属性获取搜索的内容
进行条件查询
 Question.(数据库属性名).contains(qu)
@app.route('/search/')
def search():
    qu=request.args.get('q')
    ques=Question.query.filter(
        or_(

            Question.title.contains(qu),
            Question.detail.contains(qu)
            )
    ).order_by('creat_time')
    return render_template('shouye.html',question=ques)

 

提高数据库存储的密码的安全性。

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

 _password = db.Column(db.String(200), nullable=False)

2.编写对外的password

3.密码验证的方法:

@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

4.登录验证:

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

 

个人心得:

经过一学期的Python+flask+html的学习,对于开发一个Flask项目有了初步的接触和初步的了解,学习注册、登录、发布内容的相关知识。

但在这个粗糙的项目中还有很多很多的不足,功能上缺少文件上传,修改功能等一系列的基本功能,需要继续加工。

 

 

 

 

 

 

 


 





 

 

 

 

 

 

 

 

 

 






  

posted on 2018-01-05 10:19  069王国栋  阅读(283)  评论(0编辑  收藏  举报

导航