Flask基础学习3

参考视频:41-【实战】答案列表的渲染_哔哩哔哩_bilibili


flask 实现发送短信功能

复制代码
pip install flask-mail # 安装依赖

我这里用登录的网易邮箱获取的授权码(登录QQ邮箱的授权码总是断开收不到邮件),

复制代码
# config
# config mail
MAIL_SERVER = 'smtp.163.com'
MAIL_USE_SSL = True
MAIL_PORT = 465
MAIL_USERNAME = 'xxx@163.com'
MAIL_PASSWORD='xxx'
MAIL_DEFAULT_SENDER  = 'xxx@163.com'

@bp.route('/mail/test')
def mail_test():
    message = Message(subject='mail test',recipients=['xxx@qq.com'],body='xxx')
    mail.send(message)

运行结果:

邮箱发送验证功能实现

复制代码
@bp.route('/captcha/email')
def get_mail_cptcha():
    email = request.args.get('email')
    source= string.digits*4
    cap = random.sample(source,4)
    cap  = ''.join(cap)
    message = Message(subject='菜鸟学习测试', recipients=[email], body='你的验证码是:{}'.format(cap))
    mail.send(message)

    email_capt = EmailCaptchModel(email=email,captcha=cap)
    db.session.add(email_capt)
    db.session.commit()

    return jsonify({'code':200,'message':'','data':None})

查看DB数据

注册表单验证实现:

复制代码
# blueprints/forms.py
import wtforms
from wtforms.validators import Email,Length,EqualTo
from models import UserModel,EmailCaptchModel

class RegisterForm(wtforms.Form):
    email = wtforms.StringField(validators=[Email(message="邮箱格式错误!")])
    captcha = wtforms.StringField(validators=[Length(min=4,max=4,message="验证码格式错误!")])
    username = wtforms.StringField(validators=[Length(min=3,max=20,message="用户名格式错误!")])
    password = wtforms.StringField(validators=[Length(min=3,max=20,message="密码长度为4-20位!")])
    password_confirm = wtforms.StringField(validators=[EqualTo('password',message="两次输入的错误不一致!")])

    def validate_email(self, field):
        email = field.data
        user = UserModel.query.filter_by(email=email).first()
        if user:
            raise wtforms.ValidationError(message='该邮箱已经被注册!')

    def validate_captcha(self,field):
        captcha = field.data
        email = self.email.data
        captcha_model = EmailCaptchModel.query.filter_by(email=email,captcha=captcha).first()
        if not captcha_model:
            print('邮箱或验证码格式错误!')
            # raise wtforms.ValidationError(message='邮箱或验证码格式错误!')
        # else:
        #     db.session.delete(captcha_model)
        #     db.session.commit()

注册功能后端的实现

复制代码
# blueprints/auth.py
@bp.route('/register',methods = ['POST','GET'])
def register():
    if request.method == 'GET':
        return render_template('regist.html')
    form  = RegisterForm(request.form)
    if form.validate():
        email = form.email.data
        username= form.username.data
        password = form.password.data
        user= UserModel(email=email,username=username,password=generate_password_hash(password))
        db.session.add(user)
        db.session.commit()
        return redirect(url_for('auth.login'))
    else:
        print(form.data)
        print(form.errors)
        return redirect(url_for('auth.register'))

运行结果:

登录功能后端的实现,并将session信息加密保存到cookie中

复制代码
# forms.py
class LoginForm(wtforms.Form):
    email = wtforms.StringField(validators=[Email(message="邮箱格式错误!")])
    print(wtforms.validators.Email)
    password = wtforms.StringField(validators=[Length(min=4, max=20, message="密码长度为4-20位!")])

