美文网首页
后台管理站点 -- 5.轮播图管理

后台管理站点 -- 5.轮播图管理

作者: 爱修仙的道友 | 来源:发表于2019-03-13 20:21 被阅读0次

原理同 热门文章管理

  • views.py
class BannerManageView(PermissionRequiredMixin, View):
    permission_required = ('news.view_banner', )
    raise_exception = True

    def get(self, request):
        priority_dict = OrderedDict(models.Banner.PRI_CHOICES)
        banners = models.Banner.objects.only('image_url', 'priority').filter(is_delete=False)
        return render(request, 'admin/news/news_banner.html', locals())


class BannerEditView(PermissionRequiredMixin, View):
    permission_required = ('news.delete_banner', 'news.change_banner')
    raise_exception = True

    def handle_no_permission(self):
        if self.request.method.lower() != 'get':
            return to_json_data(errno=Code.ROLEERR, errmsg='没有操作权限')
        else:
            return super(BannerEditView, self).handle_no_permission()

    def delete(self, request, banner_id):
        banner = models.Banner.objects.only('id').filter(id=banner_id).first()
        if banner:
            banner.is_delete = True
            banner.save(update_fields=['is_delete'])
            return to_json_data(errmsg="轮播图删除成功")
        else:
            return to_json_data(errno=Code.PARAMERR, errmsg="需要删除的轮播图不存在")

    def put(self, request, banner_id):
        banner = models.Banner.objects.only('id').filter(id=banner_id).first()
        if not banner:
            return to_json_data(errno=Code.PARAMERR, errmsg="需要更新的轮播图不存在")

        json_data = request.body
        if not json_data:
            return to_json_data(errno=Code.PARAMERR, errmsg=error_map[Code.PARAMERR])
        # 将json转化为dict
        dict_data = json.loads(json_data.decode('utf8'))

        try:
            priority = int(dict_data.get('priority'))
            priority_list = [i for i, _ in models.Banner.PRI_CHOICES]
            if priority not in priority_list:
                return to_json_data(errno=Code.PARAMERR, errmsg='轮播图的优先级设置错误')
        except Exception as e:
            logger.info('轮播图优先级异常:\n{}'.format(e))
            return to_json_data(errno=Code.PARAMERR, errmsg='轮播图的优先级设置错误')

        image_url = dict_data.get('image_url')
        if not image_url:
            return to_json_data(errno=Code.PARAMERR, errmsg='轮播图url为空')

        if banner.priority == priority and banner.image_url == image_url:
            return to_json_data(errno=Code.PARAMERR, errmsg="轮播图的参数未改变")

        banner.priority = priority
        banner.image_url = image_url
        banner.save(update_fields=['priority', 'image_url'])
        return to_json_data(errmsg="轮播图更新成功")


