Python后端Flask学习项目实践---搭建一个问答网站

2023-11-10

1.项目效果展示

这里主要以后端为主,前端的代码不做展示,如果需要代码可以评论或者私信

用户注册、登录相关:

用邮箱进行注册,并通过向邮箱发送验证码来进行判断,一个邮箱只能注册一个账号

 

 首页相关:

用户登录后可以进行发布问题和回答,同时也提供搜索功能,在首页展示所有问题

 搜索:

 

 评论:

 

2.项目工程目录

blueprints:

项目蓝图包括问答的逻辑实现和用户的逻辑时间

migrations:

项目数据库迁移

static、templates:

前端相关,css、html文件等

3.项目实现:

3.1数据库

主要是需要设计一个用户表user表,一个邮箱对应验证码EmailCaptcha的表,一个问题question表,一个评论Answer表

利用flask中提供的SQLAlchemy不用我们自己手动写SQL代码,用面向对象的思维解决就好

(1)新建db对象

因为在很多文件中都需要用到db对象,所以用一个专门的文件etx.py储存,并在app.py中进行初始化:

etx.py:

from flask_mail import Mail
from flask_sqlalchemy import SQLAlchemy


db = SQLAlchemy()
mail = Mail()

app.py:

app = Flask(__name__)
# 配置项
app.config.from_object(config)

db.init_app(app)
mail.init_app(app)

migrate = Migrate(app, db)
# 组装蓝图 将book、course、user模块都组装在main.py中
app.register_blueprint(qa_bp)
app.register_blueprint(user_bp)

(2)配置数据库:

# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'flask'
USERNAME = 'root'
PASSWORD = '*****'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
SQLALCHEMY_DATABASE_URI= DB_URI
# 关闭数据库修改跟踪操作[提高性能],可以设置为True,这样可以跟踪操作:
SQLALCHEMY_TRACK_MODIFICATIONS=False

# 开启输出底层执行的sql语句
SQLALCHEMY_ECHO = True

(3)设计models:

from exts import db


class EmailCaptchaModel(db.Model):
    __tablename__="email_captcha"
    id=db.Column(db.Integer,primary_key=True,autoincrement=True)
    email=db.Column(db.String(100),nullable=True,unique=True)
    captcha=db.Column(db.String(10),nullable=False)
    create_time=db.Column(db.DateTime)


class UserModel(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(200),nullable=False,unique=True)
    email = db.Column(db.String(100),nullable=False,unique=True)
    password = db.Column(db.String(200),nullable=False)
    join_time = db.Column(db.DateTime)


class QuestionModel(db.Model):
    __tablename__ = "question"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(200), nullable=False)
    content = db.Column(db.Text,nullable=False)
    create_time = db.Column(db.DateTime)
    author_id = db.Column(db.Integer,db.ForeignKey("user.id"))
    author = db.relationship("UserModel",backref="questions")


class AnswerModel(db.Model):
    __tablename__ = "answer"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    content = db.Column(db.Text,nullable=False)
    create_time = db.Column(db.DateTime)
    question_id = db.Column(db.Integer,db.ForeignKey("question.id"))
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"))

    question = db.relationship("QuestionModel",backref=db.backref("answers",order_by=create_time.desc()))
    author = db.relationship("UserModel",backref="answers")

(4)生成数据库

利用flask中提供的数据库迁移功能可以在更新数据库后直接迁移

在命令行进行输入

step1:

flask db init

这条语句执行完后会生成上述文件中的migrate文件夹

step2:

flask db migrate

step3:

flask db upgrade

更新完成!

3.2 发送邮件功能

在注册时点击发送验证码后利用一个固定的邮箱给注册的邮箱发送验证码信息,同时存储到数据库中验证输入的验证码是否与收到的验证码一致。

主要是利用flask_mail进行邮箱发送。

(1)邮箱设置

# 邮箱配置
# 项目中用的是QQ邮箱
MAIL_SERVER = "smtp.qq.com"
MAIL_PORT = 465
MAIL_USE_TLS = False
MAIL_USE_SSL = True
MAIL_DEBUG = True
MAIL_USERNAME = "774747245@qq.com"
MAIL_PASSWORD = "*****"
MAIL_DEFAULT_SENDER = "774747245@qq.com"