# auth.py
@bp.route('/login',methods = ['POST','GET'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    form = LoginForm(request.form)
    print(form.data)
    if form.validate():
        email = form.email.data
        password = form.password.data
        user = UserModel.query.filter_by(email=email).first()
        if not user:
            print('邮箱在数据库中不存在')
            return redirect(url_for('auth.login'))
        if check_password_hash(user.password,password):
            # cookie 存在浏览器上
            # flsk的session 是加密存在在cookie
            session['user.id'] = user.id
            return redirect(url_for('auth.index'))
        else:
            print('密码错误')
            return redirect(url_for('auth.login'))
    else:
        print(form.errors)
        return redirect(url_for('auth.login'))

注意: 配置session信息时要配置自定义密钥,否则会报错

复制代码
# 配置session
SECRET_KEY = 'DSAFSDFASFASDFADFSDSASFD' # 无要求,自定义

两个钩子的运用及实现

python 复制代码
# from flask import g
# 全局变量g
@login_required
def my_before_request():
    user_id = session.get('user_id')
    if user_id:
        user = UserModel.query.get(user_id)
        setattr(g,'user',user)
    else:
        setattr(g,'user',None)

@app.context_processor
def my_context_processor():
    return {'user':g.user}

配置用户的登录名称显示及注销功能的实现

python 复制代码
{% if user %}
  <li><a href="#">{{ user.username }}</a></li>
  <li><a href="{{ url_for('auth.logout') }}">注销</a></li>
{% else %}
  <li><a href="{{url_for('auth.login')}}">登录</a></li>
  <li><a href="{{url_for('auth.register')}}">注册</a></li>
{% endif %}
python 复制代码
@bp.route('/logout')
def logout():
    session.clear()
    return render_template('index.html')

发布问答后端接口的实现

python 复制代码
# model.py
class QuestionModel(db.Model):
    __tablename__ = 'question'
    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    title = db.Column(db.String(1000),nullable=False)
    content = db.Column(db.Text,nullable=False)
    create_time = db.Column(db.DateTime,default=datetime.now())
    author_id = db.Column(db.Integer,db.ForeignKey('user.id'))
    author = db.relationship(UserModel,backref = 'questions')


# form 验证器
class QuestionForm(wtforms.Form):
    title = wtforms.StringField(validators=[Length(min=4, max=100, message="标题格式错误!")])
    context = wtforms.StringField(validators=[Length(min=3, max=200, message="内容格式错误")])
python 复制代码
from flask import Blueprint,request,render_template
from .forms import QuestionForm
from decorators import login_required
from models import QuestionModel
from exts import db
bp=Blueprint('qa',__name__,url_prefix='/qa')

@bp.route('/question',methods = ['POST','GET'])
def question():
    if request.method == 'GET':
        return render_template('question.html')
    else:
        form  =QuestionForm(request.form)
        print(form.data)
        if form.validate():
            title = form.title.data
            context = form.context.data
            question = QuestionModel(title=title,content=context,author=g.user)
            db.session.add(question)
            db.session.commit()
            return render_template('index.html')
        else:
            print(form.errors)
            return render_template('question.html')

登录装饰器的实现,只有在登录后才可进行发布问答

python 复制代码
# 自定义登录装饰器
from functools import wraps
from flask import g,redirect,url_for
def login_required(func):
    # 保留func的信息
    @wraps(func)
    def inner(*args,**kwargs):
        if g.user:
            return func(*args,**kwargs)
        else:
            return redirect(url_for('auth.login'))
    return inner


# 配置装饰器
@login_required
def question()

问答列表首页功能实现:

python 复制代码
@bp.route('/')
def index():
    # 根据创建时间倒序排列
    questions = QuestionModel.query.order_by(QuestionModel.create_time.desc()).all()
    return render_template('index.html',questions=questions)

发布问答详细的功能实现

python 复制代码
@bp.route('/qa/detail/<qa_id>')
def qa_detail(qa_id):
    question=QuestionModel.query.get(qa_id)
    return render_template('detail.html',question=question)


@bp.post('/answer/public')
@login_required
def public_answer():
    form = AnswerForm(request.form)
    if form.validate():
        content = form.context.data
        question_id = form.question_id.data
        answer = AnswerModel(content=content,question_id=question_id,author_id=g.user.id)
        db.session.add(answer)
        db.session.commit()
        return redirect(url_for('qa.qa_detail',qa_id=question_id))
    else:
        print(form.errors)
    return redirect(url_for('qa.qa_detail', qa_id=request.form.get('question_id')))

搜索功能的实现

python 复制代码
@bp.route('/search')
def search():
    q = request.args.get('q')
    # 搜索标题的关键字
    questions= QuestionModel.query.filter(QuestionModel.title.contains(q)).all()
    return render_template('index.html',questions=questions)

okok

相关推荐
aha-凯心8 分钟前
vben 之 axios 封装
前端·javascript·学习
漫谈网络11 分钟前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
try2find2 小时前
安装llama-cpp-python踩坑记
开发语言·python·llama
博观而约取3 小时前
Django ORM 1. 创建模型(Model)
数据库·python·django
ytttr8733 小时前
matlab通过Q学习算法解决房间路径规划问题
学习·算法·matlab
精灵vector4 小时前
构建专家级SQL Agent交互
python·aigc·ai编程
Zonda要好好学习4 小时前
Python入门Day2
开发语言·python
Vertira4 小时前
pdf 合并 python实现(已解决)
前端·python·pdf
太凉4 小时前
Python之 sorted() 函数的基本语法
python
项目題供诗5 小时前
黑马python(二十四)
开发语言·python