class BannerAddView(PermissionRequiredMixin, View):
    permission_required = ('news.delete_banner', 'news.change_banner', 'news.view_banner')
    raise_exception = True

    def handle_no_permission(self):
        if self.request.method.lower() != 'get':
            return to_json_data(errno=Code.ROLEERR, errmsg='没有操作权限')
        else:
            return super(BannerAddView, self).handle_no_permission()

    def get(self, request):
        tags = models.Tag.objects.values('id', 'name').annotate(num_news=Count('news')). \
            filter(is_delete=False).order_by('-num_news', 'update_time')
        # 优先级列表
        # priority_list = {K: v for k, v in models.Banner.PRI_CHOICES}
        priority_dict = OrderedDict(models.Banner.PRI_CHOICES)

        return render(request, 'admin/news/news_banner_add.html', locals())

    def post(self, request):
        json_data = request.body
        if not json_data:
            return to_json_data(errno=Code.PARAMERR, errmsg=error_map[Code.PARAMERR])
        # 将json转化为dict
        dict_data = json.loads(json_data.decode('utf8'))

        try:
            news_id = int(dict_data.get('news_id'))
        except Exception as e:
            logger.info('前端传过来的文章id参数异常:\n{}'.format(e))
            return to_json_data(errno=Code.PARAMERR, errmsg='参数错误')

        if not models.News.objects.filter(id=news_id).exists():
            return to_json_data(errno=Code.PARAMERR, errmsg='文章不存在')

        try:
            priority = int(dict_data.get('priority'))
            priority_list = [i for i, _ in models.Banner.PRI_CHOICES]
            if priority not in priority_list:
                return to_json_data(errno=Code.PARAMERR, errmsg='轮播图的优先级设置错误')
        except Exception as e:
            logger.info('轮播图优先级异常:\n{}'.format(e))
            return to_json_data(errno=Code.PARAMERR, errmsg='轮播图的优先级设置错误')

        # 获取轮播图url
        image_url = dict_data.get('image_url')
        if not image_url:
            return to_json_data(errno=Code.PARAMERR, errmsg='轮播图url为空')

        # 创建轮播图
        banners_tuple = models.Banner.objects.get_or_create(news_id=news_id)
        banner, is_created = banners_tuple

        banner.priority = priority
        banner.image_url = image_url
        banner.save(update_fields=['priority', 'image_url'])
        return to_json_data(errmsg="轮播图创建成功")
  • urls.py
    path('banners/', views.BannerManageView.as_view(), name='banners_manage'),
    path('banners/<int:banner_id>/', views.BannerEditView.as_view(), name='banners_edit'),
    path('banners/add/', views.BannerAddView.as_view(), name='banners_add'),
  • html.py
<!-- 创建templates/admin/news/news_banner.html文件 -->

{% extends 'admin/base/base.html' %}

{% block title %}
  添加 banner
{% endblock %}

{% block content_header %}
  添加 banner
{% endblock %}

{% block header_option_desc %}
  添加 banner
{% endblock %}


{% block content %}
  <style>
    .banner-img {
      width: 328px;
      height: 82px;
    }

    .banner-img img {
      width: 100%;
      max-height: 100%;
    }

    .banner-info {
      margin-left: 20px;
    }

    .form-group {
      width: 500px;
    }
    ul.banner-list{
      list-style:none;
      margin:0;
      padding:0;
    }
    ul.banner-list li.banner-item{
      margin-top: 20px;
    }
    @media screen and (max-width: 1100px) {
      .form-group {
        margin-top: 15px;
      }

      .banner-info {
        margin: 0;
      }
    }
  </style>
  <div class="row">
    <div class="col-lg-6">
      <button class="btn btn-primary pull-left" id="banner-add-btn"><i class="fa fa-plus"></i> 添加轮播图</button>
      <ul class="pull-left tips" style="line-height: 18px;">
        <li>支持 JPG/PNG 格式的图片 最多可上传6张</li>
        <li>图片的宽度最好在800px以上,比例为4:1</li>
      </ul>
    </div>
  </div>
  <ul class="banner-list">

    {% for one_banner in banners %}

      <li class="box banner-item box-primary" data-banner-id="{{ one_banner.id }}">
        <div class="box-header">
          <span>当前优先级为:<span class="priority-number">{{ one_banner.priority }}</span></span>
          <a href="javascript:void(0);" class="btn btn-danger btn-xs pull-right close-btn">
            <i class="fa fa-close"></i>
          </a>
        </div>
        <div class="box-body">
          <div class="pull-left banner-img">
            <input type="file" name="banner-image-select" style="display: none;">
            <img src="{{ one_banner.image_url }}" class="img-thumbnail banner-image">
          </div>
          <div class="pull-left banner-info">

            <div class="form-group">
              <label for="priority" class="control-label" style="margin-bottom: 10px">选择优先级(第一级最高):</label>
              <div>

                <select name="priority" id="priority" class="form-control">
                  <option value="0">--请选择优先级--</option>

                  {% for id, value in priority_dict.items %}

                    {% if id == one_banner.priority %}
                      <option value="{{ id }}" selected>{{ value }}</option>
                    {% else %}
                      <option value="{{ id }}">{{ value }}</option>
                    {% endif %}

                  {% endfor %}

                </select>

              </div>
            </div>

          </div>
        </div>
        <div class="box-footer">
          <button class="btn btn-primary pull-right update-btn" data-image-url="{{ one_banner.image_url }}"
                  data-priority="{{ one_banner.priority }}">更新
          </button>
        </div>
      </li>

    {% endfor %}

  </ul>
{% endblock %}

