python设计微型小说网站(基于Django+Bootstrap框架)

一、项目背景:

为了回顾关于django的文件上传和分页功能,打算写一个微型的小说网站练练手。花了一个下午的时间,写了个小项目,发现其中其实遇到了许多问题,不过大部分通过debug之后就解决了,其他部分通过阅读了Pagination插件以及Bootstrap-FileInput插件的官方文档。

二、详细设计:

省去小说网站的用户模块的功能,小说网站主要的功能就是上传文件,在线阅读小说。针对这两个功能,

主要用到dajngo内置的Pagination模块,以及选择一个上传文件插件即可。因为用的是Bootsrap前端框架,所以就选择了Bootsrap比较多人用的FileInput插件。

大致的流程:

  • 在首页可以选择上传本地的txt文件到服务器上,然后首页上同时会异步更新已上传的txt文本文件列表。
  • 并且可以在上面选择阅读或者删除的操作。阅读则跳转到另外一个页面,后台会读取该文本文件,并且进行分页操作,返回到前端。主要的流程就是这样。接下来讲讲Pagination和FileInput插件和核心代码。

三、合适的工具:

Django内置的Pagination实现分页功能,这个不用多说,用Django做web开发分页功能都会用到。

Bootstrap本身自带upload file文件上传插件太丑了,加上功能也不够完善。所以选择了Bootstrap FileInput插件。

版本选择:

  • Python 3.6.6
  • Django==2.1.7
  • Bootstrap v4.3.1
  • bootstrap-fileinput v4.5.2

四、代码详解:

首先代码主要分为两块,一块为文件上传后,接收文件对象,保存到指定的目录下;第二块为读取txt文本文件内容,分页展示到前端页面。

首先讲讲文件上传的代码,主要涉及到前端的bootstrap-fileinputt插件。该插件将简单的HTML文件输入转换为高级文件选择器控件。对于不支持JQuery或Javascript的浏览器,将有助于回退到正常的HTML文件输入。

以上这段是官方的自我介绍,说说我个人感受吧。首先这个插件支持批量上传,异步上传等功能,简化大部分JS逻辑方面的代码,具体只要跟着官方的API文档看一看,修改一些参数即可。其次,对于上传时会显示一个进度条,用于显示上传的完成度,这样直观反映了完成度。

bootstrap-fileinput的github地址:

https://github.com/kartik-v/bootstrap-fileinput

bootstrap-fileinput的官方文档地址:

http://plugins.krajee.com/file-input

bootstrap-fileinput的官方DEMO:

http://plugins.krajee.com/file-basic-usage-demo

4.1、文件上传

HTML代码:

 <div dir=rtl class="file-loading">
  <input id="input-b8" name="input-b8" multiple type="file">
</div>

JS代码:

$(document).ready( function() {
$("#input-b8").fileinput({
  rtl: true,
  uploadUrl: '/file_receive/',
  dropZoneEnabled: false,
  showPreview: false,
  allowedFileExtensions: ['txt'],
  initialPreviewConfig: []
});
});

代码说明:

fileinput()方法里面传入的是一个json数据,里面有很多个属性,每个数值代表初始化上传控件时的特性,如果没有设置的属性则按照控件的默认属性设置。简单说下里面几个属性的设置:uploadUrl:上传文件地址;dropZoneEnabled:是否显示拖曳区域;showPreview:是否显示预览区域;allowedFileExtensions:允许上传的文件格式。

后台代码

def file_receive(request):
  #  接收File-Input空间传送的文件
  if request.method == 'POST':
    file = request.FILES['input-b8']
    file_path = "static/books/"+file.name
    with open(file_path,"wb") as f:
      for chunk in file.chunks():
        f.write(chunk)
  return JsonResponse({'status':'success'})

代码说明:

以上是后台接收文件对象并且保存的代码。我这边省略判断上传文件大小的方法,感兴趣的可以在with open()中添加判断。最后接收文件后,会返回给前端一个json数据,前端插件接收到返回的JSON数据才会确定是否上传文件成功,bootstrap Fileinput才会先Done状态。

拓展:

