Django 之瀑布流实现

左心房为你撑大大i 提交于 2019-11-30 18:34:42

需求分析

现在是 "图片为王"的时代,在浏览一些网站时,经常会看到类似于这种满屏都是图片。图片大小不一,却按空间排列,就这是瀑布流布局。

  • 以瀑布流形式布局,从数据库中取出图片
  • 每次取出等量(7 条)的图片,加载到页面
  • 当滑轮滚动到最底端时,自动再加载图片

实现流程

  • 以包形式管理模型
  • 将图片自动上传到静态文件 static
  • 前端页面每行排列四张图片(四个 div )
  • 当页面加载时,以 ajax 形式自动向后台发送请求,获取图片数据,再用 js 循环生成 img 标签添加到每个 div 中
  • JS 循环图片信息列表,将当前循环元素的索引与每行排列的图片数目(4张)求余数,再利用余数定位每个 div 标签

模型设计

在这里,我以包的形式管理模型 models,编写 app/models/video/img_models.py

from django.db import models      class Img(models.Model):      """      upload_to: 上传文件地址      """      src = models.FileField(max_length=64, verbose_name='图片地址', upload_to='app/static/app/upload')      title = models.CharField(max_length=64, verbose_name='标题')      summary = models.CharField(max_length=128, verbose_name='简介')        class Meta:          verbose_name_plural = '图片'        def __str__(self):          return self.title

视图函数

编写 app/views.py

from django.shortcuts import render  from django.http import JsonResponse  from app.models.video.img_models import Img      def img(request):        return render(request, 'app/img.html')      def getImgs(request):      nid = request.GET.get('nid')      print(nid)        # nid 第一次取为 0,每次取 7 条      last_position_id = int(nid) + 7      postion_id = str(last_position_id)        # 获取 0 < id < 7 的数据      img_list = Img.objects.filter(id__gt=nid, id__lt=postion_id).values('id', 'title', 'src')      img_list = list(img_list)   # 将字典格式转换为列表形式      ret = {          'status': True,          'data': img_list      }        return JsonResponse(ret)

在后台取出符合条件的数据,然后打包成 JSON 格式数据,前端模板再通过 jQuery 将其循环生成 img 标签,并添加到 div 标签中。

模板

编写 app/templates/app/img.html

{% load static %}  <!DOCTYPE html>  <html lang="en">  <head>      <meta charset="UTF-8">      <title>瀑布流</title>      <style type="text/css">          .box1{              width: 1000px;              margin: 0 auto;          }            .box1 .item{              width: 25%;              float: left;          }            .item img{              width: 100%;          }      </style>  </head>  <body>      <h1>瀑布流</h1>      <div class="box1" id="container">          <div class="item">            </div>            <div class="item">            </div>            <div class="item">            </div>            <div class="item">            </div>      </div>          <script src="{% static 'app/jquery/jquery-3.1.1.js' %}"></script>      <script>          $(function () {              initImg();              scroll();          });            NID = 0;          LASTPOSTION = 3;    // 循环最后那个的位置          function initImg() {              $.ajax({                  url: '/app/getImgs/',                  type: 'GET',                  data: {nid: NID},                  dataType: 'JSON',                  success: function (arg) {                      if (arg.status){                         var img_list = arg.data;                         $.each(img_list, function (index, value) {                            var n = (index + LASTPOSTION + 1) % 4;  {#                          console.log(n);    // 0、1 、2 、3    一直为 0、1 、2 、3#}                            var img = document.createElement('img');                            img.src = '/' + value.src;    //  app/static/app/upload/7.jpg                               // 也就是给第一、二、三、四给 div 添加 img 标签,eq(0) 为第一个                            $('#container').children().eq(n).append(img);                            if (index + 1 == img_list.length){                                console.log(n, value.id);                                LASTPOSTION = n;  {#                              NID = value.id;#}                            }                         });                      }                  }              })          }            // 监听滑轮          $(window).scroll(function () {              // 文档高度              var doc_height = $(document).height();              // 窗口高度              var window_height = $(window).height();              // 滑轮高度              var scroll_height = $(window).scrollTop();              if (window_height + scroll_height == doc_height){                  initImg();              }          })                  </script>  </body>  </html>

settings 配置