{% block script %}
  <script src="/static/js/admin/news/news_banner.js"></script>
{% endblock %}

// 创建static/js/admin/news/news_banner.js文件

$(function () {
  let $closeBtn = $('.close-btn');  // 删除轮播图按钮
  let $bannerList = $(".banner-list");
  let $updateBtn = $(".update-btn");  // 保存按钮
  let $bannerAddBtn = $("#banner-add-btn");  // 添加轮播图按钮

  let $bannerImage = $(".banner-image");  // 获取图片元素
  let $bannerImageSelect = $('input[name=banner-image-select]');  // image input元素

  // 删除轮播图
  $closeBtn.click(function () {
    let _this = this;
    let sBannerId = $(this).parents('li').data("banner-id");
    fAlert.alertConfirm({
      "title": "删除轮播图",
      "type": "error",
      "confirmText": "确认",
      "confirmCallback": function () {

        $.ajax({
          // 请求地址
          url: "/admin/banners/" + sBannerId + "/",  // url尾部需要添加/
          // 请求方式
          type: "DELETE",
          dataType: "json",
        })
          .done(function (res) {
            if (res.errno === "200") {
              message.showSuccess("标签删除成功");
              $(_this).parents('li').remove();
            } else {
              message.showError(res.errmsg);
            }
          })
          .fail(function () {
            message.showError('服务器超时,请重试!');
          });

      }

    })
  });


  // 更新轮播图
  $updateBtn.click(function () {
    // let _this = this;
    let imageUrl = $(this).parents('li').find('.banner-image').attr("src");
    let priority = $(this).parents('li').find('#priority').val();
    let bannerId = $(this).parents('li').data("banner-id");

    // 未更新之前的原始值
    let sSrcPriority = $(this).data('priority');  // 未更新之前的优先级
    let sImageUrl = $(this).data('image-url');    // 未更新之前的图片url
    if (!imageUrl) {
      message.showError('轮播图url为空');
      return
    }

    if (priority == sSrcPriority && imageUrl === sImageUrl) {
      message.showError('未修改任何值');
      return
    }

    let sDataParams = {
      "image_url": imageUrl,
      "priority": priority,
      "banner_id": bannerId
    };


    $.ajax({
      // 请求地址
      url: "/admin/banners/" + bannerId + "/",  // url尾部需要添加/
      // 请求方式
      type: "PUT",
      data: JSON.stringify(sDataParams),
      // 请求内容的数据类型(前端发给后端的格式)
      contentType: "application/json; charset=utf-8",
      // 响应数据的格式(后端返回给前端的格式)
      dataType: "json",
    })
      .done(function (res) {
        if (res.errno === "200") {
          message.showSuccess("更新成功");
          // fAlert.alertSuccessToast("更新成功");

          setTimeout(function () {
            window.location.href = '/admin/banners/';
          }, 900)
        } else {
          swal.showInputError(res.errmsg);
        }
      })

      .fail(function () {
        message.showError('服务器超时,请重试!');
      });

  });


  // 上传轮播图片
  $bannerImage.click(function () {
    $(this).prev().click();
  });
  $bannerImageSelect.change(function () {
    let _this = this;
    // 获取文件对象
    let file = this.files[0];   // 获取文件
    let oFormData = new FormData();  // 创建一个 FormData
    oFormData.append("image_file", file); // 把文件添加进去
    // 发送请求
    $.ajax({
      url: "/admin/news/images/",
      method: "POST",
      data: oFormData,
      processData: false,   // 定义文件的传输
      contentType: false,
    })
      .done(function (res) {
        if (res.errno === "200") {
          let sImageUrl = res["data"]["image_url"];
          $(_this).next().attr('src', sImageUrl);
        } else {
          message.showError(res.errmsg)
        }
      })
      .fail(function () {
        message.showError('服务器超时,请重试!');
      });

  });


  // 添加轮播图
  $bannerAddBtn.click(function () {
    if ($bannerList.find('li').length < 6) {
      window.location.href = '/admin/banners/add/';
    } else {
      message.showError("最多只能添加6个轮播图")
    }
  });
    // get cookie using jQuery
  function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
      let cookies = document.cookie.split(';');
      for (let i = 0; i < cookies.length; i++) {
        let cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) === (name + '=')) {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  }

  function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  }

  // Setting the token on the AJAX request
  $.ajaxSetup({
    beforeSend: function (xhr, settings) {
      if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
      }
    }
  });


});
<!-- 创建templates/admin/news/news_banner_add.html文件 -->

