【Python】基于flaskMVT架构与session实现博客前台登录登出功能

news2025/7/10 6:13:03

目录

一、MVT说明

1.Model层

2.View层

3.Template层

二、功能说明

三、代码框架展示

四、具体代码实现

models.py

登录界面前端代码

博客界面前端代码(profile.html)

main.py


一、MVT说明

MVT架构是Model-View-Template的缩写,是Django框架的架构。Flask框架本身并没有强制使用MVT架构,但是我们可以通过一些方式来实现类似MVT架构的结构。

以下是一个简单的在Flask中实现MVT的示例:

1.Model层

在Flask中,我们可以使用SQLAlchemy作为ORM框架,用于操作数据库。我们可以在app目录下创建一个models.py文件,并定义我们需要的数据模型类。例如:

from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    password = db.Column(db.String(128), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

2.View层

在Flask中,我们可以使用Blueprints来组织我们的视图函数。我们可以在app目录下创建一个views.py文件,并创建一个蓝图对象,用于定义我们的视图函数。例如:

from flask import Blueprint

bp = Blueprint('main', __name__)

@bp.route('/')
def index():
    return 'Hello, World!'

3.Template层

在Flask中,我们可以使用Jinja2作为模板引擎,用于渲染HTML页面。我们可以在app目录下创建一个templates目录,并在其中创建我们的HTML模板文件。例如:

<!doctype html>
<html>
  <head>
    <title>{{ title }}</title>
  </head>
  <body>
    <h1>Hello, {{ username }}!</h1>
  </body>
</html>

然后,在我们的视图函数中使用render_template函数来渲染模板文件。例如:

from flask import render_template

@bp.route('/hello/<username>')
def hello(username):
    return render_template('hello.html', title='Flask MVT Demo', username=username)

以上就是一个简单的在Flask中实现MVT的示例。通过这种方式,我们可以将应用逻辑、数据库操作和HTML页面渲染分别放在不同的层次中,使代码更加清晰和易于维护。

二、功能说明

展示了登录界面和博客界面

实现基于初始界面多路由跳转

通过jinja2模板引擎完成html页面的数据替换

使用SQLAlchemy完成数据操作

使用request获取用户提交的参数

使用session实现权限验证,登录登出

三、代码框架展示

四、具体代码实现

models.py

from sqlalchemy import create_engine
from sqlalchemy import Column,String,Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

#链接是需要指定要用到的MySQL数据库
engine=create_engine('mysql+pymysql://root:root@localhost:3306/flask_1?charset=utf8')
Base=declarative_base() #生成SQLORM基类

class User(Base):
    #对应MySQL中数据表的名字
    __tablename__='user'
    #创建字段
    id=Column(Integer,primary_key=True)
    user_id=Column(String(50),nullable=False)
    username=Column(String(50),nullable=False)
    head_img=Column(String(200))
    short_description=Column(String(300))

登录界面前端代码

简单的Login Form登录页html模板

博客界面前端代码(profile.html)

<!DOCTYPE html>
<!--[if IE 8]> <html lang="en" class="ie8"> <![endif]-->
<!--[if IE 9]> <html lang="en" class="ie9"> <![endif]-->
<!--[if !IE]><!--> <html lang="en"> <!--<![endif]-->
<head>
<title>Home</title>
<!-- Meta -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<link rel="shortcut icon" href="">
<link href='https://fonts.googleapis.com/css?family=Roboto:400,500,400italic,300italic,300,500italic,700,700italic,900,900italic' rel='stylesheet' type='text/css'>
<!-- Global CSS -->
<link rel="stylesheet" href="assets/plugins/bootstrap/css/bootstrap.min.css">
<!-- Plugins CSS -->
<link rel="stylesheet" href="assets/plugins/font-awesome/css/font-awesome.css">

<!-- Theme CSS -->
<link id="theme-style" rel="stylesheet" href="assets/css/styles.css">

</head>

<body>

<header class="header">

    <div class="intro">
         <div class="container text-right">
             <a href={{url_for('logout')}}>退出登录</a>
        </div><!--//container-->
        <div class="container text-center">
            <h1 class="name">{{user.username}}</h1>
            <div class="title">Full Stack Developer</div>
            <div class="profile">
                <p>{{user.short_description}}</p>
            </div><!--//profile-->
        </div><!--//container-->
    </div><!--//intro-->

    <div class="contact-info">
        <div class="container text-center">
            <ul class="list-inline">
                <li class="email"><i class="fa fa-envelope"></i><a href="mailto:someone@example.com">james.doe@website.com</a></li>
                <li><i class="fa fa-phone"></i> <a href="tel: 0123456789">0123 456 7890</a></li>
                <li class="website"><i class="fa fa-globe"></i><a href="#" target="_blank">portfoliosite.com</a></li>
            </ul>
        </div><!--//container-->
    </div><!--//contact-info-->


</header><!--//header-->

<div class="wrapper container">
    <section id="contact-section" class="contact-section section">
        <h2 class="section-title">Get in Touch</h2>
        <div class="intro">
            <img class="profile-image" src="assets/images/profile-image.png" alt="">
            <div class="dialog">
                <p>I'm currently taking on freelance work. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus.</p>
                <p><strong>I can help with the following:</strong></p>
                <ul class="list-unstyled service-list">
                    <li><i class="fa fa-check" aria-hidden="true"></i> App development with ReactJS</li>
                    <li><i class="fa fa-check" aria-hidden="true"></i> Front-end development with AngularJS</li>
                    <li><i class="fa fa-check" aria-hidden="true"></i> Back-end development with Django/Python</li>
                    <li><i class="fa fa-check" aria-hidden="true"></i> UI development</li>
                    <li><i class="fa fa-check" aria-hidden="true"></i> UX prototyping</li>
                </ul>
                <p>Drop me a line at <a href="mailto:someone@example.com">james.doe@website.com</a> or call me at <a href="tel:01234567890">0123 456 7890</a></p>
                <ul class="social list-inline">
                    <li><a href="#"><i class="fa fa-linkedin" aria-hidden="true"></i></a></li>
                    <li><a href="#"><i class="fa fa-twitter" aria-hidden="true"></i></a></li>
                    <li><a href="#"><i class="fa fa-google-plus" aria-hidden="true"></i></a></li>
                    <li><a href="#"><i class="fa fa-github-alt" aria-hidden="true"></i></a></li>
                    <li><a href="#"><i class="fa fa-skype" aria-hidden="true"></i></a></li>
                </ul><!--//social-->
            </div><!--//diaplog-->
        </div><!--//intro-->

    </section><!--//section-->

</div><!--//wrapper-->

</body>
</html>

main.py

#1.导入flask
from flask import Flask, redirect, url_for, request, make_response,session
from flask import render_template

from models.models import *


#2.用flask创建应用对象
app=Flask(__name__)
app.config['SECRET_KEY']='Z3r4y'


#3. 用应用对象.route("/index.html")对函数进行装饰,这个函数中写业务逻辑
@app.route("/")
@app.route("/index")
def index():
    return redirect('profile')

@app.route("/profile")    #当调用profile的时候,就相当于profile(user_id=xxx)
#当调用这个函数的时候,意味着用户要访问简历页面,至于是否可以访问,则要检查用户请求中的cookie,如果有,那么就认为可以访问,否则禁止访问
def profile():  #如果想调用profile成功,那么只有user_id这个位置的是纯数字的时候,才可以调用
    # 如果一个函数它是一个普通的功能的话,它一般包括2个功能:
    #1.业务方面的数据处理(对变量user_id的使用,例如查询数据库等)
    #2.模板的替换(对应profile.html的获取以及字符的替换)
    # with open('profile.html',encoding='utf-8') as f:
    #     content=f.read().replace("xxxxxxxx",str(user_id))
    #     return content

    # conn=pymysql.connect(host='localhost', user='root', password='root', database='flask_1', charset='utf8')
    # csl=conn.cursor()
    # params=[user_id]
    # csl.execute('select * from user where user_id=%s',params)
    # result=csl.fetchone()
    # print(result)
    # csl.close()
    # conn.close()
    # login_flag=request.cookies.get('login_flag')
    # user_id=request.cookies.get('user_id')  #从cookie中提取用户的id
    login_flag=session.get('login_flag')
    user_id=session.get('user_id')
    if not (login_flag and login_flag=="success" and user_id):
        return redirect(url_for('login'))

    db_session=sessionmaker(bind=engine)() #生成链接数据库的实例
    user_ret=db_session.query(User).filter(User.user_id==user_id).one()    #将从cookie中查询出来的user_id道数据库中查询这个用户
    # print(user_ret)
    db_session.close()
    # 使用模板(jinja2模板引擎),可以对html的数据处理进行了封装
    # return render_template("profile.html",user_name="Z3r4y")
    # return render_template("profile.html",user_name=result[2],short_desc=result[4])  #注意:它会默认到templates文件夹中去找 profile.html
    return render_template("profile.html",user=user_ret)

@app.route('/login')
def login():
    #判断用户名以及密码或者还有验证码是否成立,如果成立则告知浏览器用户登录成功,且让浏览器自动跳转主页
    # print(request.args)
    if request.args:
        user_name=request.args.get('Username')
        password=request.args.get('Password')
        #1.业务处理
        print("用户名是",user_name)
        print("密码是",password)
        db_session = sessionmaker(bind=engine)()  # 生成链接数据库的实例
        user_ret = db_session.query(User).filter(User.username == user_name).first()
        db_session.close()
        print(user_ret)
        if user_ret:
            # response=make_response("<h1>登陆成功</h1>")
            response=make_response(redirect(url_for('index')))
            # response.set_cookie("user_id",user_ret.user_id)
            # response.set_cookie("login_flag","success")
            session['login_flag']="success"
            session['user_id']=user_ret.user_id
            return response
        else:
            return "<h1>登陆失败</h1>"
        # return redirect('/index')
        # return redirect(url_for("profile",user_id=2))   #帮助我们动态地生成与路由函数关联的URL
    else:
        return render_template('login.html')

@app.route('/logout')
def logout():
    # #1.清理cookie
    # response=make_response(redirect(url_for('index')))
    # response.delete_cookie('login_flag')
    # response.delete_cookie('user_id')
    #1.清理session
    session.clear()
    # 2.跳转到主页
    return redirect(url_for('index'))

@app.route('/demo')
def demo():
    return "状态码",404


#4.应用程序.run()
app.run(debug=True,port=1337,host="0.0.0.0")     #开启调试模式,意味着如果有代码的改动,flask会自动重启服务器
# app.run()
# print(app.url_map)

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

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

相关文章

基于 Editor.js 开发富文本编辑器库

开始 Editor.js 提供了简单而直观的用户界面&#xff0c;根据需求可以灵活添加自定义的编辑工具&#xff0c;通过插件扩展功能 Editorjs 使用 js 开发&#xff0c;脱离框架依赖&#xff0c;因此可以基于它封装富文本编辑器&#xff0c;用于 Vue 和 React 项目 editor-js-com…

电化学仿真的基础知识笔记

1 概述 电化学反应是一种特殊的化学反应&#xff0c;其能量转移形式为化学能和电能之间互相转换。根据能量转换方向&#xff0c;可分为两类&#xff1a; 原电池&#xff08;Galvanic cells&#xff09;&#xff1a;将化学能转化为电能&#xff0c;对外放电电解槽&#xff08;…

2024 年 22 款顶级免费数据恢复软件比较 [Windows 和 Mac]

适用于 Windows 和 Mac 用户的最佳数据恢复软件下载列表和比较&#xff0c;可快速恢复丢失的数据、已删除的文件、照片或格式化的分区数据&#xff1a; 数据恢复软件是一种从任何存储介质恢复丢失文件的应用程序。它可以恢复由于病毒攻击、硬盘故障或任何其他原因而意外删除或…

Hadoop入门学习笔记——四、MapReduce的框架配置和YARN的部署

视频课程地址&#xff1a;https://www.bilibili.com/video/BV1WY4y197g7 课程资料链接&#xff1a;https://pan.baidu.com/s/15KpnWeKpvExpKmOC8xjmtQ?pwd5ay8 Hadoop入门学习笔记&#xff08;汇总&#xff09; 目录 四、MapReduce的框架配置和YARN的部署4.1. 配置MapReduce…

nn.LSTM个人记录

简介 nn.LSTM参数 torch.nn.lstm(input_size, "输入的嵌入向量维度&#xff0c;例如每个单词用50维向量表示&#xff0c;input_size就是50"hidden_size, "隐藏层节点数量,也是输出的嵌入向量维度"num_layers, "lstm 隐层的层数&#xff0c;默认…

02_算法分析

02_算法分析 0.1 算法的时间复杂度分析0.1.1 函数渐近增长概念&#xff1a;输入规模n>2时&#xff0c;算法A1的渐近增长小于算法B1 的渐近增长随着输入规模的增大&#xff0c;算法的常数操作可以忽略不计测试二&#xff1a;随着输入规模的增大&#xff0c;与最高次项相乘的常…

【计数DP】牛客小白月赛19

登录—专业IT笔试面试备考平台_牛客网 题意 思路 首先做法一定是计数 dp 然后状态设计&#xff0c;先设 dp[i] 然后看影响决策的因素&#xff1a;两边的火焰情况&#xff0c;那就 dp[i][0/1][0/1]表示 前 i 个&#xff0c;该位有无火焰&#xff0c;该位右边有无火焰的方案数…

单片机的RTC获取网络时间

理解网络同步校准RTC的原理需要考虑NTP、SNTP、RTC这三个关键组件的作用和交互。下面详细解释这个过程&#xff1a; 1. NTP&#xff08;Network Time Protocol&#xff09;&#xff1a; 协议目的&#xff1a;NTP是用于同步计算机和设备时钟的协议。它通过在网络上与时间服务器通…

为什么react call api in cDidMount

为什么react call api in cDM 首先&#xff0c;放到constructor或者cWillMount不是语法错误 参考1 参考2 根据上2个参考&#xff0c;总结为&#xff1a; 1、官网就是这么建议的&#xff1a; 2、17版本后的react 由于fiber的出现导致 cWM 会调用多次&#xff01; cWM 方法已…

【并发设计模式】聊聊两阶段终止模式如何优雅终止线程

在软件设计中&#xff0c;抽象出了23种设计模式&#xff0c;用以解决对象的创建、组合、使用三种场景。在并发编程中&#xff0c;针对线程的操作&#xff0c;也抽象出对应的并发设计模式。 两阶段终止模式- 优雅停止线程避免共享的设计模式- 只读、Copy-on-write、Thread-Spec…

LangChain 30 ChatGPT LLM将字符串作为输入并返回字符串Chat Model将消息列表作为输入并返回消息

LangChain系列文章 LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储&#xff0c;读取YouTube的视频文本搜索I…

【线性代数】决定张成空间的最少向量线性无关吗?

答1&#xff1a; 是的&#xff0c;张成空间的最少向量是线性无关的。 在数学中&#xff0c;张成空间&#xff08;span space&#xff09;是一个向量空间&#xff0c;它由一组向量通过线性组合&#xff08;即每个向量乘以一个标量&#xff09;生成。如果这组向量是线性无关的&…

CV算法面试题学习

本文记录了CV算法题的学习。 CV算法面试题学习 点在多边形内&#xff08;point in polygon&#xff09;高斯滤波器 点在多边形内&#xff08;point in polygon&#xff09; 参考自文章1&#xff0c;其提供的代码没有考虑一些特殊情况&#xff0c;所以做了改进。 做法&#xff…

网络爬虫之多任务数据采集(多线程、多进程、协程)

进程&#xff1a;是操作系统中资源分配的基本单位 线程&#xff1a;使用进程分配的资源处理具体任务 一个进程中可以有多个线程&#xff1a;进程相当于一个公司&#xff0c;线程就是公司里面的员工。 一 多线程 多线程都是关于功能的并发执行。而异步编程是关于函数之间的非…

持续集成交付CICD:Jira 远程触发 Jenkins 实现更新 GitLab 分支

目录 一、实验 1.环境 2.GitLab 查看项目 3.Jira新建模块 4. Jira 通过Webhook 触发Jenkins流水线 3.Jira 远程触发 Jenkins 实现更新 GitLab 分支 二、问题 1.Jira 配置网络钩子失败 2. Jira 远程触发Jenkins 报错 一、实验 1.环境 &#xff08;1&#xff09;主机 …

uniapp自定义头部导航怎么实现?

一、在pages.json文件里边写上自定义属性 "navigationStyle": "custom" 二、在对应的index页面写上以下&#xff1a; <view :style"{ height: headheight px, backgroundColor: #24B7FF, zIndex: 99, position: fixed, top: 0px, width: 100% …

STM32——CAN协议

文章目录 一.CAN协议的基本特点1.1 特点1.2 电平标准1.3 基本的五个帧1.4 数据帧 二.数据帧解析2.1 帧起始和仲裁段2.2 控制段2.3 数据段和CRC段2.4 ACK段和帧结束 三.总线仲裁四.位时序五.STM32CAN控制器原理与配置5.1 STM32CAN控制器介绍5.2 CAN的模式5.3 CAN框图 六 手册寄存…

Hago 的 Spark on ACK 实践

作者&#xff1a;华相 Hago 于 2018 年 4 月上线&#xff0c;是欢聚集团旗下的一款多人互动社交明星产品。Hago 融合优质的匹配能力和多样化的垂类场景&#xff0c;提供互动游戏、多人语音、视频直播、 3D 虚拟形象互动等多种社交玩法&#xff0c;致力于为用户打造高效、多样、…

P4 音频知识点——PCM音频原始数据

目录 前言 01 PCM音频原始数据 1.1 频率 1.2 振幅&#xff1a; 1.3 比特率 1.4 采样 1.5 量化 1.6 编码 02. PCM数据有以下重要的参数&#xff1a; 采样率&#xff1a; 采集深度 通道数 ​​​​​​​ PCM比特率 ​​​​​​​ PCM文件大小计算&#xff1a; ​…

计算机毕业设计 基于SpringBoot的房屋租赁管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…