紧锣密鼓完成小闭环,微型 CSDN 项目快快进入下一阶段

Posted 梦想橡皮擦

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了紧锣密鼓完成小闭环,微型 CSDN 项目快快进入下一阶段相关的知识,希望对你有一定的参考价值。

橡皮擦,一个逗趣的互联网高级网虫。新的系列,让我们一起进入 Django 世界。

二十二、导航菜单的增删改查

学习任何编程语言,都要先小碎步快快跑,等到积累足够,就直接奔上一个大山头。

本篇博客要把导航菜单部分进行收尾,上篇已经对导航菜单的增加进行了实现,也同步完成了查询列表功能,不过该页面呈现比较简单,并没有实现分页操作,关于分页部分,在后续的内容进行编写,本文优先实现对导航菜单的编辑与删除。

22.1 路由编写

对于 Django 的 MVT 模式,很多人都有自己的编写习惯,橡皮擦习惯性的从路由开始进行编写。

修改 navbar/urls.py 文件代码。

from django.urls import path
from . import views

urlpatterns = [
    path('add/', views.NavItemCreateView.as_view(), name='navbar-add'),
    path('list/', views.NavItemListView.as_view(), name='navbar-list'),
    path('<int:pk>/update', views.NavItemUpdateView.as_view(), name='navbar-update'),
    path('<int:pk>/delete', views.NavItemDeleteView.as_view(), name='navbar-delete')
]

在上述代码中,新配置了更新与删除的路由,并分别指定了 views.py 中的具体类名。

22.2 补齐 views.py 中的类

修改 views.py 文件,重点补齐路由中调用的类,完整代码如下,NavItemUpdateViewNavItemDeleteView 为新增类代码。

from django.shortcuts import render
from django.views.generic import CreateView, ListView,UpdateView,DeleteView
from utils.mixins import AjaxResponseMixin
from .models import NavItem
from django.http import JsonResponse
from django.urls import reverse, reverse_lazy


# Create your views here.
class NavItemCreateView(AjaxResponseMixin, CreateView):
    model = NavItem
    fields = ["title", "order", "url"]
    template_name_suffix = '_add'
    success_url = "/navbar/list"


class NavItemListView(ListView):
    model = NavItem
    context_object_name = 'navbar_list'

# 更新
class NavItemUpdateView(AjaxResponseMixin,UpdateView):
    model = NavItem
    fields = ["title", "order", "url"]
    context_object_name = "navitem"
    template_name_suffix = "_edit"
    success_url = "/navbar/list"

# 删除
class NavItemDeleteView(AjaxResponseMixin, DeleteView):
    model = NavItem
	success_url = "/navbar/list"
    def delete(self, request, *args, **kwargs):
        super(NavItemDeleteView,self).delete(request,*args,**kwargs)
        return JsonResponse({
            "state":"success"
        })

22.3 补齐编辑逻辑

实现更新页面模板,由过往代码知道模板页面的名称应该为 navitem_edit.html,在该文件中模仿新增页面编写出更新页面。
该页面需要对数据进行回显展示,例如 value="{{navitem.url}}" ,其中 navitemviews.py 文件中通过设置 context_object_name 而来。

{% extends 'csdn/backend/backend_common.html' %} 
{% block option-title%}导航菜单编辑{%endblock%} 
{% block content%}

<div class="col-md-12">
  <form class="form-horizontal" id="data-form">
    {% csrf_token %} 
    <div class="form-group">
      <label for="title" class="col-sm-2 control-label">标题:</label>
      <div class="col-sm-10">
        <input
          type="text"
          class="form-control"
          id="title"
          name="title"
          placeholder="请输入标题"
          value="{{navitem.title}}"
        />
      </div>
    </div>
    <div class="form-group">
      <label for="url" class="col-sm-2 control-label">链接</label>
      <div class="col-sm-10">
        <input
          type="text"
          class="form-control"
          id="url"
          name="url"
          placeholder="请输入链接"
          value="{{navitem.url}}"
        />
      </div>
    </div>
    <div class="form-group">
      <label for="order" class="col-sm-2 control-label">顺序</label>
      <div class="col-sm-10">
        <input
          type="text"
          class="form-control"
          id="order"
          name="order"
          placeholder="请输入顺序"
          value="{{navitem.order}}"
        />
      </div>
    </div>
    <div class="form-group">
      <div class="col-sm-offset-2 col-sm-10">
        <button class="btn btn-info" id="btn-submit">更新</button>
      </div>
    </div>
  </form>
</div>
{% endblock %} {% block ext_js %}
<script type="text/javascript">
  $('#btn-submit').click(function(e){
      e.preventDefault();
      $.post('{% url 'navbar-update' navitem.pk %}',$("#data-form").serializeArray(),function(data){
          var state = data.state;
          if(state == "success"){
              alert("编辑成功")
              location.href = "/navbar/list"
          }
     },"json")
  })
</script>

{% endblock %}

