• Flask基础学习3


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


     flask 实现发送短信功能

    pip install flask-mail # 安装依赖

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

    1. # config
    2. # config mail
    3. MAIL_SERVER = 'smtp.163.com'
    4. MAIL_USE_SSL = True
    5. MAIL_PORT = 465
    6. MAIL_USERNAME = 'xxx@163.com'
    7. MAIL_PASSWORD='xxx'
    8. MAIL_DEFAULT_SENDER = 'xxx@163.com'
    1. @bp.route('/mail/test')
    2. def mail_test():
    3. message = Message(subject='mail test',recipients=['xxx@qq.com'],body='xxx')
    4. mail.send(message)

    运行结果:

    邮箱发送验证功能实现

    1. @bp.route('/captcha/email')
    2. def get_mail_cptcha():
    3. email = request.args.get('email')
    4. source= string.digits*4
    5. cap = random.sample(source,4)
    6. cap = ''.join(cap)
    7. message = Message(subject='菜鸟学习测试', recipients=[email], body='你的验证码是:{}'.format(cap))
    8. mail.send(message)
    9. email_capt = EmailCaptchModel(email=email,captcha=cap)
    10. db.session.add(email_capt)
    11. db.session.commit()
    12. return jsonify({'code':200,'message':'','data':None})

    查看DB数据

    注册表单验证实现:

    1. # blueprints/forms.py
    2. import wtforms
    3. from wtforms.validators import Email,Length,EqualTo
    4. from models import UserModel,EmailCaptchModel
    5. class RegisterForm(wtforms.Form):
    6. email = wtforms.StringField(validators=[Email(message="邮箱格式错误!")])
    7. captcha = wtforms.StringField(validators=[Length(min=4,max=4,message="验证码格式错误!")])
    8. username = wtforms.StringField(validators=[Length(min=3,max=20,message="用户名格式错误!")])
    9. password = wtforms.StringField(validators=[Length(min=3,max=20,message="密码长度为4-20位!")])
    10. password_confirm = wtforms.StringField(validators=[EqualTo('password',message="两次输入的错误不一致!")])
    11. def validate_email(self, field):
    12. email = field.data
    13. user = UserModel.query.filter_by(email=email).first()
    14. if user:
    15. raise wtforms.ValidationError(message='该邮箱已经被注册!')
    16. def validate_captcha(self,field):
    17. captcha = field.data
    18. email = self.email.data
    19. captcha_model = EmailCaptchModel.query.filter_by(email=email,captcha=captcha).first()
    20. if not captcha_model:
    21. print('邮箱或验证码格式错误!')
    22. # raise wtforms.ValidationError(message='邮箱或验证码格式错误!')
    23. # else:
    24. # db.session.delete(captcha_model)
    25. # db.session.commit()

     注册功能后端的实现

    1. # blueprints/auth.py
    2. @bp.route('/register',methods = ['POST','GET'])
    3. def register():
    4. if request.method == 'GET':
    5. return render_template('regist.html')
    6. form = RegisterForm(request.form)
    7. if form.validate():
    8. email = form.email.data
    9. username= form.username.data
    10. password = form.password.data
    11. user= UserModel(email=email,username=username,password=generate_password_hash(password))
    12. db.session.add(user)
    13. db.session.commit()
    14. return redirect(url_for('auth.login'))
    15. else:
    16. print(form.data)
    17. print(form.errors)
    18. return redirect(url_for('auth.register'))

    运行结果:

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

    1. # forms.py
    2. class LoginForm(wtforms.Form):
    3. email = wtforms.StringField(validators=[Email(message="邮箱格式错误!")])
    4. print(wtforms.validators.Email)
    5. password = wtforms.StringField(validators=[Length(min=4, max=20, message="密码长度为4-20位!")])
    6. # auth.py
    7. @bp.route('/login',methods = ['POST','GET'])
    8. def login():
    9. if request.method == 'GET':
    10. return render_template('login.html')
    11. form = LoginForm(request.form)
    12. print(form.data)
    13. if form.validate():
    14. email = form.email.data
    15. password = form.password.data
    16. user = UserModel.query.filter_by(email=email).first()
    17. if not user:
    18. print('邮箱在数据库中不存在')
    19. return redirect(url_for('auth.login'))
    20. if check_password_hash(user.password,password):
    21. # cookie 存在浏览器上
    22. # flsk的session 是加密存在在cookie
    23. session['user.id'] = user.id
    24. return redirect(url_for('auth.index'))
    25. else:
    26. print('密码错误')
    27. return redirect(url_for('auth.login'))
    28. else:
    29. print(form.errors)
    30. return redirect(url_for('auth.login'))

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

    1. # 配置session
    2. SECRET_KEY = 'DSAFSDFASFASDFADFSDSASFD' # 无要求,自定义

    两个钩子的运用及实现

    1. # from flask import g
    2. # 全局变量g
    3. @login_required
    4. def my_before_request():
    5. user_id = session.get('user_id')
    6. if user_id:
    7. user = UserModel.query.get(user_id)
    8. setattr(g,'user',user)
    9. else:
    10. setattr(g,'user',None)
    11. @app.context_processor
    12. def my_context_processor():
    13. return {'user':g.user}

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

    1. {% if user %}
    2. "#">{{ user.username }}
  • "{{ url_for('auth.logout') }}">注销
  • {% else %}
  • "{{url_for('auth.login')}}">登录
  • "{{url_for('auth.register')}}">注册
  • {% endif %}
    1. @bp.route('/logout')
    2. def logout():
    3. session.clear()
    4. return render_template('index.html')

    发布问答后端接口的实现

    1. # model.py
    2. class QuestionModel(db.Model):
    3. __tablename__ = 'question'
    4. id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    5. title = db.Column(db.String(1000),nullable=False)
    6. content = db.Column(db.Text,nullable=False)
    7. create_time = db.Column(db.DateTime,default=datetime.now())
    8. author_id = db.Column(db.Integer,db.ForeignKey('user.id'))
    9. author = db.relationship(UserModel,backref = 'questions')
    10. # form 验证器
    11. class QuestionForm(wtforms.Form):
    12. title = wtforms.StringField(validators=[Length(min=4, max=100, message="标题格式错误!")])
    13. context = wtforms.StringField(validators=[Length(min=3, max=200, message="内容格式错误")])
    1. from flask import Blueprint,request,render_template
    2. from .forms import QuestionForm
    3. from decorators import login_required
    4. from models import QuestionModel
    5. from exts import db
    6. bp=Blueprint('qa',__name__,url_prefix='/qa')
    7. @bp.route('/question',methods = ['POST','GET'])
    8. def question():
    9. if request.method == 'GET':
    10. return render_template('question.html')
    11. else:
    12. form =QuestionForm(request.form)
    13. print(form.data)
    14. if form.validate():
    15. title = form.title.data
    16. context = form.context.data
    17. question = QuestionModel(title=title,content=context,author=g.user)
    18. db.session.add(question)
    19. db.session.commit()
    20. return render_template('index.html')
    21. else:
    22. print(form.errors)
    23. return render_template('question.html')

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

    1. # 自定义登录装饰器
    2. from functools import wraps
    3. from flask import g,redirect,url_for
    4. def login_required(func):
    5. # 保留func的信息
    6. @wraps(func)
    7. def inner(*args,**kwargs):
    8. if g.user:
    9. return func(*args,**kwargs)
    10. else:
    11. return redirect(url_for('auth.login'))
    12. return inner
    13. # 配置装饰器
    14. @login_required
    15. def question()

    问答列表首页功能实现:

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

    发布问答详细的功能实现

    1. @bp.route('/qa/detail/')
    2. def qa_detail(qa_id):
    3. question=QuestionModel.query.get(qa_id)
    4. return render_template('detail.html',question=question)
    5. @bp.post('/answer/public')
    6. @login_required
    7. def public_answer():
    8. form = AnswerForm(request.form)
    9. if form.validate():
    10. content = form.context.data
    11. question_id = form.question_id.data
    12. answer = AnswerModel(content=content,question_id=question_id,author_id=g.user.id)
    13. db.session.add(answer)
    14. db.session.commit()
    15. return redirect(url_for('qa.qa_detail',qa_id=question_id))
    16. else:
    17. print(form.errors)
    18. return redirect(url_for('qa.qa_detail', qa_id=request.form.get('question_id')))

    搜索功能的实现

    1. @bp.route('/search')
    2. def search():
    3. q = request.args.get('q')
    4. # 搜索标题的关键字
    5. questions= QuestionModel.query.filter(QuestionModel.title.contains(q)).all()
    6. return render_template('index.html',questions=questions)

     okok

  • 相关阅读:
    数据结构与算法——算法时间复杂度
    redis HyperLogLog数据类型——亿级用户访问量统计解决方案
    自动化测试框架Pytest(三)——自定义allure测试报告
    深入分析以太坊合并后的监管和应用层问题
    机器学习笔记 YOLOv9模型相关论文简读
    单元测试到底是什么?应该怎么做?
    单链表(4)
    #FPGA(基础知识)
    .NET Core 实现后台任务(定时任务)BackgroundService(二)
    halcon 算子set_display_font
  • 原文地址:https://blog.csdn.net/qq_44238024/article/details/136277821