TEMPLATES = [      {          'BACKEND': 'django.template.backends.django.DjangoTemplates',            # templates 设置          'DIRS': [os.path.join(BASE_DIR, 'templates')],          'APP_DIRS': True,          'OPTIONS': {              'context_processors': [                  'django.template.context_processors.debug',                  'django.template.context_processors.request',                  'django.contrib.auth.context_processors.auth',                  'django.contrib.messages.context_processors.messages',              ],          },      },  ]    LANGUAGE_CODE = 'zh-hans'    TIME_ZONE = 'Asia/Shanghai'    # 因为让模板能够找到 static 中图片,添加了 /app  STATIC_URL = '/app/static/'  STATICFILES_DIRS = (      os.path.join(BASE_DIR, 'app', 'static'),  )      TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'app', 'templates'),)

urlconf 配置

这是我的 app/urls.py

# Project/urls.py  from django.contrib import admin  from django.urls import path, include    urlpatterns = [      path('admin/', admin.site.urls),      path('app/', include('app.urls')),  ]    # app/urls.py  from django.urls import path  from app import views    urlpatterns = [      path('img/', views.img, name='img'),      path('getImgs/', views.getImgs, name='getImgs'),  ]

包管理模型

整个项目的模型部分,以包的形式管理,有些功能部分单独设计模型文件,因此要在包文件中导入相应模型。

编写 app/models/video/__init__.py

from app.models.video.img_models import Img

使用对象封装全局变量

在上面 JS 代码中,我们使用了全局变量,实际开发中应该尽量避免使用全局变量,在这里用对象将其封装。

// 全局变量封装  $(function () {      var obj = new ScrollImg();   // 定义一个对象      obj.fetchImg();               obj.scrollEvent();  });    // 对象 ScrollImg  function ScrollImg() {      // 将之前的全局变量封装在对象内部,仅其内部能使用      this.NID = 0;             this.LASTPOSITION = 3;        // 向后台发送 ajax 请求,获取图片信息      this.fetchImg = function () {          var that = this;          $.ajax({              url: '/app/getImgs/',              type: 'GET',              data: {nid: that.NID},              dataType: 'JSON',              success: function (arg) {                  var img_list = arg.data;                  $.each(img_list, function (index, value) {                      var n = (index + that.LASTPOSITION + 1) % 4;                      var img = document.createElement('img');                      img.src = '/' + value.src;                        $('#container').children().eq(n).append(img);                      if (index + 1 == img_list.length) {                          that.LASTPOSITION = n;                            // 每取完一次,便把最后那条的 id 赋值给 NID 传到后台,再根据这个条件取 7 条数据                          that.NID = value.id;                      }                  });              }          })      };        this.scrollEvent = function () {          var that = this;            // 监听滑轮,当滑轮高度+窗口高度==文档高度时,即表示滑轮已经滑动到最底部,再执行 fetchImg() 函数,再从数据库取出数据          $(window).scroll(function () {              var scroll_height = $(window).scrollTop();              var window_height = $(window).height();              var doc_height = $(document).height();              if (scroll_height + window_height == doc_height ) {                  that.fetchImg();              }          })      }  }

这是整个项目大致分布:

现在是 "图片为王"的时代,在浏览一些网站时,经常会看到类似于这种满屏都是图片。图片大小不一,却按空间排列,就这是瀑布流布局。

  • 以瀑布流形式布局,从数据库中取出图片
  • 每次取出等量(7 条)的图片,加载到页面
  • 当滑轮滚动到最底端时,自动再加载图片

实现流程

  • 以包形式管理模型
  • 将图片自动上传到静态文件 static
  • 前端页面每行排列四张图片(四个 div )
  • 当页面加载时,以 ajax 形式自动向后台发送请求,获取图片数据,再用 js 循环生成 img 标签添加到每个 div 中
  • JS 循环图片信息列表,将当前循环元素的索引与每行排列的图片数目(4张)求余数,再利用余数定位每个 div 标签

模型设计

在这里,我以包的形式管理模型 models,编写 app/models/video/img_models.py

from django.db import models      class Img(models.Model):      """      upload_to: 上传文件地址      """      src = models.FileField(max_length=64, verbose_name='图片地址', upload_to='app/static/app/upload')      title = models.CharField(max_length=64, verbose_name='标题')      summary = models.CharField(max_length=128, verbose_name='简介')        class Meta:          verbose_name_plural = '图片'        def __str__(self):          return self.title

视图函数

编写 app/views.py

from django.shortcuts import render  from django.http import JsonResponse  from app.models.video.img_models import Img      def img(request):        return render(request, 'app/img.html')      def getImgs(request):      nid = request.GET.get('nid')      print(nid)        # nid 第一次取为 0,每次取 7 条      last_position_id = int(nid) + 7      postion_id = str(last_position_id)        # 获取 0 < id < 7 的数据      img_list = Img.objects.filter(id__gt=nid, id__lt=postion_id).values('id', 'title', 'src')      img_list = list(img_list)   # 将字典格式转换为列表形式      ret = {          'status': True,          'data': img_list      }        return JsonResponse(ret)

在后台取出符合条件的数据,然后打包成 JSON 格式数据,前端模板再通过 jQuery 将其循环生成 img 标签,并添加到 div 标签中。

模板

编写 app/templates/app/img.html

{% load static %}  <!DOCTYPE html>  <html lang="en">  <head>      <meta charset="UTF-8">      <title>瀑布流</title>      <style type="text/css">          .box1{              width: 1000px;              margin: 0 auto;          }            .box1 .item{              width: 25%;              float: left;          }            .item img{              width: 100%;          }      </style>  </head>  <body>      <h1>瀑布流</h1>      <div class="box1" id="container">          <div class="item">            </div>            <div class="item">            </div>            <div class="item">            </div>            <div class="item">            </div>      </div>          <script src="{% static 'app/jquery/jquery-3.1.1.js' %}"></script>      <script>          $(function () {              initImg();              scroll();          });            NID = 0;          LASTPOSTION = 3;    // 循环最后那个的位置          function initImg() {              $.ajax({                  url: '/app/getImgs/',                  type: 'GET',                  data: {nid: NID},                  dataType: 'JSON',                  success: function (arg) {                      if (arg.status){                         var img_list = arg.data;                         $.each(img_list, function (index, value) {                            var n = (index + LASTPOSTION + 1) % 4;  {#                          console.log(n);    // 0、1 、2 、3    一直为 0、1 、2 、3#}                            var img = document.createElement('img');                            img.src = '/' + value.src;    //  app/static/app/upload/7.jpg                               // 也就是给第一、二、三、四给 div 添加 img 标签,eq(0) 为第一个                            $('#container').children().eq(n).append(img);                            if (index + 1 == img_list.length){                                console.log(n, value.id);                                LASTPOSTION = n;  {#                              NID = value.id;#}                            }                         });                      }                  }              })          }            // 监听滑轮          $(window).scroll(function () {              // 文档高度              var doc_height = $(document).height();              // 窗口高度              var window_height = $(window).height();              // 滑轮高度              var scroll_height = $(window).scrollTop();              if (window_height + scroll_height == doc_height){                  initImg();              }          })                  </script>  </body>  </html>

settings 配置

TEMPLATES = [      {          'BACKEND': 'django.template.backends.django.DjangoTemplates',            # templates 设置          'DIRS': [os.path.join(BASE_DIR, 'templates')],          'APP_DIRS': True,          'OPTIONS': {              'context_processors': [                  'django.template.context_processors.debug',                  'django.template.context_processors.request',                  'django.contrib.auth.context_processors.auth',                  'django.contrib.messages.context_processors.messages',              ],          },      },  ]    LANGUAGE_CODE = 'zh-hans'    TIME_ZONE = 'Asia/Shanghai'    # 因为让模板能够找到 static 中图片,添加了 /app  STATIC_URL = '/app/static/'  STATICFILES_DIRS = (      os.path.join(BASE_DIR, 'app', 'static'),  )      TEMPLATE_DIRS = (os.path.join(BASE_DIR, 'app', 'templates'),)

urlconf 配置

这是我的 app/urls.py

# Project/urls.py  from django.contrib import admin  from django.urls import path, include    urlpatterns = [      path('admin/', admin.site.urls),      path('app/', include('app.urls')),  ]    # app/urls.py  from django.urls import path  from app import views    urlpatterns = [      path('img/', views.img, name='img'),      path('getImgs/', views.getImgs, name='getImgs'),  ]

包管理模型

整个项目的模型部分,以包的形式管理,有些功能部分单独设计模型文件,因此要在包文件中导入相应模型。

编写 app/models/video/__init__.py

from app.models.video.img_models import Img

使用对象封装全局变量

在上面 JS 代码中,我们使用了全局变量,实际开发中应该尽量避免使用全局变量,在这里用对象将其封装。

// 全局变量封装  $(function () {      var obj = new ScrollImg();   // 定义一个对象      obj.fetchImg();               obj.scrollEvent();  });    // 对象 ScrollImg  function ScrollImg() {      // 将之前的全局变量封装在对象内部,仅其内部能使用      this.NID = 0;             this.LASTPOSITION = 3;        // 向后台发送 ajax 请求,获取图片信息      this.fetchImg = function () {          var that = this;          $.ajax({              url: '/app/getImgs/',              type: 'GET',              data: {nid: that.NID},              dataType: 'JSON',              success: function (arg) {                  var img_list = arg.data;                  $.each(img_list, function (index, value) {                      var n = (index + that.LASTPOSITION + 1) % 4;                      var img = document.createElement('img');                      img.src = '/' + value.src;                        $('#container').children().eq(n).append(img);                      if (index + 1 == img_list.length) {                          that.LASTPOSITION = n;                            // 每取完一次,便把最后那条的 id 赋值给 NID 传到后台,再根据这个条件取 7 条数据                          that.NID = value.id;                      }                  });              }          })      };        this.scrollEvent = function () {          var that = this;            // 监听滑轮,当滑轮高度+窗口高度==文档高度时,即表示滑轮已经滑动到最底部,再执行 fetchImg() 函数,再从数据库取出数据          $(window).scroll(function () {              var scroll_height = $(window).scrollTop();              var window_height = $(window).height();              var doc_height = $(document).height();              if (scroll_height + window_height == doc_height ) {                  that.fetchImg();              }          })      }  }

这是整个项目大致分布:

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!