1.个人学期总结

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

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

  

  学习初期第一方面,我认为学习每一知识点的开始则是了解其知识点的概念及基础。首先则是认识URL,观察那些常用网站的网址,区分它们不同组成部分。然后,观察web的浏览过程。最后,最为重要的则是实操,了解HTML基础并联系使用标签制作最简单的页面。自行了解各个标签的用法以及整体标签的规范。第二方面,认识div块与form表单的作用,利用div块与form表单制作登录页面。同时,练习使用各种列表,例如下拉列表选择框、无序列表、有序列表以及定义列表。 观察常用网页的HTML元素,并在实操过程中,用已学的标签模仿制作。通过网络搜索补充自己所想要的知识点,不要仅仅依赖于课堂。

  Python是一种面向对象的解释型计算机程序设计语言,Python是纯粹的自由软件, 源代码和解释器CPython遵循 GPL(GNU General Public License)协议。Python语法简洁清晰,特色之一是强制用空白符(white space)作为语句缩进。Flask是一个面向简单需求小型应用的“微框架(microframework)”,Flask选择组件的额外工作给那些使用案例不适用标准ORM的开发者提供了更多的灵活性,同样也给使用不同工作流和模版化系统的开发者们带来了灵活性。MySQL是一个关系型数据库管理系统MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件。MySQL是一种关系数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。

      制作网页初期,应制作一个有主题性的导航条。首先认识HTML头部元素:<base>  定义了页面链接标签的默认链接地址;<style>  定义了HTML文档的样式文件;<link>  定义了一个文档和外部资源之间的关系。其次练习样式表:行内样式表;内嵌样式表;外部样式表。最后分别练习定义三类选择器:HTML 选择器;CLASS 类选择器;ID 选择器。

<nav>
  <div></div>
</nav>

  当制作出了导航条之后,则需要实现样式的美化,这就需要用到CSS知识点的运用。首先要认识CSS的 盒子模型。然后了解CSS选择器的灵活使用。CSS可以通过三种方式实现:第一,图片文字用div等元素布局形成HTML文件;第二,新建相应CSS文件,并link到html文件中;第三,在HTML中的head标签中使用style标签块进行布局美化。

<div>
  <div></div>
<div>

  了解了HTML基础以及CSS基础后,同时还需要了解JS基础。同CSS一样,<script></script>也存在三种用法:第一,放在<body>中;第二,放在<head>中;第三,放在外部JS文件中。同时还需要了解三种输出数据的方式:使用 document.write() 方法将内容写到 HTML 文档中;使用 window.alert() 弹出警告框;使用 innerHTML 写入到 HTML 元素(用 "id" 属性来标识 HTML 元素、用document.getElementById(id) 方法访问 HTML 元素、用innerHTML 来获取或插入元素内容)。

  基础了解完后,则就开始了登录页面准备:通过JS语句增加错误提示框,并实现写好HTML+CSS文件,设置每个输入元素的id。定义JavaScript 函数,设置登录注册页面验证用户名与登录密码6-20位,注册还需包括验证用户名首字母不能是数字,只能包含字母和数字,输入的两次密码必须一致,并在各自html页面的button标签onclick调用这个函数。

function MyLogin() { //登录
    var oUname=document.getElementById("uname");
    var oUpass=document.getElementById("upass");
    var oError=document.getElementById("errorbox");

    //uname
     if(oUname.value=="Username"&&oUpass.value=="Password"){
        oError.innerHTML="Please input username";
        return;
    }else if(oUname.value.length<6||oUname.value.length>20){
        oError.innerHTML="Username must be 6 to 20";
        return;
    }else if(oUname.value.charCodeAt(0)>=48 && oUname.value.charCodeAt(0)<=57){
        oError.innerHTML="Frist Number";
        return;
    }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 = "Only letter or number";
            return;
        }
    }
    //upass
    if(oUpass.value.length<6||oUpass.value.length>20) {
        oError.innerHTML = "Password must be 6 to 20";
        return;
    }
    window.alert("Login Successful")
}
function MyRegister() { //注册
    var oUname=document.getElementById("uname");
    var oFUpass=document.getElementById("fupass");
    var oSUpass=document.getElementById("supass");
    var oError=document.getElementById("errorbox");
    //uname
    if(oUname.value=="Username"&&oFUpass.value=="Password"&&oSUpass.value=="Password"){
        oError.innerHTML="Please input username";
        return;
    }else if(oUname.value.length<6||oUname.value.length>12){
        oError.innerHTML="Username must be 6 to 12";
        return;
    }else if(oUname.value.charCodeAt(0)>=48 && oUname.value.charCodeAt(0)<=57){
        oError.innerHTML="Frist Number";
        return;
    }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 = "Only letter or number";
            return;
        }
    }
    //upass
    if(document.getElementById("fupass").value!=document.getElementById("supass").value){
        oError.innerHTML="The password must be the same";
        return;
    }else if(oFUpass.value.length<6||oFUpass.value.length>12) {
        oError.innerHTML = "Password must be 6 to 12";
        return;
    }
    window.alert("Register Successful")
}

   实现完页面的设计后,新建Flask项目,实现功能的使用。设置调试模式,理解Flask项目主程序。使用装饰器,设置路径与函数之间的关系;使用Flask中render_template,用不同的路径,返回首页、登录员、注册页;再用视图函数反转得到URL,{{url_for(‘login’)}},完成导航条里的链接。