(2)得到验证码

可以在浏览器中进行测试

@bp.route("/captcha", methods=['POST'])
def get_captcha():
    email = request.form.get("email")
    # 从letters集合中随机取出4个生成验证码 letters集合是英文和数字的集合
    letters = string.ascii_letters + string.digits
    captcha = "".join(random.sample(letters, 4))

    if email:
        message = Message(
            subject="邮箱测试",
            recipients=[email],
            body=f"您的注册验证码是:{captcha}"
        )
        mail.send(message)
        # 存放到数据库中:先通过email进行查询,如果存在该email就直接更新captcha就行,如果不存在就添加一个记录
        captcha_model = EmailCaptchaModel.query.filter_by(email=email).first()
        if captcha_model:
            captcha_model.captcha = captcha
            # captcha_model.create_time=datetime.time.now()
            db.session.commit()
        else:
            captcha_model = EmailCaptchaModel(email=email, captcha=captcha)
            db.session.add(captcha_model)
            db.session.commit()
        print("captcha:", captcha)
        return jsonify({"code": 200, "message": "suceess"})
    else:
        return jsonify({"code": 400, "message": "mail为空"})

3.3 用户注册和登录、登出

(1)判断注册和登录填写的表单是否符合要求

可以直接利用flask中的wtforms进行格式限制:

新建一个forms.py:

import wtforms
from wtforms.validators import length,email,EqualTo,InputRequired
from models import EmailCaptchaModel,UserModel


class LoginForm(wtforms.Form):
    email = wtforms.StringField(validators=[email()])
    password = wtforms.StringField(validators=[length(min=6,max=20)])


class RegisterForm(wtforms.Form):
    username = wtforms.StringField(validators=[length(min=3,max=20,message="长度在3和20之间")])
    email = wtforms.StringField(validators=[email()])
    captcha = wtforms.StringField(validators=[length(min=4, max=4)])
    password = wtforms.StringField(validators=[length(min=6,max=20,message="长度在6和20之间")])
    password_confirm = wtforms.StringField(validators=[EqualTo("password")])

    def validate_captcha(self,field):
        captcha = field.data
        email = self.email.data
        captcha_model = EmailCaptchaModel.query.filter_by(email=email).first()
        print(captcha_model.captcha)
        if not captcha_model or captcha_model.captcha.lower() != captcha.lower():
            print("验证码错误")
            raise wtforms.ValidationError("邮箱验证码错误!")

    def validate_email(self,field):
        email = field.data
        user_model = UserModel.query.filter_by(email=email).first()
        if user_model:
            print("邮箱已存在")
            raise wtforms.ValidationError("邮箱已经存在!")


class QuestionForm(wtforms.Form):
    title = wtforms.StringField(validators=[length(min=3, max=200)])
    content = wtforms.StringField(validators=[length(min=5)])


class AnswerForm(wtforms.Form):
    content = wtforms.StringField(validators=[length(min=1)])

(2)注册

注册主要是判断格式是否正确,并判断验证码是否正确,如果正确后,新生成一个user对象插入到user表中。同时在存储时进行密码加密存储

@bp.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'GET':
        return render_template("register.html")
    else:
        form = RegisterForm(request.form)
        if form.validate():
            print("验证成功")
            username = form.username.data
            email = form.email.data
            password = form.password.data
            # 密码加密
            hash_password = generate_password_hash(password=password)
            captcha = form.captcha.data
            create_time = datetime.datetime.now()
            # 1.通过email查询user表 如果存在就通知已存在该用户 不存在就新建
            user_model = UserModel.query.filter_by(email=email).first()
            if user_model:
                print("该邮箱已被注册,请重新输入")
                return redirect(url_for("user.register"))
            user = UserModel(username=username, email=email, password=hash_password, join_time=create_time)
            db.session.add(user)
            db.session.commit()
            return redirect(url_for("user.login"))
        else:
            print("注册验证失败")
            return redirect(url_for("user.register"))

(3)登录

先查询是否存在这个用户,如果存在进行密码验证

