草庐IT

两天时间,用Python重写了我的Markdown-Online系统,主要使用了Flask技术栈的基础知识,这不比游戏有意思?

@魏大大 2023-05-05 原文

Markdown-Online

文末附源码

之前写的《在线Markdown编辑系统》本来只是自己瞎搞的,没想到用起来真香~~

而且,还有很多童鞋对之前的叙利亚战损版系统非常感兴趣,正好趁着五一放假,我花了两天时间重构了之前的系统,引入了前端框架,使界面看起啦更统一,同时也增加了一些其他的功能。

不过,关于Flask搭建的文章,我写太多了,感觉有点皮了,本文就不再做过多解读,有兴趣的可以看我之前的文章《我用Python写网站》,有点粗糙,还能看吧。

如果,有人想了解更多可留言催更,最近在研究JS,精力分散了。

下面是截图加简介时间:

系统预览

预览地址:Markdown-Online

有兴趣的同学可以访问以上链接,注册个账号瞅一瞅,不要用手机打开,没有针对移动端做设计~~

以下是系统的主页,啥也没有~~


界面介绍

  1. 登录界面
    Flask开发的标准步骤:wtf表单创建、html代码编写,最后是视图函数,当然不同的人顺序可能稍有区别.
    使用Flask-wtf的最大好处就是表单的验证,其次就是配合Bootstrap能够快速生成的简单的界面。
    首先是LoginForm的代码:

    # forms.py
    class LoginForm(FlaskForm):
        email = EmailField('Email', validators=[DataRequired(), Email()])
        password = PasswordField('Password', validators=[DataRequired()])
        submit = SubmitField('Sign In')
    

    然后是对应的html

    <!-- login.html -->
    {% extends 'base.html' %}
    {% from 'bootstrap5/form.html' import render_field %}
    
    {% block content %}
    <div style="height: 600px; padding-top: 100px;">
        <div style="width: 36rem;" class="mx-auto shadow-sm px-3 py-5 bg-body rounded">
            <h2>Sign In</h2>
            <hr>
            {% for msg in get_flashed_messages() %}
            <p class="text-sm-start text-warning">{{msg}}</p>
            {% endfor %}
            <form method="post">
                {{ form.csrf_token() }}
                {{ render_field(form.email,placeholder='Your email')}}
                {{render_field(form.password,placeholder='Your password')}}
                {{render_field(form.submit)}}
                <a class="btn btn-light" href="{{url_for('auth.register')}}"> Sign Up</a>
            </form>
        </div>
    </div>
    {% endblock %}
    

    最后是对应的后端view代码:

    @bp.route('/login', methods=['POST', 'GET'])
    def login():
        print('auth/login')
        loginForm = LoginForm()
        if loginForm.validate_on_submit():  #登录
            print('validated')
            email = loginForm.email.data
            password = loginForm.password.data
            user = User.query.filter_by(email=email).first()
            if not user:
                flash('User does not exist')
                return render_template('login.html', form=loginForm)
            if user.role >= const.DB_ROLE_VISITOR:
                flash('Please verify the mailbox first')
                return redirect(url_for('auth.email_verify'))
            if not user.check_password(password):
                flash('Incorrect password')
                return render_template('login.html', form=loginForm)
            login_user(user)
            return redirect(url_for('post.list'))
        return render_template('login.html', form=loginForm)
    
  2. 注册界面

    注册界面的代码和登录几乎没有太大的区别。

    首先是注册表单:

    class RegisterForm(FlaskForm):
        email = EmailField('Email', validators=[DataRequired(), Email()])
        username = StringField('Username', validators=[DataRequired(), Length(min=3, max=16)])
        password = PasswordField('Password', validators=[DataRequired(), Length(min=6, max=12)])
        submit = SubmitField('Sign Up')
    

    然后是对应的前端代码:

    <!-- register.html -->
    {% extends 'base.html' %}
    {% from 'bootstrap5/form.html' import render_field,render_form_row %}
    	
    {% block content %}
    <div style="height: 600px; padding-top: 100px;">
    	   <div style="width: 36rem;" class="mx-auto shadow-sm px-3 py-5  bg-body rounded">
    	       <h2>Sign Up</h2>
    	       <hr>
    	       {% for msg in get_flashed_messages() %}
    	       <p class="text-sm-start text-warning">{{msg}}</p>
    	       {% endfor %}
    	       <form method="post">
    	           {{ form.csrf_token() }}
    	           {{ render_field(form.email,placeholder='Enter your email address')}}
    	           {{ render_field(form.username,placeholder='Make a name you like')}}
    	           {{render_field(form.password,placeholder='Create a strong password')}}
    	           {{render_field(form.submit)}}
    	           <a class="btn btn-light" href="{{url_for('auth.login')}}"> Sign In</a>
    	       </form>
    	   </div>
    </div>
    {% endblock %}
    

    最后是视图代码:

    @bp.route('/register', methods=['POST', 'GET'])
    def register():
        print('auth/register')
        registerForm = RegisterForm()
        if registerForm.validate_on_submit():
            print('validated')
            email = registerForm.email.data
            username = registerForm.email.data
            password = registerForm.password.data
            user = User.query.filter_by(email=email).first()
            if user:
                flash('Mailbox registered')
                return render_template('register.html', form=registerForm)
            user = User(email=email, password=password, username=username)
            addUser(user)
            newPost(user)  # 为当前用户添加一个文章
            return redirect(url_for('auth.email_send', emailbox=email))
        return render_template('register.html', form=registerForm)
    
  3. 密码修改

    密码修改表单:

    class RePasswardForm(FlaskForm):
        password = PasswordField('Original Password', validators=[DataRequired()])
        newpaswd = PasswordField('New Password', validators=[DataRequired(), Length(min=6, max=12)])
        confpswd = PasswordField( 'Confirm Password', validators=[DataRequired(), Length(min=6, max=12)])
        submit = SubmitField('Confirm')
    

    密码修改界面:

    {% extends 'base.html' %}
    {% from 'bootstrap5/form.html' import render_field %}
    
    {% block content %}
    <div style="height: 600px; padding-top: 100px;">
        <div style="width: 36rem;" class="mx-auto shadow-sm px-3 py-5 bg-body rounded">
            {% for msg in get_flashed_messages() %}
            <p class="text-sm-start text-warning">{{msg}}</p>
            {% endfor %}
            <form method="post">
                {{ form.csrf_token() }}
                {{ render_field(form.password) }}
                {{ render_field(form.newpaswd) }}
                {{ render_field(form.confpswd) }}
                {{ render_field(form.submit) }}
                <a class="btn btn-light" href="{{url_for('auth.register')}}"> Sign Up</a>
            </form>
        </div>
    </div>
    {% endblock %}
    

    密码修改后端代码:

    @login_required
    @bp.route("/resetpwd/<int:id>", methods=['GET', 'POST'])
    def resetpwd(id):
        print('auth/resetpwd')
        resetForm = RePasswardForm()
        if resetForm.validate_on_submit():
            password = resetForm.password.data
            newpaswd = resetForm.newpaswd.data
            if not current_user.check_password(password):
                flash('The original password is incorrect')
                return render_template('reset_pwd.html', form=resetForm)
            current_user.password = newpaswd
            updateUser(current_user)
            return redirect(url_for('auth.logout'))
        return render_template('reset_pwd.html', form=resetForm)
    
  4. 邮箱验证

    这也是本次更新的重点,用户在注册账号之后,系统会对注册邮箱发送一封邮件,用户在没有验证邮箱之前不能登录系统。
    前后端的处理和之前一样,本次不再重复,只贴一段flask-email的使用代码:

    @bp.route('/email_send/<emailbox>')
    def email_send(emailbox):
        # 发送邮箱验证码
        print('email_send')
        user = User.query.filter_by(email=emailbox).first()
        if not user:
            return '404'
        if user.role >= const.DB_ROLE_BAD:
            flash('Sorry!')
            return '404'
    
        msg = Message('Mailbox verification - Markdown-Online',
                      sender=current_app.config['MAIL_USERNAME'],
                      recipients=[emailbox])
        code = random.randint(100000, 999999)
        msg.body = "Your verification code is:" + str(
            code) + "\n Please keep it safe."
        send_async_email(msg)
        user.status = code
        user.role += 1
        updateUser(user)
        return redirect(url_for('auth.email_verify'))
    

    以上代码会向目标邮箱发送一封带有验证码的邮件。
    使用flask-email插件,需要配置的参数:

    SECRET_KEY = b'_5#y2L"99567\n\xec]/'    # Flask需要的密钥,一个复杂的字符串即可
    ICP='京ICP备20210xxxxxx号'				# 网站的备案号,需要备案才能获得
    MAIL_SERVER = 'smtp.qq.com'				# 发送邮件需要的smtp服务器,这里是qq邮箱的
    MAIL_PORT = 465							# 端口,一般都是465,如果使用163邮箱,可以百度一下
    MAIL_USE_SSL = True						# SSL加密的传输方式
    MAIL_USE_TSL = False					# 传统的传输方式
    MAIL_USERNAME = 'markdown-online@qq.com'# 这是你想用来发邮件的邮箱,可以填你自己的邮箱
    MAIL_PASSWORD = 'wtvcrkyjzlagbadg'		# 邮箱的授权码,但是需要去申请一个
    HOST_NAME='www.weidawang.site'			# 这是我的域名,写不写都行
    SMMS_AUTHORIZATION='7qV3kO1Fc8U6ixxxxxx'# sm.ms图床的授权码,上文介绍了获取方式
    
  5. 文章列表

    支持分页,删除文章,这里还有一个admin按钮,可以跳转管理员界面。普通用户看不到这个按钮。

  6. 文章编辑

    这里和之前没有什么两样。

  7. 编辑器主题

    在编辑器的下面,是编辑器的主题选择,可以选择工具条、编辑区、预览区的主题风格。
    尤其是编辑区,有多种可选的主题。

  8. 管理页面

    这里是简单的管理页面,虽然页面看起来非常简单,但是包括了权限管理、用户删除等多种功能。

    其中,管理员显示红色,并有特殊标记,用户、游客、封号都有不同的颜色和标记。

    管理员可以授权普通用户成为管理员,也可以删除管理员的管理权限。

