橡皮擦,一个逗趣的互联网高级网虫。新的系列,让我们一起进入 Django 世界。
二十二、导航菜单的增删改查
学习任何编程语言,都要先小碎步快快跑,等到积累足够,就直接奔上一个大山头。
本篇博客要把导航菜单部分进行收尾,上篇已经对导航菜单的增加进行了实现,也同步完成了查询列表功能,不过该页面呈现比较简单,并没有实现分页操作,关于分页部分,在后续的内容进行编写,本文优先实现对导航菜单的编辑与删除。
22.1 路由编写
对于 Django 的 MVT 模式,很多人都有自己的编写习惯,橡皮擦习惯性的从路由开始进行编写。
修改 navbar/urls.py 文件代码。
from django.urls import pathfrom . 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 文件,重点补齐路由中调用的类,完整代码如下,NavItemUpdateView 与 NavItemDeleteView 为新增类代码。
from django.shortcuts import renderfrom django.views.generic import CreateView, ListView,UpdateView,DeleteViewfrom utils.mixins import AjaxResponseMixinfrom .models import NavItemfrom django.http import JsonResponsefrom 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}}" ,其中 navitem 在 views.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 %}
复制代码
最终呈现的效果如下:
21.6 本篇博客小节
本小节完成了导航的增删改查,并且在后台新增了列表与新增的入口,页面美观度部分非本系列重点知识,所以先实现效果吧。
评论