这里有点需要注意的就是,后台接收上传的文件,虽然是通过POST的方式上传,但是不能通过request.POST["filename"]或者request.POST.get("filename","None")两种方式来访问。

而是需要用另外一种方式:

request.FILES["filename"]或者request.FILES.get("filename","None")

接下来已经得到文件对象,需要把在内存中的文件写入到硬盘中。读取文件的几个方法和属性:

  • filename.read():从文件读取整个上传的数据,这个方法只适合小文件
  • filename.chunks():按块返回文件,通过for循环进行迭代,可以将大文件按块写入到服务器中
  • filename.multiple_chunks():当filename文件大于2.5M时,该方法返回True,否则返回False。可以根据该方法来判断选择用1方法还是2方法。

4.2、异步更新已上传的文件列表

HTML代码:

<div style="padding-top: 20px">
  <table id="book_list" class="table table-striped table-bordered table-hover">
    <tr>
      <th>上传书籍</th>
      <th>上传时间</th>
      <th>文件大小</th>
      <th>操作</th>
    </tr>
    {% for book in objects %}
    <tr>
      <td>{{ book.name}}</td>
      <td>{{ book.book_time }}</td>
      <td>{{ book.book_size }}</td>
      <td><a href="/book_read/?book_name={{ book.name }}" rel="external nofollow" >阅读</a>
      <a href="/book_del/?book_name={{ book.name }}" rel="external nofollow" >删除</a></td>
    </tr>
    {% endfor %}
  </table>
</div>

JS代码:

$("#input-b8").on('fileuploaded',function(){
  console.log('success');
  $.get('/book_update/',function(data){
    var book_html ="<tr>\n" +
      "<th>上传书" +
      "籍</th>" +
      "<th>上传时间</th>" +
      "<th>文件大小</th>" +
      "<th>操作</th>"+
      "</tr>";

    console.log(data);
    for (var i in data){
      book_html += "<tr><td>"+ data[i]['name']+"</td>" +
        "<td>"+data[i]['book_time']+"</td>" +
        "<td>"+data[i]['book_size']+"</td>" +
        "<td><a href=\"/book_read/?book_name="+data[i]['name']+"\">阅读</a>"+
        "<a href=\"/book_del/?book_name="+data[i]['name']+"\">删除</a></td>"+
        "</tr>"
    }
    $("#book_list").html(book_html)
    console.log(book_html)
  });
});

代码说明:

$("#input-b8").on('fileuploaded',function(){})这个方法时在上传完文件后进行回调事件的函数;就是指上传一个文件成功后就会调用该方法;所以我将异步更新上传文件列表的代码放在这个回调事件中。当每个文件上传后,就会请求后台,查询指定目录下的文件列表,生成json格式的数据返回前台,前台再通过遍历的形式拿到其中的数据,进行展示,具体效果如下:

后台代码

def book_list():
  #  获取books目录下的书籍
  file_list = []
  filedir_path = "static/books/"
  list_file = os.listdir(filedir_path)
  for book in list_file:
    book_info = {}
    book_path = filedir_path + book

    book_info['name'] = book
    book_info['timestamp'] = os.path.getctime(book_path)
    book_info['book_time'] = time_format(book_info['timestamp'])
    book_info['book_size'] = os.path.getsize(book_path)
    file_list.append(book_info)
  books = sorted(file_list,key= lambda x:x['timestamp'],reverse=True)
  return books 

def time_format(timestamp):
  #  格式化时间戳成指定的时间
  time_struct = time.localtime(timestamp)
  time_string = time.strftime('%Y-%m-%d %H:%M',time_struct)
  return time_string 

代码说明:

代码其实很简单,主要是对通过os模块获取静态目录static下的books目录下的文件列表,然后在获取每个文件的时间戳,通过列表推导式,按时间戳为key值进行逆向排序。

4.3、文章分页模块

HTML代码:

<div class="header text-center ">
  <a href="/index/" rel="external nofollow" style="float: left;">
    <i class="fa fa-home fa-2x" aria-hidden="true">Home</i>
  </a>
  <h3>{{ book_name }}</h3>
</div>

<div class="col-md-12 col-sm-offset-1 main">
  {% for content in book_content %}
  <span>{{ content }}</span>
  {% endfor %}