{% extends 'admin/base/base.html' %}

{% block title %}
  添加轮播图
{% endblock %}

{% block content_header %}
  添加轮播图
{% endblock %}

{% block header_option_desc %}
  添加轮播图
{% endblock %}


{% block content %}
  <style>
    .banner-img {
      width: 40%;
      margin: 10px 300px 20px;
    }

    .banner-img img {
      width: 100%;
      max-height: 100%;
    }

    @media screen and (max-width: 1100px) {
      .form-group {
        margin-top: 15px;
      }
    }
  </style>

  <div class="box box-primary">
    <div class="box-body">
      <div class="form-horizontal">

        <div class="form-group">
          <div class="pull-left banner-img">
            <input type="file" name="banner-image-select" style="display: none;">
            <img src="" class="img-thumbnail banner-image">
          </div>
        </div>

        <div class="form-group">
          <label for="category-select" class="col-md-2 col-sm-2 control-label">选择文章分类</label>
          <div class="col-md-2 col-sm-3">
            <select name="category" id="category-select" class="form-control input-md">
              <option value="0">--请选择文章分类--</option>

              {% for one_tag in tags %}
                <option value="{{ one_tag.id }}">{{ one_tag.name }}</option>
              {% endfor %}

            </select>
          </div>
          <div class="col-md-8 col-sm-7">
            <label for="news-select" style="display: none;"></label>
            <select name="news" class="form-control input-md" id="news-select">
              <option value="0">--请选择文章--</option>
            </select>
          </div>
        </div>
        <div class="form-group">
          <label for="priority" class="col-md-2 col-sm-2 control-label">选择优先级</label>

          <div class="col-md-2 col-sm-3">
            <select name="priority" id="priority" class="form-control input-md">
              <option value="0">--请选择优先级--</option>

              {% for id, value in priority_dict.items %}
                <option value="{{ id }}">{{ value }}</option>
              {% endfor %}

            </select>

          </div>
        </div>

      </div>
      <div class="box-footer">
        <a href="javascript:void(0);" class="btn btn-primary pull-right" id="save-btn">保存</a>
      </div>
    </div>
  </div>
{% endblock %}


{% block script %}
  <script src="/static/js/admin/news/news_banner_add.js"></script>
{% endblock %}

// 创建static/js/admin/news/news_banner_add.js文件