@bp.route('/login', methods=['GET', 'POST'])
def login():
    """登录:guest1:123456
    0.通过验证
    1.通过邮箱查找出user_model
    2.如果存在就比较密码是否正确 正确:登录成功 不正确:密码错误
    3.不存在直接提示用户不存在并返回到注册页面"""
    if request.method == 'GET':
        return render_template("login.html")
    else:
        form = LoginForm(request.form)
        if form.validate():
            email = form.email.data
            password_input = form.password.data
            user_model = UserModel.query.filter_by(email=email).first()
            if user_model:
                if check_password_hash(user_model.password, password=password_input):
                    print("登录成功")
                    session['user_id'] = user_model.id
                    return redirect("/")
                else:
                    print("密码输入错误")
                    flash("密码输入错误")
                    return redirect(url_for("user.login"))
            else:
                print("该用户不存在,请注册")
                flash("该用户不存在,请注册")
                return redirect(url_for("user.register"))
        else:
            print("请输入正确格式的账号或密码")
            flash("请输入正确格式的账号或密码")
            return redirect(url_for("user.login"))

(4)登出

删除session即可

@bp.route('/logout')
def logout():
    session.clear()  # 清除session就可
    return redirect(url_for("user.login"))

3.4 访问页面权限管理

用户在未登录时不能进行发布问答的功能,这里可以利用一个装饰器进行实现

"""装饰器"""
from flask import g, redirect, url_for
from functools import wraps

"""如果没有登录就不能访问,跳转到登录页面 如果登录了就正常逻辑处理"""


