小白都能看懂的实战教程 手把手教你Python Web全栈开发 (DAY 6)

Posted 亓官劼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小白都能看懂的实战教程 手把手教你Python Web全栈开发 (DAY 6)相关的知识,希望对你有一定的参考价值。

大家好,我叫亓官劼(qí guān jié ),这个《小白都能看懂的实战教程 手把手教你Python Web全栈开发》是一个零基础的实战教程,手把手带你开发一套系统,带你了解Python web全栈开发,目前正在连续更新中,如果喜欢的话可以点赞关注博主,后面会持续更新。

博主博客文章内容导航(实时更新)
更多优质文章推荐:

小白都能看懂的实战教程 手把手教你Python Web全栈开发 (DAY 6)

  今天来到我们实战系列的第六天,在之前的五天里,我们已经完成了在线论坛系统的导航条、登录、注册、论坛页面、帖子详情页面、个人页面、修改密码、查看已发布帖子等的功能实现,目前我们的论坛已经可以进行帖子发布,查看帖子详情,并且进行回复信息了。在上一讲中,我们还是实现了功能限制,对不同用户的访问进行过滤。下面我们继续来完善我们的这个在线论坛系统,今天我们来为这个系统添加资源专区,这里我们主要分为资源上传,资源列表(查看资源列表),在线查看资源文件、资源文件下载的功能。

  本文原创为CSDN博主亓官劼,原文链接为:收藏!最详细的Python全栈开发指南 看完这篇你还不会Python全栈开发 你来打我!!!,请大家支持原创,拒绝抄袭。

6.1资源上传功能实现

  这里我们来开始实现资源上传功能,我们先从前端开始实现,然后到后端进行存储。之前写过一篇如何实现文件上传下载的博文,如果对这方面还不太了解的同学,可以先去看一下博文:Python Flask文件上传下载,这篇博文简单的介绍了如何实现文件的上传与下载,这里我们来进行一个详细的实现。

6.1资源上传功能实现-前端

  资源文件上传,我们这里设计一个<div>,然后里面放一个<form>,进行文件的上传,和文件描述。这里先创建一个post_file.html文件用来当前的前端的文件,post_file.css文件用来记录样式。我们这个页面还是继承自base.html。还是先上个效果图,然后我们给一个源码,因为这里前端的话,我们就是一个<table>然后里面放3行的信息。

这里我们需要注意的就是,在我们的form中,不要忘记设置enctype,需要把这个属性设置为multipart/form-data
post_file.html:

% extends 'base.html' %

% block title %
资源上传
% endblock %

% block css %
<link rel="stylesheet" href="/static/css/post_file.css">
% endblock %

% block content %
<div class="post_file_content">
    <div class="page-header" id="page_header">
      <h1>资源上传<small>Resource upload</small></h1>
    </div>
    <div class="post_file_div">
        <form action="" method="post" enctype="multipart/form-data">
            <table id="file_table">
                <tr>
                    <td>
                        选择你需要上传的文件
                    </td>
                    <td>
                        <input id="file_butt" type="file" name="file">
                    </td>
                </tr>
                <tr>
                    <td>
                        请输入文件名称:
                    </td>
                    <td>
                        <div class="form-group">
                            <input type="text" class="form-control" name="filename" id="exampleInputEmail1" placeholder="请输入文件名称:">
                        </div>
                    </td>
                </tr>
                <tr>
                    <td>
                        请输入文件描述信息:
                    </td>
                    <td>
                        <div class="form-group">
                            <input type="text" class="form-control" name="file_info" id="exampleInputEmail1" placeholder="请输入文件描述信息:">
                        </div>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <div id="login_butt">
                          <button type="submit" class="btn btn-default">上传</button>
                      </div>
                    </td>
                </tr>
            </table>
        </form>
    </div>
</div>
% endblock %

post_file.css

.post_file_content
    margin-top: 8%;;
    margin-left: 25%;
    margin-right: 25%;


#page_header
    text-align: center;


#file_table td
    width: 200px;

#login_butt
    text-align: center;

6.1.2资源上传功能实现-数据库端

  这里我们又需要新增一个表了,用来存储我们的一个文件的存储信息,我们主要存储的信息有:Fno(用来唯一标识我们的文件)、文件名称、文件描述信息、文件上传时间。

SQL语句为:

create table Files
(
	Fno varchar(128) not null,
	filename nvarchar(128) default '未命名' null,
	file_info nvarchar(128) default '没有描述信息' null,
	file_time datetime null,
	email varchar(128) null,
	constraint Files_UserInformation_email_fk
		foreign key (email) references UserInformation (email)
);