$(function () {
  let $tagSelect = $("#category-select");   // 获取选择分类标签元素
  let $newsSelect = $("#news-select");      // 获取选择文章标签元素
  let $saveBtn = $('#save-btn');            // 获取保存按钮元素
  let $bannerImage = $(".banner-image");  // 获取图片元素
  let $bannerImageSelect = $('input[name=banner-image-select]');  // image input元素

  // 上传轮播图片
  $bannerImage.click(function () {
    $(this).prev().click();
  });
  $bannerImageSelect.change(function () {
    let _this = this;
    // 获取文件对象
    let file = this.files[0];   // 获取文件
    let oFormData = new FormData();  // 创建一个 FormData
    oFormData.append("image_file", file); // 把文件添加进去
    // 发送请求
    $.ajax({
      url: "/admin/news/images/",
      method: "POST",
      data: oFormData,
      processData: false,   // 定义文件的传输
      contentType: false,
    })
      .done(function (res) {
        if (res.errno === "200") {
          let sImageUrl = res["data"]["image_url"];
          $(_this).next().attr('src', sImageUrl);
        } else {
          message.showError(res.errmsg)
        }
      })
      .fail(function () {
        message.showError('服务器超时,请重试!');
      });

  });


  // 选择文章不同类别,获取相应的文章
  $tagSelect.change(function () {
    // 获取当前选中的下拉框的value
    let sTagId = $(this).val();
    if (sTagId === '0') {
      $newsSelect.children('option').remove();
      $newsSelect.append(`<option value="0">--请选择文章--</option>`);
      return
    }
    // 根据文章分类id向后端发起get请求
    $.ajax({
      // 请求地址
      url: "/admin/tags/" + sTagId + "/news/",  // url尾部需要添加/
      // 请求方式
      type: "GET",
      dataType: "json",
    })
      .done(function (res) {
        if (res.errno === "200") {

          $newsSelect.children('option').remove();
          $newsSelect.append(`<option value="0">--请选择文章--</option>`);
          res.data.news.forEach(function (one_news) {
            let content = `<option value="${one_news.id}">${one_news.title}</option>`;
            $newsSelect.append(content)
          });

        } else {
          // swal.showInputError(res.errmsg);
          fAlert.alertErrorToast(res.errmsg);
        }
      })
      .fail(function () {
        message.showError('服务器超时,请重试!');
      });

  });

  // 点击保存按钮执行的事件
  $saveBtn.click(function () {
    let priority = $("#priority").val();  // 获取优先级
    // 获取下拉框中选中的文章标签id 和 文章id
    let sTagId = $tagSelect.val();
    let sNewsId = $newsSelect.val();
    let sImageUrl = $bannerImage.attr('src');
    // 打印值
    console.log(`
          priority(优先级): ${priority}
          tagsTagId(文章标签id): ${sTagId}
          sNewsId(文章id): ${sNewsId}
          sImageUrl(轮播图url): ${sImageUrl}
    `);

    if (sImageUrl === '/static/images/banner_default.png') {
      message.showError('轮播图不能为默认图片');
      return
    }

    // 判断是否为 0, 表示在第一个 未选择
    if (sTagId !== '0' && sNewsId !== '0' && priority !== '0' && sImageUrl) {

      let sDataParams = {
        "priority": priority,
        "news_id": sNewsId,
        "image_url": sImageUrl
      };

      $.ajax({
        // 请求地址
        url: "/admin/banners/add/",  // url尾部需要添加/
        // 请求方式
        type: "POST",
        data: JSON.stringify(sDataParams),
        // 请求内容的数据类型(前端发给后端的格式)
        contentType: "application/json; charset=utf-8",
        // 响应数据的格式(后端返回给前端的格式)
        dataType: "json",
      })
        .done(function (res) {
          if (res.errno === "200") {
            message.showSuccess("轮播图创建成功");

            setTimeout(function () {
              window.location.href = '/admin/banners/';
            }, 800)
          } else {
            message.showError(res.errmsg);
          }
        })

        .fail(function () {
          message.showError('服务器超时,请重试!');
        });

    } else {
      message.showError("文章分类、文章以及优先级都要选!");
    }
  });
    // get cookie using jQuery
  function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
      let cookies = document.cookie.split(';');
      for (let i = 0; i < cookies.length; i++) {
        let cookie = jQuery.trim(cookies[i]);
        // Does this cookie string begin with the name we want?
        if (cookie.substring(0, name.length + 1) === (name + '=')) {
          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
          break;
        }
      }
    }
    return cookieValue;
  }

  function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
  }

  // Setting the token on the AJAX request
  $.ajaxSetup({
    beforeSend: function (xhr, settings) {
      if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
        xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
      }
    }
  });


});

相关文章

网友评论

      本文标题:后台管理站点 -- 5.轮播图管理

      本文链接:https://www.haomeiwen.com/subject/pltxmqtx.html