Flask基础学习3

news2024/10/2 22:22:29

参考视频: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.coloradmin.cn/o/1471841.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3 实现 el-pagination页面分页组件的封装以及调用

示例图 一、组件代码 <template><el-config-provider :locale"zhCn"><el-pagination background class"lj-paging" layout"prev, pager, next, jumper" :pager-count"5" :total"total":current-page"p…

LeetCode二叉树中的第 K 大层和

题目描述 给你一棵二叉树的根节点 root 和一个正整数 k 。 树中的 层和 是指 同一层 上节点值的总和。 返回树中第 k 大的层和&#xff08;不一定不同&#xff09;。如果树少于 k 层&#xff0c;则返回 -1 。 注意&#xff0c;如果两个节点与根节点的距离相同&#xff0c;则…

SocketWeb实现小小聊天室

SocketWeb实现小小聊天室 消息推送的常见方式轮询长轮询SSE&#xff08;server-sent event&#xff09;&#xff1a;服务器发送事件WebSocketWebSocket简介WebSocket API 实现小小聊天室实现流程消息格式客户端-->服务端服务端-->客户端 消息推送的常见方式 轮询 浏览器…

C# TesseractOCR识别身份证号

https://github.com/tesseract-ocr/tessdata 新建控制台项目并添加包 Tesseract和Tesseract.Drawing 下载训练的模型 地址 代码实现 using Tesseract;var filePath "F:\\Desktop\\韦小宝.png"; var exePath AppDomain.CurrentDomain.BaseDirectory; var …

远程连接Redis

以连接阿里云上的Redis为例 1. 在阿里云安全组中开放端口 2.修改Redis启动时所用的配置文件&#xff08;redis.conf&#xff09; 2.1 修改ip地址 如图&#xff1a;将默认的本地ip bind 127.0.0.1地址改为bind 0.0.0.0 2.2 将保护模式关闭 将默认的 supervised yes 改为 n…

Docker基础(一)

文章目录 1. 基础概念2. 安装docker3. docker常用命令3.1 帮助命令3.2 镜像命令3.3 容器命令3.4 其他命令 4. 使用案例 1. 基础概念 镜像&#xff08;Image&#xff09;&#xff1a;Docker 镜像&#xff08;Image&#xff09;&#xff0c;就相当于是一个 root 文件系统。比如官…

Java Web(八)--Servlet(一)

介绍 官网&#xff1a;Servlet 3.1 API Documentation - Apache Tomcat 8.0.53 为什么需要&#xff1f; 提出需求: 请用你现有的html css javascript&#xff0c;开发网站&#xff0c;比如可以让用户留言/购物/支付? 引入我们动态网页(能和用户交互)技术>Servlet 是什…

医院LIS(全称Laboratory Information Management System)系统源码

目录 一、医院LIS系统概况 二、医院LIS系统建设必要性 三、为什么要使用LIS系统 四、技术框架 &#xff08;1&#xff09;总体框架 &#xff08;2&#xff09;技术细节 &#xff08;3&#xff09;LIS主要功能模块 五、LIS系统优势 &#xff08;1&#xff09;客户/用户…

【Python】记录生产编程小tips(字符串处理、列表删除、字典、csv、excel操作)持续更新

文章目录 一.for循环删除列表元素1.删除list元素方法2.直接删除往往结果与期望不一致3.循环删除元素的正确方法&#xff1a;方法1&#xff1a;while循环i减方法2&#xff1a;使用copy方法3&#xff1a;倒叙遍历 二.字符串处理库三.字典—dict运用四.csv操作五.excel操作1.读exc…

AI:139-基于深度学习的语音指令识别与执行

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

改进 RAG:自查询检索

原文地址&#xff1a;Improving RAG: Self Querying Retrieval 2024 年 2 月 11 日 让我们来解决构建 RAG 系统时的一个大问题。 我们不能依赖语义搜索来完成每个检索任务。只有当我们追求单词的含义和意图时&#xff0c;语义搜索才有意义。 But in case&#xff0c;我们正…

python自动化管理和zabbix监控网络设备(有线网络和路由配置部分)

目录 目录 一、拓扑图 二、core-sw1 三、core-sw2 四、sum-sw1 五、sum-sw2 六、FW1 七、DMZ-SW1 结语 一、拓扑图 二、core-sw1 sys sysname core-sw1 vlan batch 10 20 30 40 50 60 100 vlan batch 200 210 220 230 240 250 stp region-configuration region-name…

选择稳定代理IP需要考虑哪些因素?

很多人不知道怎么选择稳定的代理IP&#xff0c;也不知道当前代理IP套餐是否稳定&#xff0c;今天我们一起来分析下&#xff0c;选择稳定的代理IP可以从哪几方面去考虑。 1、代理IP的可用性 代理IP要稳定&#xff0c;先要可以用。一个代理IP池是否稳定&#xff0c;要看代理IP的…

区分服务 DiffServ

目录 区分服务 DiffServ 区分服务的基本概念 区分服务 DiffServ 的要点 每跳行为 PHB DiffServ 定义的两种 PHB 区分服务 DiffServ 区分服务的基本概念 由于综合服务 IntServ 和资源预留协议 RSVP 都较复杂&#xff0c;很难在大规模的网络中实现&#xff0c;因此 IET…

Docker复习笔记

Centos7安装Docker Docker官网:www.docker.com Docker官网仓库:hub.docker.com Docker文档是比较详细的 安装相关依赖 yum -y install gcc gcc-c yum install -y yum-utils 设置docker镜像仓库 yum-config-manager --add-repo https://download.docker.com/linux/centos/do…

Mysql运维篇(五) 部署MHA--主机环境配置

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; 大佬博文 https://www.cnblogs.com/gomysql/p/3675429.html MySQL 高可用&#xff08;MHA&#x…

js:通过input标签或Drag拖拽文件实现浏览器文件上传获取File文件对象

文档 https://developer.mozilla.org/zh-CN/docs/Web/API/Filehttps://developer.mozilla.org/zh-CN/docs/Web/API/HTMLElement/drag_event 通过读取文件可以获取File对象的信息 lastModified: 1707210706000 lastModifiedDate: Tue Feb 06 2024 17:11:46 GMT0800 (中国标准…

使用 Verilog 做一个可编程数字延迟定时器 LS7211-7212

今天的项目是在 Verilog HDL 中实现可编程数字延迟定时器。完整呈现了延迟定时器的 Verilog 代码。 所实现的数字延迟定时器是 CMOS IC LS7212&#xff0c;用于生成可编程延迟。延迟定时器的规格可以在这里轻松找到。基本上&#xff0c;延迟定时器有 4 种操作模式&#xff1a;…

备考北京高考数学:历年选择题真题练一练和解析(2014-2023)

还有三个多月的时间就要高考了&#xff0c;我们今天继续看北京市高考数学真题和解析。今天看5道选择题。独家制作的在线练习集&#xff0c;可以便捷地反复刷这些真题&#xff0c;吃透真题&#xff08;背后的知识点和解题技巧&#xff09;&#xff0c;让高考数学再上一个台阶。 …

【LeetCode:2476. 二叉搜索树最近节点查询 + 中序遍历 + 有序表】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…