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' # 无要求,自定义

两个钩子的运用及实现

# 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}

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

{% 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 %}
@bp.route('/logout')
def logout():
    session.clear()
    return render_template('index.html')

发布问答后端接口的实现

# 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="内容格式错误")])
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')

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

# 自定义登录装饰器
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()

问答列表首页功能实现:

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

发布问答详细的功能实现

@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')))

搜索功能的实现

@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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/408141.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python入门必学:单引号、双引号与三引号的差异与应用

Python入门必学&#xff1a;单引号、双引号与三引号的差异与应用 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程 &#x1f448; 希望得…

HC595级联原理及实例 - STM32

74HC595的最重要的功能就是&#xff1a;串行输入&#xff0c;并行输出。其次&#xff0c;74HC595里面有2个8位寄存器&#xff1a;移位寄存器、存储寄存器。74HC595的数据来源只有一个口&#xff0c;一次只能输入一个位&#xff0c;那么连续输入8次&#xff0c;就可以积攒为一个…

MiKTeX安装后,Latex编译后PDF无法预览,是灰色的

解决方式删掉编译器就可以&#xff0c; 即删掉MiKTeX MiKTeX安装后会将编译器默认修改为MiKTeX&#xff0c;这个时候会显示报错&#xff0c;简单粗暴的方式是删掉MiKTeX软件

python统计分析——单因素方差分析

参考资料&#xff1a;用python动手学统计学 方差分析&#xff1a;analysis of variance&#xff0c;缩写为ANOVA 1、背景知识 1.1 要使用方差分析&#xff0c;数据的总体必须服从正态分布&#xff0c;而且各个水平内部的方差必须相等。 1.2 反复检验导致显著性结果更易出现…

相机选型介绍

摄影测量中&#xff0c;相机是非常重要的角色&#xff0c;合适的相机产出合适的图像&#xff0c;得到合适的重建精度&#xff0c;这是相机的重要性。 您也许第一反应是&#xff0c;摄影测量所需的理想相机&#xff0c;是有着超高分辨率的相机&#xff0c;但事实可能并非如此&a…

太阳能光伏模型的参数确定及模型应用介绍

一、太阳能光伏模型介绍 ​ 太阳能通过光伏&#xff08;PV&#xff09;发电系统转化为电能。通过使用新材料技术&#xff0c;一直致力于提高光伏系统中太阳能电池的功率转换效率。基于钙钛矿太阳能电池的冠军器件具有24.8%的认证功率转换效率&#xff0c;仍有很大的改进空间。…

学习 LangChain 的 Passing data through

学习 LangChain 的 Passing data through 1. Passing data through2. 示例 1. Passing data through RunnablePassthrough 允许不改变或添加额外的键来传递输入。这通常与 RunnableParallel 结合使用&#xff0c;将数据分配给映射中的新键。 RunnablePassthrough() 单独调用&…

ChatGPT Plus遇到订阅被拒原因与解决方案

ChatGPT Plus被广泛认为相比普通版本更快、更强&#xff0c;并且能最先体验新功能。 很多小伙伴再订阅时遇到图片中的问题 错误提示包括这些&#xff1a; Your credit card was declined.Try paying with a debit card instead.您的信用卡被拒绝了。请尝试用借记卡支付。你的…

Data-Shape制作UI节点简介

很多小伙伴对于Data-Shape制作简单的UI都是似懂非懂&#xff0c;群里很多小伙伴也总是询问相关的问题&#xff0c;那么&#xff0c;今天我就简单举几个例子&#xff0c;专门介绍下Data-Shape创建简单UI的教程。 首先&#xff0c;本次教程&#xff0c;使用的是Data-Shape 2021.…

队列基础练习(C语言实现)

目录 队列基础练习 用队列实现栈 用栈实现队列 设计循环队列 队列基础练习 用队列实现栈 题目链接&#xff1a;225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部…

政安晨【示例演绎虚拟世界开发】(一):Cocos Creator 的 Hello World

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: AI虚拟世界大讲堂 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正。 前言 Cocos Creator是一款非常强大的游戏开发引擎&#xff0c;它有着优秀…

基于springboot+vue的安康旅游网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

洛谷P5723 质数口袋 题解

#题外话&#xff08;第39篇题解&#xff09;&#xff08;本题为普及-难度&#xff09; #先看题目 题目链接https://www.luogu.com.cn/problem/P5723 #思路&#xff08;看代码吧&#xff09; #代码 #include <bits/stdc.h> using namespace std; bool p(int p_i){for(i…

啊丢的刷题记录手册

1.洛谷题P1923 求第k小的数 题目描述 输入 n&#xff08;1≤n<5000000 且 n 为奇数&#xff09;个数字ai​&#xff08;1≤ai​<109&#xff09;&#xff0c;输出这些数字的第 k 小的数。最小的数是第 0 小。 请尽量不要使用 nth_element 来写本题&#xff0c;因为本题…

《优化接口设计的思路》系列:第八篇—分页接口的设计和优化

系列文章导航 第一篇—接口参数的一些弯弯绕绕 第二篇—接口用户上下文的设计与实现 第三篇—留下用户调用接口的痕迹 第四篇—接口的权限控制 第五篇—接口发生异常如何统一处理 第六篇—接口防抖(防重复提交)的一些方式 第七篇—接口限流策略 第八篇—分页接口的设计和优化 …

C语言实现简单选择排序

简单选择排序 简单选择排序的平均复杂度为 O(n2),但效率通常比相同平均复杂度的直接插入排序还要差。但由于选择排序是 内部排序&#xff0c;因此在内存严格受限的情况下还是可以用的。选择排序的原理很简单&#xff0c;如下图所示&#xff1a;持续从未处理元素中找到最小值并加…

虚拟机的四种网络模式对比

nat网络地址转换 nat网络 桥接 内网模式 仅主机

【数据结构(顺序表)】

一、什么是数据结构? 数据结构是由“数据”和“结构”两词组合而来。 什么是数据&#xff1f;常见的数值1、2、3、4.....、教务系统里保存的用户信息&#xff08;姓名、性别、年龄、学历等等&#xff09;、网页里肉眼可以看到的信息&#xff08;文字、图片、视频等等&#xff…

Google炸场!最强轻量级、开放模型Gemma发布,个人PC就能用,内部员工:强是强,但名字取得让我混乱

想参与根多多学术讨论&#xff0c;请加qq群 链接直达&#xff1a;00后编程交流qq群 如果想要聊天交友&#xff0c;可以加qq群 链接直达&#xff1a;00后聊天交友处cp 欢迎大家加入 不同于OpenAI的闭源大模型&#xff0c;科技巨头如Google和Meta正积极投入开放模型的开发&a…

Qt的QFileSystemModel与QTreeView、QTableView、QListView的组合使用

1.相关描述 QFileSystemModel与QTreeView、QTableView、QListView的组合&#xff0c;当QTreeView点击发生改变&#xff0c;QTableView和QListView也会发生变化 2.相关界面 3.相关代码 mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h"…