create unique index Files_Fno_uindex
	on Files (Fno);

alter table Files
	add constraint Files_pk
		primary key (Fno);


  本文原创为CSDN博主亓官劼,原文链接为:收藏!最详细的Python全栈开发指南 看完这篇你还不会Python全栈开发 你来打我!!!,请大家支持原创,拒绝抄袭。

6.1.3资源上传实现-后端

  下面我们来实现我们资源上传的数据库端,首先我们需要在我们的项目文件中创建一个文件夹用来存放我们上传的文件。这里创建了一个store文件夹用于存放上传的文件。
下面我们就来讲从前端发送的文件保存到我们的服务器的文件夹中。这里为了服务器文件的安全性,我们这里文件的名称采用再次命名,一来可以防止重复的文件名,二来可以防止文件名称中有一些特殊的字符。我们这里的文件名称采用随机的120字符,然后加上原本文件的后缀组成,这里可以防止本地存储位置的文件有重复。在代码中有各个步骤的详细注解,大家可以查看代码中的信息:

# 生成120位随机id
def gengenerateFno():
    re = ""
    for i in range(120):
        re += chr(random.randint(65, 90))
    return re

# 资源上传页面
@app.route('/post_file',methods=['GET','POST'])
@login_limit
def post_file():
    if request.method == 'GET':
        return render_template('post_file.html')
    if request.method == 'POST':
        email = session.get('email')
        upload_file = request.files.get('file')
        filename = request.form.get('filename')
        file_info = request.form.get('file_info')
        file_path = 'store'
        file_time = time.strftime("%Y-%m-%d %H:%M:%S")
        Fno = gengenerateFno()
        try:
            cur = db.cursor()
            sql = "select * from Files where Fno = '%s'" % Fno
            db.ping(reconnect=True)
            cur.execute(sql)
            result = cur.fetchone()
            # 如果result不为空,即该Fno已存在时,一直生成随机的Fno,只到该数据库中不存在
            while result is not None:
                Fno = gengenerateFno()
                sql = "select * from Files where Fno = '%s'" % Fno
                db.ping(reconnect=True)
                cur.execute(sql)
                result = cur.fetchone()
            # 获取文件的后缀
            upload_name = str(upload_file.filename)
            houzhui = upload_name.split('.')[-1]
            # 保存在本地的名字为生成的Fno+文件后缀,同时修改Fno的值
            Fno = Fno+"."+houzhui
            # 保存文件到我们的服务器中
            upload_file.save(os.path.join(file_path,Fno))
            # 将文件信息存储到数据库中
            sql = "insert into Files(Fno, filename, file_info, file_time,email) VALUES ('%s','%s','%s','%s','%s')" % (Fno,filename,file_info,file_time,email)
            db.ping(reconnect=True)
            cur.execute(sql)
            db.commit()
            cur.close()
            return render_template('index.html')
        except Exception as e:
            raise e

  这样我们就可以将我们的文件上传到我们是服务器端,并且保存到我们制定的文件夹中了。

6.2 资源专区功能实现

  下面我们开始来实现我们的资源专区,这里的资源专区我们用来显示我们的所有的资源的一个列表,并且可以进行在线查看资源和下载资源。

6.2.1 资源专区功能实现-后端

  资源专区的话,我们还是先实现后端,发送数据到前端,然后我们前端将接收到的数据进行一个排版,然后显示。大家有没有发现一个问题,我们刚刚先实现了资源的上传,但是我们并没有导航,那为什么我们要先实现资源上传呢?因为如果我们先实现资源专区的话,没有东西显示,用于测试啊~所以我们先实现资源上传,可以先上传文件,便于资源专区的实现。
  这里我们需要返回到前端的数据有Fno、文件名、文件描述、创建时间和创建人的昵称。

# 资源专区
@app.route('/source')
def source():
    if request.method == 'GET':
        try:
            cur = db.cursor()
            sql = "select Fno,filename,file_info,file_time,nickname from Files,UserInformation where Files.email = UserInformation.email"
            db.ping(reconnect=True)
            cur.execute(sql)
            files = cur.fetchall()
            cur.close()
            return render_template('source.html',files = files)
        except Exception as e:
            raise e

6.2.2资源专区功能实现-前端

  资源专区的前端我们首先需要一个列表用来展示我们的服务器中已上传的文件的信息,并且导航到我们的文件在线查看,文件下载等功能。这里使用source.html用来实现我们的前端功能,使用source.css存放样式的描述信息。页面效果为:
在这里由于我们的在线查看文件和下载文件还没有实现,所有我们这里的超链接的地址是#,等下我们来进行实现。目前的前端的页面代码为:

% extends 'base.html' %

% block title %
资源专区
% endblock %

% block css %
<link rel="stylesheet" href="/static/css/source.css">
% endblock %

% block content %
<div class="source_content">
    <div class="page-header" id="page_header">
      <h1>资源专区<small>Resources Zone</small></h1>
    </div>
    <div class="source_div">
        <ul class="source_ul">
            % for file in files %
                <li class="issue_list_li">
                    <div class="issue_div">
                        <div class="issue_content">
                            <h3>
                                <a href="#">
                                     file[1] 
                                </a>
                            </h3>
                            <article>
                                 file[2] 
                            </article>
                        </div>
                        <div class="author_info">
                            <p class="post-info">
                                <span>上传者: file[4] </span>&emsp;&emsp;
                                <span>上传时间: file[3] </span>&emsp;
                                <span><a href="#">在线查看</a></span>&emsp;
                                <span><a href="#">下载文件</a></span>
                            </p>
                        </div>
                    </div>
                </li>
            % endfor %
        </ul>
    </div>
</div>
% endblock %
% block source_class %
active
% endblock %

source.css:

.source_content
    margin-right: 20%;
    margin-left: 20%;
    margin-top: 8%;


.author_info
    text-align: right;


.source_ul
    list-style-type: none;
    margin-left: 0;
    padding-left: 0;

#page_header
    text-align: center;

  我们在base.html中添加了资源专区的导航,并且添加了source_class的block,如果不修改base.html的话,需要将source.html的最后3行删除,不然会报错。base中插入的代码为<li class="% block source_class %% endblock %"><a href=" url_for('source') ">资源专区</a></li>插入在论坛导航的下面一行。

  本文原创为CSDN博主亓官劼,原文链接为:收藏!最详细的Python全栈开发指南 看完这篇你还不会Python全栈开发 你来打我!!!,请大家支持原创,拒绝抄袭。

6.2.3 实现文件在线查看功能

  其实这里面要想实现文件的在线查看功能非常的容易实现,我们只需要返回这个文件即可。我们这里需要在路由处传递一个参数Fno,用来寻找我们的文件。

# 在线查看文件
@app.route('/online_file/<Fno>')
def online_file(Fno):
    return send_from_directory(os.path.join('store'), Fno)

6.2.4 实现文件下载功能

  我们再来实现我们的文件下载功能,这个也是非常简单的,我们直接返回一个send_file即可实现文件的下载。

# 文件下载功能
@app.route('/download/<Fno')
def download(Fno):
    return send_file(os.path.join('store') + "/" + Fno, as_attachment=True)

在实现完我们的文件在线查看和文件下载之后,我们就可以修改我们的资源专区的前端,为其超链接添加一个正确的链接,让他能够实现正确的功能了。修改后的souce.html页面为:

% extends 'base.html' %

% block title %
资源专区
% endblock %

% block css %
<link rel="stylesheet" href="/static/css/source.css">
% endblock %

% block content %
<div class="source_content">
    <div class="page-header" id="page_header">
      <h1>资源专区<small>Resources Zone</small></h1>
    </div>
    <div class="source_div">
        <ul class="source_ul">
            % for file in files %
                <li class="issue_list_li">
                    <div class="issue_div">
                        <div class="issue_content">
                            <h3>
                                <a href=" url_for('online_file',Fno = file[0]) ">
                                     file[1] 
                                </a>
                            </h3>
                            <article>
                                 file[2] 
                            </article>
                        </div>
                        <div class="author_info">
                            <p class="post-info">
                                <span>上传者: file[4] </span>&emsp;&emsp;
                                <span>上传时间: file[3] </span>&emsp;
                                <span><a href以上是关于小白都能看懂的实战教程 手把手教你Python Web全栈开发 (DAY 6)的主要内容,如果未能解决你的问题,请参考以下文章

小白都能看懂的实战教程 手把手教你Python Web全栈开发 (DAY 4)

小白都能看懂的实战教程 手把手教你Python Web全栈开发 (DAY 6)

手把手教你使用 Vuex,猴子都能看懂的教程

实战篇:小白都能看懂的Linux安装Oracle数据库详细教程

小白都能看得懂的教程 一本教你如何在前端实现富文本编辑器

小白都能看得懂的教程 一本教你如何在前端实现markdown编辑器