总结

系统虽小,五脏俱全,肝了两天,好累~~
欢迎大家体验,我这里就不详细介绍了,睡了睡了
预览地址:Markdown-Online
代码下载:Markdown-Online

有关两天时间,用Python重写了我的Markdown-Online系统,主要使用了Flask技术栈的基础知识,这不比游戏有意思?的更多相关文章

  1. 电脑0x0000001A蓝屏错误怎么U盘重装系统教学 - 2

      电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。  准备工作:  1、U盘一个(尽量使用8G以上的U盘)。  2、一台正常联网可使用的电脑。  3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。  4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。  U盘启动盘制作步骤:  注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注

  2. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  3. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  4. ruby -::在 Ruby 语法中是什么意思? - 2

    这个问题在这里已经有了答案:WhatisRuby'sdouble-colon`::`?(12个答案)关闭8年前。什么是::?@song||=::TwelveDaysSong.new

  5. ruby - __FILE__ == $PROGRAM_NAME 在 ruby​​ 中是什么意思? - 2

    这个问题在这里已经有了答案:Whatdoes`if__FILE__==$0`meaninRuby(6个答案)关闭6年前。我在审查Ruby代码时偶然发现了这个语法。代码是:if__FILE__==$PROGRAM_NAME#somecode...end我想__FILE__是一个变量,可以让我获取我所在文件的名称?但是$PROGRAM_NAME简化了什么?另外,为什么这个if语句是必需的,因为程序可以使用或不使用它?

  6. ruby-on-rails - 没有参数的 `<<`(小于两倍)是什么意思? - 2

    我在一个我想在formtasticGem中覆盖的方法中找到了这个。该方法如下所示:defto_htmlinput_wrappingdohidden_field_html是什么意思?在第三行做什么?我知道它对数组有什么作用,但在这里我不知道。 最佳答案 你可以这样读:hidden_field_htmllabel_with_nested_checkbox是连接到hidden_​​field_html末尾的参数-为了“清晰”,他们将其分成两行 关于ruby-on-rails-没有参数的`

  7. ruby - Ruby 的 AST 中的 'send' 关键字是什么意思? - 2

    我正在尝试学习Ruby词法分析器和解析器(whitequarkparser)以了解更多有关从Ruby脚本进一步生成机器代码的过程。在解析以下Ruby代码字符串时。defadd(a,b)returna+bendputsadd1,2它导致以下S表达式符号。s(:begin,s(:def,:add,s(:args,s(:arg,:a),s(:arg,:b)),s(:return,s(:send,s(:lvar,:a),:+,s(:lvar,:b)))),s(:send,nil,:puts,s(:send,nil,:add,s(:int,1),s(:int,3))))任何人都可以向我解释生成的

  8. ruby - 在没有基准或时间的情况下用 Ruby 测量用户时间或系统时间 - 2

    因为我现在正在做一些时间测量,我想知道是否可以在不使用Benchmark类或命令行实用程序time的情况下测量用户时间或系统时间。使用Time类只显示挂钟时间,而不显示系统和用户时间,但是我正在寻找具有相同灵active的解决方案,例如time=TimeUtility.now#somecodeuser,system,real=TimeUtility.now-time原因是我有点不喜欢Benchmark,因为它不能只返回数字(编辑:我错了-它可以。请参阅下面的答案。)。当然,我可以解析输出,但感觉不对。*NIX系统的time实用程序也应该可以解决我的问题,但我想知道是否已经在Ruby中实

  9. ruby - 我需要从 facebook 游戏中抓取数据——使用 ruby - 2

    修改(澄清问题)我已经花了几天时间试图弄清楚如何从Facebook游戏中抓取特定信息;但是,我遇到了一堵又一堵砖墙。据我所知,主要问题如下。我可以使用Chrome的检查元素工具手动查找我需要的html-它似乎位于iframe中。但是,当我尝试抓取该iframe时,它​​是空的(属性除外):如果我使用浏览器的“查看页面源代码”工具,这与我看到的输出相同。我不明白为什么我看不到iframe中的数据。答案不是它是由AJAX之后添加的。(我知道这既是因为“查看页面源代码”可以读取Ajax添加的数据,也是因为我有b/c我一直等到我可以看到数据页面之后才抓取它,但它仍然不存在)。发生这种情况是因为

  10. 语法类似于 GitHub Flavored Markdown 的 Ruby markdown 解释器? - 2

    我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong

随机推荐