一、我的学期总结css
经过这一个学期的Python学习,我已经从简单的简单输入输出交互,画一组同心圆以及词频统计再到HTML练习使用标签制做简单的页面。 最后通过一步步的学习与研究,到如今已经可以作css样式、JavaScript、HTML、Python去作一个简单相似于简书的能够发布简单的问答、评论、登陆、注册以及我的中心的做品。html
二、总结Python+Flask+MysqL的web建设技术过程,标准以下:python
1、开发工具:主要工具备:pycharm64.exe + Python 3.6 64-bit + MySQL + Navicat for MySQL(辅助工具)mysql
2、功能设计:web
一、登陆注册:sql
利用CSS样式以及和html,python数据库
注册须要用户名,用户密码以及电话号码:flask
用js进行注册验证,用户名首字母不能为数字,且必须为6到20位,电话号码必须为11位,初始密码与确认密码必须一致且在6到20位之间。session
js代码以下:app
function myRegister() { var oUname = document.getElementById("uname"); var oError = document.getElementById("error_box"); var oUpass = document.getElementById("upass"); var oConfirm = document.getElementById("uconfirmrpass"); var oUtel = document.getElementById("utel"); // var isError = true; oError.innerHTML = "<br>"; // oError.innerHTML="<br>" if ((oUname.value.length < 6) || (oUname.value.length > 20)) { oError.innerHTML = "用户名必须为6-20位"; return false; } else if ((oUname.value.charCodeAt(0) >= 48) && (oUname.value.charCodeAt(0) <= 57)) { oError.innerHTML = "用户名首位必须为字母"; 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)) { oError.innerHTML = "用户名必须为字母或数字"; return false; } } if (oUtel.value.length != 11) { oError.innerHTML = "电话号码必须为11位"; return false; } else for (var i = 0; i < oUname.value.length; i++) { if (oUtel.value.charCodeAt(i) < 48 || oUtel.value.charCodeAt(i) > 57) { oError.innerHTML = "电话号码必须为数字"; return false; } } if ((oUpass.value.length < 6) || (oUpass.value.length > 20)) { oError.innerHTML = "密码必须6-20位"; return false; } else if (oConfirm.value != oUpass.value) { oError.innerHTML = "两次输入的密码不一致"; return false; } return true; // window.alert("注册成功") }
注册HTML:
<form action="{{ url_for('register') }}" method="post"> <div class="container"> <div class="box"> <a href="{{ url_for('login') }}" class="active">登陆</a> <a>*</a> <a href="{{ url_for('register') }}">注册</a> </div> <br><br> <div class="input_box"> Username:<input id="uname" type="text" placeholder="你的昵称" name="Username"><br><br> Telphone:<input id="utel" type="text" placeholder="手机号" name="Telphone"><br><br> Password:<input id="upass" type="password" placeholder="设置密码" name="Password"><br><br> Confirmpass:<input id="uconfirmrpass" type="password" placeholder="确认密码" name="Confirmpass"><br><br></div> <div id="error_box"></div> <div> <button id="register" type="submit" onclick=" return myRegister()">注册</button> </div> </div> </form>
注册页面功能实现:
登陆实现:
登陆须要根据用户名,根据输入的密码查询与数据库的是否相同
js验证:
function myLogin() { var oUname = document.getElementById("uname"); var oError = document.getElementById("error_box"); var oUpass = document.getElementById("upass"); var isError = true; oError.innerHTML = "<br>"; if ((oUname.value.length < 6) || (oUname.value.length > 20)) { oError.innerHTML = "用户名必须为6-20位"; 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; } } if ((oUpass.value.length < 6) || (oUpass.value.length > 20)) { oError.innerHTML = "密码必须6-20位"; isError = false; return isError; } return isError; //return window.alert("登陆成功") }
登陆成功以后将会跳到首页。
2、导航框
导航框的实现是在base.html,这样其余页面只须要继承这个父模板,就能够用到导航框的内容。
下面是导航框的页面,登陆成功以后,就能够在右侧看到登陆名以及注销,点击注销将能够跳到登陆页面,从新登陆。
HTML:
<body id="myBody"> <nav class="daohang"> <div class="daohang_box"> <form action="{{ url_for('search')}}" method="get" > <a class="shouye" href="{{ url_for('index') }}">首页</a> <input id="search_box" type="text" name="q" placeholder="请输入关键词查找"> <button id="search" type="submit">搜索</button> <a class="xiaoqu3" href="{{ url_for('question') }}">发布影评</a> <img id="on_off" onclick="mySwitch()" src="{{ url_for('static',filename='images/bulbon.png') }}" > {% if Username %} {# <a class="xiaoqu1" href="{{ url_for('usercenter',user_id=session.get('id')}}">欢迎您{{session.get('Username'}}</a>#导航条的用户#} <a class="xiaoqu1" href="{{ url_for('usercenter',user_id=session.get('userid') ,tag='1')}}">欢迎您{{session.get('user')}}</a>#导航条的用户 {# <a class="xiaoqu1" href="#">欢迎您{{Username}}</a>#} <a class="xiaoqu2" href="{{ url_for('logout') }}">注销</a> {% else %} <a class="xiaoqu1" href="{{ url_for('login') }}">登陆</a> <a class="xiaoqu2" href="{{ url_for('register') }}">注册</a> {% endif %}</form> </div> </nav>
3、发布功能:
发布问答,首先要登陆才能发布
用了一个登陆装饰器,判断用户是否登陆:
def login_re(func): @wraps(func) def wrapper(*args, **kwargs): if session.get('user'): return func(*args, **kwargs) else: return redirect(url_for('login')) return wrapper
在发布影评的主py里加入
@login_re
便可判断是否登陆了。
question的HTML代码:
{% extends 'base.html' %} {% block title %}发布影评{% endblock %} {% block head %} <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/question.css') }}"> {% endblock %} {% block main %} <div class="fa"> <h1>发布影评</h1> <form action="{{ url_for('question') }}" method="post"> <div class="zhuti"> <label for="question">标题</label><br> <input id="question" type="text" name="title"></div><br> <div class="fa-question"> <label for="questionDetial">详情</label><br> <textarea id="questionDetial" rows="12" name="detail"></textarea></div> <div class="check"><input type="checkbox">check me out</div> <button class="sumbit" type="submit">提交</button> </form> </div> {% endblock %}
4、用户评论:
同一个问答要保证不一样用户的评论显示在相同问答下面:
<form action="{{ url_for('comment') }}" method="post"> <div class="ping"> <div class="pinglun"><label for="comment">评论:({{ ques.comments|length }})</label><br></div> <textarea id="comment" rows="8" name="commentdetail" PLACEHOLDER="写下你的评论"></textarea> <input name="question_id" type="hidden" value="{{ ques.id }}"/> <div class="but"> <button type="submit" class="fasong">发送评论</button> </div> </div> </form>
显示评论列表:
<ul> {% for foo in ques.comments %} <li> <img id="tubiao" src="{{ url_for('static',filename='images/tou.jpg') }}"> <a href="{{ url_for('usercenter',user_id=foo.author_id,tag=1 )}}">{{ foo.author.Username }}</a> <a class="creat_time">{{ foo.creat_time }}</a> <a class="title" href="{{ url_for('detail',question_id=foo.id) }}">{{ foo.title }}</a> <p class="abstract">{{ foo.detail }}</p> </li> {% endfor %}</ul>
5、查看我的中心
我的中心模板:
{# 新页面user.html,用<ul ><li role="presentation"> 实现标签页导航。#} {% extends 'base.html' %} {% block title %}我的中心{% endblock %} {% block head %} <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/userbase.css') }}"> {% endblock %} {% block main %} <div class="nav1"> <ul> <li role="presentation"><a href="{{ url_for('usercenter',user_id=user.id ,tag='1')}}">所有影评</a></li> <li role="presentation"><a href="{{ url_for('usercenter',user_id=user.id ,tag='2')}}">所有评论</a></li> <li role="presentation"><a href="{{ url_for('usercenter',user_id=user.id ,tag='3')}}">我的资料</a></li> </ul> </div><br><br><br> {% block user %}{% endblock %} {% endblock %}
所有影评:
{% extends 'userbase.html' %} {% block head %} <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/userbase.css') }}"> <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/user.css') }}"> {% endblock %} {% block user %} <div class="juli"> <h3>{{ user.Username}}<br> <small>所有影评</small> </h3> </div> <div class="xiao_ul"> <ul> {% for foo in user.question %} <li> <img id="tubiao" src="{{ url_for('static',filename='images/pl.jpg') }}"> <a href="#">{{ foo.author.Username }}</a> <a class="creat_time">{{ foo.creat_time }}</a><br> {# <p class="title" href="#" onclick="window.location.replace({{ url_for('detail')}})">{{ foo.title }}</p>#} <a class="title" href="{{ url_for('detail',question_id=foo.id)}}">{{ foo.title }}</a> <div class="abstract">{{ foo.detail }}</div> </li> {% endfor %}</ul> </div> {% endblock %}
所有资料:
{% extends 'userbase.html' %} {% block user %} {% block head %} <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/userbase.css') }}"> <link rel="stylesheet" type="text/css" href="{{ url_for('static',filename='css/user.css') }}"> {% endblock %} <div class="juli"> <h3>{{ user.Username }}<br> <small>我的资料</small> </h3> </div> <div class="xiao_ul"> <ul> <li>头像:<img id="tubiao" src="{{ url_for('static',filename='images/tou.jpg') }}"></li> <li>用户:{{ user.Username }}</li> <li>文章篇数:{{ user.question|length }}</li> <li>评论数:{{ user.comments|length }}</li> </ul> </div> {% endblock %}
6、模型分离与迁移
装饰器分离:
from flask import Flask, render_template, request, redirect, url_for, session from functools import wraps def login_re(func): @wraps(func) def wrapper(*args, **kwargs): if session.get('user'): return func(*args, **kwargs) else: return redirect(url_for('login')) return wrapper
exit.py
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
数据的迁移:
from flask_script import Manager from flask_migrate import Migrate,MigrateCommand from denglu import app from exts import db from models import Question,User,Comment manger=Manager(app) migrate=Migrate(app,db) manger.add_command('db',MigrateCommand) if __name__ == '__main__': manger.run()#使用Manager实例
表迁移:
from datetime import datetime from werkzeug.security import generate_password_hash,check_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)#内部使用 Telphone = 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 Question(db.Model): __tablename__ = 'question' id = db.Column(db.Integer, primary_key=True, autoincrement=True) author_id = db.Column(db.Integer,db.ForeignKey('user.id')) 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 = 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',order_by=creat_time.desc))# author = db.relationship('User', backref=db.backref('comments')) # db.create_all()
链接数据库:
import os #DEBUG=True SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:@127.0.0.1:3306/login_db?charset=utf8' SQLALCHEMY_TRACK_MODIFICATIONS = False SECRET_KEY = os.urandom(24)