</div>

<div class="pagination">
  <div class="col-md-4 ">
    {% if book_content.has_previous %}
    <i class="fa fa-arrow-left" aria-hidden="true">
      <a href="?book_name={{ book_name }}&page={{ book_content.previous_page_number }}" rel="external nofollow" >
        上一页
      </a>
    </i>

    {% endif %}
  </div>

  <div class="col-md-4 ">
    <h5>
      第{{ book_content.number }}页/共{{ book_content.paginator.num_pages }}页
    </h5>

  </div>
  {% if book_content.has_next %}
  <div class="col-md-4 ">
    <a href="?book_name={{book_name}}&page={{ book_content.next_page_number }}" rel="external nofollow" >
      下一页
    </a>
    <i class="fa fa-arrow-right" aria-hidden="true">
    </i>
  </div>
  {% endif %}
</div>

JS代码:

def book_read(request):
  #  获取上传书籍的内容
  if request.method == 'GET':
    book_name = request.GET['book_name']      # 书籍名称
    file_path = "static/books/" + book_name     # 书籍路径

    with open(file_path,encoding='gbk', errors='ignore') as f:
      book_contents = f.readlines()

    paginator = Paginator(book_contents, 50)
    try:
      page = int(request.GET['page']) # 页码
      book_content = paginator.page(page)
    except Exception as e:
      book_content = paginator.page(1)
    return render_to_response('book.html',{'book_content': book_content, 'book_name': book_name})

代码说明:

读取文件的所有行,保存在一个列表中(list),每行作为一个元素。然后实例化一个Paginator对象,并且在实例化中传入一个需要分页的对象列表,以及一页包含多少个数据。再从接收前端传送过来的页码,取特定页码的数据,再传回前端。

拓展:

1、分页功能有Django内置的Paginator类提供的,该类位于django/core/paginator,需要用的地方导入即可:
from django.core.paginator improt Paginator

2、read()、readline()、readlines()方法的区别:
三者都是读取文件内容:

  • read([size]):从当前位置其读取size字节,如果方法里面没有参数size,读取至文件结束为止。返回的是一个字符串对象。
  • readline():方法调用一次就读文件一行,该方法返回一个字符串。
  • readlines():读取整个文件所有行,保存在一个列表中,每行作为一个元素

3、Paginator对象操作:

实例化对象:

book_list = [1,2,3,4,5,6,7,8]
book_content = Paginator(book_list,3)

取特定页的数据

content = book_content.page(2)

查特定页当前页码数:

content.number

查分页后的总页数

content.num_pages

查询某一页是否有上一页或者查询上一页页码:

content.has_previous()
content.previous_page_number()

查询某一页是否有下一页或者查询下一页页码:

content.has_next()
content.next_page_number()

感兴趣的同学可以上GitHub上,项目代码的地址:

https://github.com/libuliduobuqiuqiu/noval_test

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 如何使用bootstrap框架 bootstrap入门必看!

    前言: 前几天,本想做一个登陆界面,但自己写form表单必然很丑,所以想用下bootstarp框架,之前听别人说bootstrap很牛的样子.但我完全不会bootstrap... 下载&目录 看bootstrap官网,接着我下载了用于生产环境Bootstrap: 解压出来是这样的: 目录结构大概是这样的,前几天在官网有看到.下面这个目录结构你应该先了解下: bootstrap3 ├── css │├── bootstrap-theme.css //主题类型,生产上一般用不到 │├── boots

  • 一个基于flask的web应用诞生 bootstrap框架美化(3)

    经过上一章的内容,其实就页面层来说已结可以很轻松的实现功能了,但是很明显美观上还有很大的欠缺,现在有一些很好的前端css框架,如AmazeUI,腾讯的WeUI等等,这里推荐一个和flask集成很好的bootstrap框架 安装框架 在模板中直接引用bootstrap的CDN或者本地路径外,还可以直接应用flask的bootstrap集成包,首先需要对集成包进行安装: pip3.6 install flask-bootstrap 这是一个flask的扩展包,flask的所有扩展包默认默认的包名都为

  • Python的Django框架中forms表单类的使用方法详解

    Form表单的功能 自动生成HTML表单元素 检查表单数据的合法性 如果验证错误,重新显示表单(数据不会重置) 数据类型转换(字符类型的数据转换成相应的Python类型) Form相关的对象包括 Widget:用来渲染成HTML元素的工具,如:forms.Textarea对应HTML中的<textarea>标签 Field:Form对象中的一个字段,如:EmailField表示email字段,如果这个字段不是有效的email格式,就会产生错误. Form:一系列Field对象的集合,负责验证和

  • 详解基于Bootstrap扁平化的后台框架Ace

    最近一段时间在做一个管理系统,在网上找了很久的前端展示框架,终于找到一款基于Bootstrap的后台管理系统模版:Ace.Bootstrap是Twitter 于2010年开发出来的前端框架,用过的同学应该知道,这款前端框架不仅界面很美观,而且兼容了很多的浏览器,大大加速了我们开发网站的速度!这篇文章讲到的Ace是基于Bootstrap的,所以界面自然也非常美观,这款后台管理系统组合了好多插件以及组件,可以满足很大一部分的后台管理系统模版.废话不多说,看下界面就知道了 如果想及时了解Spark.H

  • Bootstrap框架下下拉框select搜索功能

    之前用Easyui框架下做的下拉框选择,虽然可以搜索,但是有诸多的不便:比如,不能模糊匹配,必须按照第一个字母来搜索 心血来潮,想换个框架写后台,然后用Bootstrap搭了个架子,然后两种样式冲突,百度了一把,找到了另一个牛逼的基于Bootstrap下拉框搜索功能的js 不区分大小写,模糊匹配,哈哈,太棒了~~ 具体用法: <script type="text/javascript" src="<%=basePath%>/js/commons/jquery

  • 在Python的Django框架的视图中使用Session的方法

    SessionMiddleware 激活后,每个传给视图(view)函数的第一个参数``HttpRequest`` 对象都有一个 session 属性,这是一个字典型的对象. 你可以象用普通字典一样来用它. 例如,在视图(view)中你可以这样用: # Set a session value: request.session["fav_color"] = "blue" # Get a session value -- this could be called in

  • 使用PyCharm配合部署Python的Django框架的配置纪实

    安装软件 安装 Python 2.7.PyCharm.pip(Python包管理工具).Django ( pip install Django) 部署 PyCharm 新建Django工程 完成后,其目录如下: 子目录MyDjangoProject下表示工程的全局配置,分别为setttings.py.urls.py和wsgi.py,其中setttings.py包括了系统的数据库配置.应用配置和其他配置,urls.py则 表示web工程Url映射的配置. 子目录student则是在该工程下创建的a

  • Python的Django框架中使用SQLAlchemy操作数据库的教程

    零.SQLAlchemy是什么? SQLAlchemy的官网上写着它的介绍文字: SQLAlchemy is the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL. SQLAlchemy 是一个非常强大的ORM和数据库工具,但是它庞大的文档和复杂的功能总是让很 多人望而生畏.而Django的ORM相对来说

  • python设计微型小说网站(基于Django+Bootstrap框架)

    一.项目背景: 为了回顾关于django的文件上传和分页功能,打算写一个微型的小说网站练练手.花了一个下午的时间,写了个小项目,发现其中其实遇到了许多问题,不过大部分通过debug之后就解决了,其他部分通过阅读了Pagination插件以及Bootstrap-FileInput插件的官方文档. 二.详细设计: 省去小说网站的用户模块的功能,小说网站主要的功能就是上传文件,在线阅读小说.针对这两个功能, 主要用到dajngo内置的Pagination模块,以及选择一个上传文件插件即可.因为用的是B

  • 网站发布后Bootstrap框架引用woff字体无法正常显示的解决方法

    网站发布到IIS后,发现网站使用的Bootstrap框架所引用的woff字体无法正常显示.于是跟踪http请求,发现woff字体请求出现GET .woff 404 (Not Found)的问题,但是项目中woff字体的文件并未丢失.后经排查,原来是服务器上IIS没有添加woff字体的MIME类型,导致发送HTTP请求时,IIS无法处理和识别此类型的文件. 解决方法1:在Web.config配置文件中添加woff字体的MIME类型 解放方法2:在IIS中添加woff字体的MIME类型 woff字体

  • python 爬取国内小说网站

    原理先行 作为一个资深的小说爱好者,国内很多小说网站如出一辙,什么

  • 利用Python如何实现一个小说网站雏形

    前言 最近做了一个爬取妹子套图的小功能,小伙伴们似乎很有兴趣,为了还特意组建了一个Python兴趣学习小组,来一起学习.十个python九个爬,在大家的印象中好像Python只能做爬虫.然而并非如此,Python 也可以做Web开发,接下来给大家展示一下如何做一个小说站点. 下面话不多说了,来一起看看详细的介绍吧 相关软件 软件 版本 功能 地址 Python 3.7.1 脚本语言 https://www.python.org/ Django 2.1.3 Web框架 https://www.dj

  • Python爬虫之爬取最新更新的小说网站

    一.引言 这个五一假期自驾回老家乡下,家里没装宽带,用手机热点方式访问网络.这次回去感觉4G信号没有以前好,通过百度查找小说最新更新并打开小说网站很慢,有时要打开好多个网页才能找到可以正常打开的最新更新.为了躲懒,老猿决定利用Python爬虫知识,写个简单应用自己查找小说最新更新并访问最快的网站,花了点时间研究了一下相关报文,经过近一天时间研究和编写,终于搞定,下面就来介绍一下整个过程. 二.关于相关访问请求及应答报文 2.1.百度搜索请求 我们通过百度网页的搜索框进行搜索时,提交的url请求是

  • 基于Django的python验证码(实例讲解)

    验证码 在用户注册.登录页面,为了防止暴力请求,可以加入验证码功能,如果验证码错误,则不需要继续处理,可以减轻一些服务器的压力 使用验证码也是一种有效的防止crsf的方法 验证码效果如下图: 验证码视图 新建viewsUtil.py,定义函数verifycode 此段代码用到了PIL中的Image.ImageDraw.ImageFont模块,需要先安装Pillow(3.4.1)包, 详细文档参考 http://pillow.readthedocs.io/en/3.4.x/ Image表示画布对象

  • python爬虫爬取笔趣网小说网站过程图解

    首先:文章用到的解析库介绍 BeautifulSoup: Beautiful Soup提供一些简单的.python式的函数用来处理导航.搜索.修改分析树等功能. 它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序. Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码. 你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了.然后,你仅仅

  • 基于Django contrib Comments 评论模块(详解)

    老版本的Django中自带一个评论框架.但是从1.6版本后,该框架独立出去了,也就是本文的评论插件. 这个插件可给models附加评论,因此常被用于为博客文章.图片.书籍章节或其它任何东西添加评论. 一.快速入门 快速使用步骤: 安装包:pip install django-contrib-comments 在django的settings中的INSTALLED_APPS处添加'django.contrib.sites'进行app注册,并设置SITE_ID值. 在django的settings中

  • 基于 Django 的手机管理系统实现过程详解

    一.概述 打算通过设计数据库,然后结合 Python 框架Django,实现在网页上对数据库的增删改查(本例以手机的管理为例,不考虑订购功能),有普通用户界面和管理员用户界面,普通用户只能做简单的查看需求,管理员用户可以实现对数据库内容的实时修改. 网站主体如下图: 二.设计数据库 根据业务需求,设计数据表,需要下列这些属性: 手机型号.品牌.手机描述.出厂年份.价格.照片.产地. 根据数据表设计原则,数据表设计需要满足基本的函数依赖和范式要求,因此我们将上述属性拆分为四张表格,并建立这些数据表

  • 基于Django框架的权限组件rbac实例讲解

    1.基于rbac的权限管理 RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,一个角色拥有若干权限.这样,就构造成"用户-角色-权限"的授权模型.在这种模型中,用户与角色之间,角色与权限之间都是多对多的关系. 简单的模型图示如下: 2.Rbac组件的基本目录结构: 3.按照写的流程,来讲解rbac组件中的各个部分,以及功能, 3.1 models数据库表设计(models.py). 为了在

随机推荐