@app.route('/链接路径/')
def 函数名():
    return render_template('register.html')

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

function MySwitch() {
    var on_off=document.getElementById("on_off")
    if(on_off.src.match("on")){
        on_off.src="../static/image/off1.PNG"
        document.getElementById("mybody").style.background="darkgray"
    }else{
        on_off.src="../static/image/on1.PNG"
        document.getElementById("mybody").style.background="wheat"
    }
}

  用url_for加载静态文件,flask 从static文件夹开始寻找可用于加载css, js, image文件。实现继承和扩展把一些公共的代码放在父模板中,避免每个模板写同样的内容。子模板继承父模板,父模板提前定义好子模板可以实现一些自己需求的位置及名称,子模板中写代码实现自己的需求。 

  配置链接数据库信息,建立mysql和app的连接,创建用户模型。通过用户模型,学习对数据库进行增删改查操作。

SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@localhost:3306/wuwen?charset=utf8'
SQLALCHEMY_TRACK_MODIFICATIONS = False
class User(db.Model):
    __tablename__='user'

  完成注册功能:实现js文件,onclick函数return True时才提交表单,return False时不提交表单。在主py文件定义函数,获取form中的数据且判断用户名是否存在:存在报错,若不存在则存进数据库中,redirect重定向到登录页。

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

  完成登录功能:与注册一样完成js文件,在主py文件定义函数,读取表单数据查询数据库。当用户名密码正确时,记住用户名并跳转到首页;当用户名密码不正确时,提示相应错误。同时,用session记住用户名。

def login():
    if request.method=='GET':
        return render_template('login.html')
    else:
        username = request.form.get('username')
        password = request.form.get('password')
        user = User.query.filter(User.username==username).first()
        if user:
            if user.password==password:
                session['user'] = username
                session.permanent = True
                return redirect(url_for('base'))
            else:
                return 'Password error'
        else:
            return 'Username inexistent'

  实现登录后更新导航:用上下文处理器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('home'))  

  编写要求登录的装饰器,定义函数将其返回。应用装饰器,要求在发布前进行登录,登录后可发布。建立发布内容的对象关系映射,完成发布函数。

@app.route('/question/',methods=['GET','POST'])
@loginFrist
def question():
    if request.method == 'GET':
        return render_template('question.html')
    else:
        title = request.form.get('title')
        detail = request.form.get('detail')
        user=User.query.filter(User.username == session.get('user')).first()
        author_id = user.id
        question = Question.query.filter(Question.title == title).first()
        if question:
            return 'Question existed'
        else:
            question1 = Question(title=title, detail=detail, author_id=author_id)
            question1.author = user
            db.session.add(question1)  # 保存到数据库
            db.session.commit()  # 提交
            return redirect(url_for('home'))

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

  在首页添加显示问答的列表,并定义好相应的CSS样式。首页列表显示全部问答:将数据库查询结果传递到前端页面,前端页面循环显示整个列表,进行问答排序。

<ul >
  <li></li>
</ul> 
@app.route('/question/',methods=['GET','POST'])
@loginFrist
def question():
    if request.method == 'GET':
        return render_template('question.html')
    else:
        title = request.form.get('title')
        detail = request.form.get('detail')
        user=User.query.filter(User.username == session.get('user')).first()
        author_id = user.id
        question = Question.query.filter(Question.title == title).first()
        if question:
            return 'Question existed'
        else:
            question1 = Question(title=title, detail=detail, author_id=author_id)
            question1.author = user
            db.session.add(question1)  # 保存到数据库
            db.session.commit()  # 提交
            return redirect(url_for('home'))
@app.route('/detail/')
def detail():
    return render_template('detail.html') 

  主PY文件写视图函数,带id参数。 首页标题的标签做带参数的链接,在详情页将数据的显示在恰当的位置。建立评论的对象关系映射,尝试实现发布评论。 

  完成评论功能:定义评论的视图函数,读取前端页面数据,保存到数据库中。用<input type="hidden" 方法获取前端的"question_id" ,显示评论次数,要求评论前登录(调用登录装饰器),尝试实现详情页面下的评论列表显示。

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

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

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

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

<a href="{{ url_for('usercenter1',user_id =session.get('id'),tag=1) }}" style="font-weight: 600">{{ username }}</a>
<a href="{{ url_for('usercenter1',user_id=foo.author_id,tag=1) }}">{{ foo.author.username }}</a>
<a href="{{ url_for('usercenter1',user_id=user.id,tag=1) }}"> {{ user.username }}</a>

  实现搜索功能:准备视图函数search(),修改父模 中搜索输入框所在的;完成视图函数获取搜索关键字,条件查询并加载查询结果,实现组合条件查询。

@app.route('/search/')
@loginFirst
def search():
    que=request.args.get('q')
    ques=Question.query.filter(
        or_(
            Question.title.contains(que),
            Question.detail.contains(que),
        )
    ).order_by('-creat_time')
    return render_template('home.html',questions=ques)

  最后实现密码保护功能。

@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

  如此则完成了一集齐登录、注册、发布问答简单功能的web项目系统。

 

posted on 2017-12-29 11:18  077吴文欣  阅读(293)  评论(0编辑  收藏  举报