其中服务器,依据路由访问 http://127.0.0.1:8000/navbar/1/update 进入编辑页面,注意中间的主键ID 1 可以切换为其它数值,每个数值都对应一条数据。

在列表页面实现编辑页面跳转,点击按钮跳转该数据的编辑页面。

<td>
  <a href="{% url 'navbar-update' item.pk %}" class="btn btn-primary" role="button">编辑</a>
  <button class="btn btn-danger" role="button">删除</button>
</td>

22.4 补齐删除逻辑

删除操作也在列表页实现,在每个删除按钮上都绑定记录的主键。

<button class="btn btn-danger" role="button" data-id="{{item.id}}">删除</button>

增加删除操作的 JS 代码如下:

{% block ext_js %}
<script type="text/javascript">
  $(".btn-danger").click(function () {
    var dom_item = this;
    $.post(
      '{% url "navbar-delete" 00 %}'.replace("0", this.dataset["id"]),
      {},
      function (data) {
        var state = data.state;
        if (state === "success") {
          dom_item.parentElement.parentElement.setAttribute("hidden", "");
          alert("删除成功!");
        }
      }
    );
  });
</script>
{% endblock %}

此时如果进行删除操作,会出现如下错误,该错误为 CSRF 验证失败,在新增与更新操作的时候,我们都是通过在 form 表单中增加 {% csrf_token %} 实现该验证,但删除操作是在列表中实现的,无法像表单一样增加 {% csrf_token %} ,故需要调整本部分逻辑代码。

Forbidden (403)
CSRF verification failed. Request aborted.

templates/csdn/common.html 中增加 CSRF 验证逻辑。

<script type="text/javascript">
  var csrftoken = $.cookie("csrftoken");
  function csrfSafeMethod(method) {
    return /^(GET|HEAD|OPTIONS|TRACE)$/.test(method);
  }
  $.ajaxSetup({
    beforeSend: function (xhr, settings) {
      if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
        xhr.setRequestHeader("X-CSRFToken", csrftoken);
      }
    },
  });
</script>

然后去除新增与更新页面 {% csrf_token %} ,重新测试效果,查看是否正常运行。

22.5 补齐后台管理功能

页面添加完毕之后,可以在后台通用框架中新增相关功能。

templates/navbar 文件夹中新增 navbar_link.html 文件 ,编写代码:

<ul class="nav nav-sidebar">
  <li id="navbar-list">
    <a href="{% url 'navbar-list'%}">导航菜单列表</a>
  </li>
  <li id="navbar-add">
    <a href="{% url 'navbar-add'%}">导航菜单添加</a>
  </li>
</ul>

打开 templates/csdn/backend/nav.html 文件,引入 navbar_link.html 文件。

<ul class="nav nav-sidebar">
  <li id="overview">
    <a href="#">工作台</a>
  </li>
</ul>
{% include 'navbar/navbar_link.html' %}

最后在 bacnend.html 文件中导入导航菜单模板。

{% block body %}
<nav class="navbar nav-inverse">
  <div class="contain-fluid">
    <div class="navbar-header">
      <a href="#" class="navbar-brand">后台管理</a>
    </div>
  </div>
</nav>
<div class="container-fluid">
  <div class="row">
    <div class="col-md-2 sidebar">{% include 'csdn/backend/nav.html' %}</div>
    <div class="col-md-10 main">
      <h1 class="page-header">{% block option-title%}{%endblock%}</h1>
      <div class="row placeholders">{% block content%}{%endblock%}</div>
    </div>
  </div>
</div>

{% endblock %}

最终呈现的效果如下:

紧锣密鼓完成小闭环,微型 CSDN 项目快快进入下一阶段

21.6 本篇博客小节

本小节完成了导航的增删改查,并且在后台新增了列表与新增的入口,页面美观度部分非本系列重点知识,所以先实现效果吧。

本文章属于《滚雪球学 Python 第三轮》中的一篇,欢迎继续关注。

今天是持续写作的第 148 / 200 天。可以点赞、评论、收藏啦。

继续阅读

  1. 国内,首套,成体系,技术博客写作专栏发布啦
  2. 学弟学妹:大佬们,别劝了,学不动了,学不动了
  3. 自己动手写个微型 CSDN 吧,还能实现网页版 Blink,No.1

本文长尾关键词,提供给机器使用,阅读请忽略
django api django redis django bootstrap
topview django flask django cms
django3 pycharm django django 开源

以上是关于紧锣密鼓完成小闭环,微型 CSDN 项目快快进入下一阶段的主要内容,如果未能解决你的问题,请参考以下文章

课程章节更新突破 没有支付权限的小程序 完成支付闭环

PDF转换成图片的小技巧,快快收藏

团队项目-项目进度

紧锣密鼓!yarnexpo纱线展“云展小程序”使用说明书来了

大咖对话丨文旅夜游项目如何以运营前置为导向,实现商业模式闭环

Beta实际开发与初始计划的比较