def login_required(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if hasattr(g, "user"):
            return func(*args, **kwargs)
        else:
            print("未登录不能进行访问")
            return redirect(url_for("user.login"))

    return wrapper

在需要进行访问限制的方法上面加上

@bp.route('/public_question', methods=['GET', 'POST'])
@login_required
def public_question():

就可以实现访问权限的设置啦!!!

3.5 问答查看、搜索

问答功能:实际上就是生成一个QuestionModel,将符合要求的Question存储到数据库中

(1)QuestionModel:

class QuestionModel(db.Model):
    __tablename__ = "question"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    title = db.Column(db.String(200), nullable=False)
    content = db.Column(db.Text,nullable=False)
    create_time = db.Column(db.DateTime)
    author_id = db.Column(db.Integer,db.ForeignKey("user.id"))
    author = db.relationship("UserModel",backref="questions")

(2)表单验证:

class QuestionForm(wtforms.Form):
    title = wtforms.StringField(validators=[length(min=3, max=200)])
    content = wtforms.StringField(validators=[length(min=5)])

(3)问答功能

@bp.route('/public_question', methods=['GET', 'POST'])
@login_required
def public_question():
    """发布问答"""
    if request.method == 'GET':
        return render_template("public_question.html")
    else:
        form = QuestionForm(request.form)
        if form.validate():
            title = form.title.data
            content = form.content.data
            create_time = datetime.datetime.now()
            question = QuestionModel(title=title, content=content, author=g.user, create_time=create_time)
            db.session.add(question)
            db.session.commit()
            print("发布问答成功")
            return redirect(url_for("qa.index"))
        else:
            flash("格式不正确")
            return redirect(url_for("qa.public_question"))

(4)问题细节查看

@bp.route("/question/<int:question_id>")
def question_detail(question_id):
    question = QuestionModel.query.get(question_id)
    return render_template("detail.html", question=question)

(5)问题搜索

在标题和内容中都可以进行查询搜索,只有符合其一就输出

@bp.route('/search')
def search():
    q = request.args.get("q")
    questions = QuestionModel.query.filter(
        or_(QuestionModel.title.contains(q), QuestionModel.content.contains(q))).order_by(db.text("create_time"))
    print("搜索结果", questions == None)
    if questions:
        return render_template("index.html", questions=questions)
    else:
        print("搜索结果为空")
        return "搜索结果为空"

3.6 评论功能

在发布问题后可以进行评论,与问题一致的流程

(1)生成AnswerModel:

class AnswerModel(db.Model):
    __tablename__ = "answer"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    content = db.Column(db.Text,nullable=False)
    create_time = db.Column(db.DateTime)
    question_id = db.Column(db.Integer,db.ForeignKey("question.id"))
    author_id = db.Column(db.Integer, db.ForeignKey("user.id"))

    question = db.relationship("QuestionModel",backref=db.backref("answers",order_by=create_time.desc()))
    author = db.relationship("UserModel",backref="answers")

(2)生成表单验证:

class AnswerForm(wtforms.Form):
    content = wtforms.StringField(validators=[length(min=1)])

(3)进行评论

@bp.route("/answer/<int:question_id>", methods=['POST'])
@login_required
def answer(question_id):
    form = AnswerForm(request.form)
    if form.validate():
        content = form.content.data
        create_time = datetime.datetime.now()
        answer_model = AnswerModel(content=content, author=g.user, question_id=question_id, create_time=create_time)
        db.session.add(answer_model)
        db.session.commit()
        return redirect(url_for("qa.question_detail", question_id=question_id))
    else:
        flash("表单验证失败!")
        return redirect(url_for("qa.question_detail", question_id=question_id))

4.总结

就是简单的一个小项目练练手,新手的可以看这个直接入门,但是项目也需要进行完善啦,比如注册也可以设置头像之类的,这样在首页就可以显示自己的头像之类的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python后端Flask学习项目实践---搭建一个问答网站 的相关文章

  • 如何将字典转换为字符串

    我正在尝试使用提供的解决方案here https stackoverflow com questions 5192753 how to get the number of occurrences of each character usin
  • 如何分组显示argparse子命令?

    对于具有许多子命令的程序 我想在 help 输出中显示它们按逻辑分组 Python argparse 有一个add argument group http docs python org library argparse html argp
  • 有没有办法拥有租户特定的 JWT 令牌

    我目前正在开发一个 SPA 应用程序 角度 后端使用 Python Flask API 该应用程序将支持多个租户 我对安全概念有点挣扎 我目前正在使用 jwt extend 颁发的 JWT 令牌对所有租户都有效 我当然可以从令牌中获取用户
  • 代码运行时出现内存问题(Python、Networkx)

    我编写了一个代码来生成具有 379613734 条边的图 但由于内存问题 代码无法完成 当经过 6200 万行时 大约会占用服务器内存的 97 所以我杀了它 您有解决这个问题的想法吗 我的代码是这样的 import os sys impor
  • 在 Flask 中将配置文件作为字典读取

    在 instance app cfg 我已经配置 test test 在我的烧瓶文件 app py 中 with app open instance resource app cfg as f config f read print con
  • python下安装xgboost 32位msys失败

    尝试安装 xgboost 失败 Windows 和企业版版本为 Anaconda 2 1 0 64 位 我该如何继续 我一直在使用 R 似乎从 RStudio 在 R 中安装新包相当容易 但在间谍程序中则不然 因为我需要进入命令窗口来执行此
  • 带剖面的 3D 曲面图

    基本上 我有一个由一组时间序列组成的曲面图 我想在特定高度添加剖面图 以更好地了解一年中值高于所选阈值的时期 由此 其中显示平面但不是剖面 To This 有什么建议吗 使用 alpha 和相机仰角并没有解决问题 平面似乎仍然在人物的前面
  • 使用字符串迭代 url - python

    我现在完全被我的代码困住了 首先 我尝试从 volkskrant 的存档页面检索所有网址 这是我被打击的第一步 某一特定日期的 url 如下所示 http www volkskrant nl archief detail 01012016
  • While 在范围内循环用户输入

    我有一些代码 我想要求用户输入 1 100 之间的数字 如果他们在这些数字之间输入一个数字 它将打印 Size input 并打破循环 但是 如果他们在外部输入一个数字1 100 它将打印 大小 输入 并继续向他们重新询问一个数字 但我遇到
  • Python 请求包含有值的参数和没有值的参数

    我正在为 API 编写一个 Python 包装器 该 API 支持具有值的查询参数 例如param1如下 和查询参数do not有价值观 例如param2如下 即 https example com service param1 value
  • Python 结构的 PHP 替代品

    我很高兴在我的 Python 项目中使用 Fabric 进行部署 现在我正在从事一个更大的 PHP 项目 想知道是否有类似 PHP 的 Fabric 之类的东西 唔 为什么这有关系 Fabric 只是 python 脚本 所以它与项目语言无
  • django 密码重置功能中出现 NoReverseMatch 错误

    我正在尝试在 django 中实现密码重置功能 下面是我的代码 urls py urlpatterns patterns url r signup accounts views signup name signup email url r
  • 调度算法,找到设定长度的所有非重叠区间

    我需要为我的管理应用程序实现一种算法 该算法将告诉我何时可以将任务分配给哪个用户 我实现了一个蛮力解决方案 它似乎有效 但我想知道是否有更有效的方法来做到这一点 为了简单起见 我重写了算法以对数字列表进行操作 而不是数据库查询等 下面我将尝
  • Keras CNN 回归模型损失低,准确度为 0

    我在 keras 中遇到这个 NN 回归模型的问题 我正在研究一个汽车数据集 以根据 13 个维度预测价格 简而言之 我已将其读取为 pandas 数据帧 将数值转换为浮点数 缩放值 然后对分类值使用 one hot 编码 这创建了很多新列
  • 有没有比 ` except: pass` 更简洁的替代方案?

    我有一个函数 可以按偏好顺序返回多个组的随机成员 事情是这样的 def get random foo or bar I d rather have a foo than a bar if there are foos return get
  • 如何导入 boto3 ssm ParameterNotFound 异常?

    我想import the exception当一个boto3 ssm找不到参数get parameter 我正在尝试添加一些额外的内容ssm的功能moto图书馆 但我现在很困惑 gt gt gt import boto3 gt gt gt
  • 如何在 Windows 10 上将 ipynb 文件与 Jupyter Lab(来自 Anaconda)关联

    我使用 Windows 10 Jupiter Lab 是从 Anaconda 安装的 我想交往ipynb使用 Jupyter Lab 保存文件 这样 当我双击ipynb文件应使用 Jupyter Lab 打开 我该怎么做 Install n
  • 当没有 main 函数时,为什么 sys.settrace 不触发?

    import sys def printer frame event arg print frame event arg return printer sys settrace printer x 1 sys settrace None 上
  • Flask-migrate:更改模型属性并重命名相应的数据库列

    我对 Flask 有一些经验 但对数据库 Flask migrate alembic SqlAlchemy 不太了解 我正在跟进this https blog miguelgrinberg com post the flask mega t
  • Python 3d 金字塔

    我是 3D 绘图新手 我只想用 5 个点建造一个金字塔并通过它切出一个平面 我的问题是我不知道如何填充两侧 points np array 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 fig plt figure ax fi

随机推荐

  • Ubuntu 内存泄漏检测工具Valgrind的安装

    第一种方式 下载源码 编译安装 比较复杂 wget http valgrind org downloads valgrind 3 4 1 tar bz2 tar xvf valgrind 3 4 1 tar bz2 cd valgrind
  • Openwrt开发之网络配置

    MT7688平台运行Openwrt18 06版本 mt7688的rt305x esw交换芯片有6个交换接口 其中一个和CPU内核连接 其余可通过RJ45接口引出 手里的开发板只引出其中3个口 这3个口一个作为wan口 其余两个作为lan口
  • pink老师【品优购商城】

    最初 好久之前学过H5 CSS JS 跟着黑马的pink老师写了品优购商城的静态界面 复习一下的同时也学到了许多东西 收获 链接 https pan baidu com s 1P5FautCJCwK vTMFycvV1w pwd wsox
  • 【点云重采样Resampling】Python-pcl 基于多项式平滑点云及法线估计的曲面重建

    1 点云重采样 基于多项式平滑点云及法线估计的曲面重建以实现重采样 可以使得点云数据更规整一些 没之前那么杂乱 set Compute Normals True 可以通过在最小二乘法中进行法线估计 提高重采样准确度 set polynomi
  • char&short的整形提升

    目录 前言 整形提升的意义 整形提升的步骤 负数的整形提升 正数的整形提升 无符号整形提升 整形提升的例子 前言 前面我们介绍了有关C语言中操作符的有关知识 当然操作符的作用就是要求相关表达式的值 当不同的数据类型相加减的时候 我们要进行一
  • 嵌入式数据库sqlite3交叉编译和移植测试总结

    一 背景 根据项目需求 需要使用数据库存放一些数据 比如用户信息 配置参数 以及后期所采集RTU设备的数据等 这里选择了适合嵌入式产品的数据库 sqlite3 二 移植平台和环境 主机端 Ubuntu ARM板 ZLG EasyARM i
  • 事务并发问题及事务隔离级别的学习

    以下内容都是看的咕泡学院的大神老师讲的一个公开课 就是记录一下 事务并发带来的三大问题 1 脏读 如下图 左右两个事务A B 事务A首先查询id 1的数据 得到age 16之后 事务B对id 1的数据 将age 16更新为age 18 然后
  • STM32驱动步进电机(原理、程序、解决电机只震动不转动问题)

    一 步进电机的介绍 首先来看一下步进电机的样子 本介绍采用平时最常见也是最简单的28BYJ 48 这是一个五线四项电机 五线 顾名思义 外部五条线 四项 电机内部的定子上有8个齿 正对着的2个齿上的绕组又是串联在一起的 也就是说正对着的2个
  • STM32CUBE 定时器使用

    目录 STM32F407VET6 定时中断 记录各个STM32型号的定时器使用方法 包括定时中断 输入捕获等功能 持续更新 STM32F407VET6 定时中断 时钟配置 这里主频配置为100Mhz 最高168Mhz 即HCLK 100MH
  • [用python辅助学生中考与高考-1]:家长篇-科技特长生概述与优势

    目录 前言 这是科技的最好时代 1 什么是科技特长生 2 科技特长生的优势 科技特长生录取方式 3 科技特长生的类型 4 科技特长生七大招生类目 5 如何成为科技特长生 6 常见的赛事 前言 这是科技的最好时代 随着国家强基计划的出台和国际
  • java编程之java jwt token什么是JWT?(一)

    转自 http www leftso com blog 220 html 一 什么是JWT 了解JWT 认知JWT 首先jwt其实是三个英语单词JSON Web Token的缩写 通过全名你可能就有一个基本的认知了 token一般都是用来认
  • 房屋租赁系统

    java房屋租赁系统
  • RFC文档:官网、中文RFC文档 及 HTTP/2相关文档

    记录一下RFC的官方文档 2023 06 12修正中文RFC文档无法访问问题 一 RFC官方网站 http www rfc editor org Index of rfc RFC文档列表 Index of rfc 二 中文RFC文档 中文R
  • OS面试题(转载)

    转载自 http placement freshersworld com power preparation technical interview preparation os interview questions 23351 1 Wh
  • Tracy 小笔记 Vue - Vue 对象

    Vue 对象 const vue new Vue options el 类型 String HtmlElement 作用 挂载对象 决定之后Vue 对象会管理哪个 Dom template 当同时有 el 和 tempalte 的时候这里写
  • java泛型

    一 泛型概念的提出 为什么需要泛型 首先 我们看下下面这段简短的代码 1 public class GenericTest 2 3 public static void main String args 4 List list new Ar
  • 计算机文档加密如何解锁,bitlocker怎么解锁_bitlocker解锁方法

    许多用户为了保护电脑文件安全不被偷看 都会喜欢使用bitlocker加密功能来进行加密 Bitlocker是一种独特的为磁盘添加密码的工具 但是很多用户使用bitlocke加密完之后 不知道要怎么解锁 为此小编这就给大家带来bitlocke
  • Vue 使用 mqttws31.js 实现消息实时推送功能(WebSocket)

    1 在 vue 文件中引入 mqttws31 js 文件 mqttws31 js 文件代码在本页底部 import utils mqttws31 2 在 vue 文件中添加代码 export default data return clie
  • MapReduce官方案例wordcount

    wordcountReduce java package MaperReduce import java io IOException import org apache hadoop io LongWritable import org
  • Python后端Flask学习项目实践---搭建一个问答网站

    1 项目效果展示 这里主要以后端为主 前端的代码不做展示 如果需要代码可以评论或者私信 用户注册 登录相关 用邮箱进行注册 并通过向邮箱发送验证码来进行判断 一个邮箱只能注册一个账号 首页相关 用户登录后可以进行发布问题和回答 同时也提供搜