zoukankan      html  css  js  c++  java
  • 项目一:CRM(客户关系管理系统)--8--删除页面

    添加、修改页面都已经搞定,就差删除功能啦!删除这里就比较麻烦了,麻烦在那些表之间的关系。

    1. 添加删除功能

    1.1 删除页面路由

    为用户的良好体验,我们新增加一个删除显示页面,路由:

    1 urlpatterns = [
    2     url(r'^$', views.index, name='table_index'),
    3     url(r'^(w+)/(w+)/$', views.display_objects, name='display_objects'),
    4     url(r'^(w+)/(w+)/(d+)/edit/$', views.table_object_edit,name="table_object_edit"),
    5     url(r'^(w+)/(w+)/add/$', views.table_object_add,name="table_object_add"),
    6     url(r'^(w+)/(w+)/(d+)/delete/$', views.table_object_delete,name="table_object_delete"),#删除路由
    7 ]

    1.2 添加删除页面模板

    templates/king_admin目录下新建table_object_delete.html文件,内容如下:

     1 {% extends 'king_admin/table_index.html' %}
     2  
     3 {% block body-content %}
     4  
     5     {# 表单提交  #}
     6     <form method="post">
     7         {% csrf_token %}
     8         <input type="submit" class="btn btn-danger" value="Yes,I'm sure">
     9         <input class="hidden" value="yes" name="delete_confirm">
    10         <a class="btn btn-info" href="{% url 'king_admin:table_object_edit' app_name table_name object_id %}">No,Take me back</a>
    11     </form>
    12 {% endblock %}

    1.3 视图函数

     1 def table_object_delete(request, app_name, table_name, object_id):
     2     admin_class = site.enabled_admins[app_name][table_name]
     3  
     4     object_list = admin_class.model.objects.filter(id=object_id)
     5     if request.method == 'POST':
     6         if request.POST.get('delete_confirm') == 'yes':
     7             object_list.delete()
     8             return redirect('/king_admin/{app_name}/{table_name}'.format(app_name=app_name, table_name=table_name))
     9  
    10  
    11     return render(request, 'king_admin/table_object_delete.html', {'app_name': app_name,
    12                                                                    'table_name': table_name,
    13                                                                    'object_id': object_id,
    14                                                                    'object_list': object_list})

    1.4 为删除页面添加入口

    table_object_edit.html文件中,只需要添加一个按钮,但是这个按钮很是关键 ,要经过一些特别的处理,避免一些不必要的问题发生。

     1 ...
     2  
     3         {% endfor %}
     4     {# 添加保存按钮 #}
     5      <div class="form-group">
     6          {# 添加删除功能,并独立出来,以免影响其他功能 #}
     7          {% block obj_delete %}
     8           <div class="col-sm-2">
     9                 <a class="btn btn-danger" href="{% url 'king_admin:table_object_delete' app_name table_name object_id %}">删除</a>
    10           </div>
    11           {% endblock %}
    12           <div class="col-sm-10 ">
    13             <button type="submit" class="btn btn-success pull-right">保存</button>
    14           </div>
    15       </div>
    16     </form>
    17  
    18 ...

    还记得,我们的添加功能是继承自编辑页面吧,那里同样也要加上继承标签,以免二者出现一些关联错误。

    table_object_add.html页面添加一个块标签即可,且不加任何内容:

    1 ...
    2 
    3 {% block obj_delete %}
    4 
    5 {% endblock %}

    渲染后的效果:

    删除后跳转到显示页面的功能在视图函数中已经写好,不在赘述,和之前的编辑页面添加跳转是类似的。

    2. 添加映射关系显示

    上面我们完成了删除的基本功能,但是在Djangoadmin中还额外的显示了表与表之间的关系,这里我们同样来实现这个功能。在实现之前,我们需要先搞清楚一些关系。

    在这里我将关联关系分为三大类:主动关联、被动关联与特殊关联。

    • 主动关联和被动关联都包含特殊关联。

    • 主动关联
      在当前表中有ForeignKey或者OneToOne关键字段,主动去关联其他表的方式为主动关联

    • 被动关联
      当前表中有ForeignKey或者OneToOne或者没有其中的任何一个,但是其他表通过ForeignKey或者OneToOne关联到该表的方式为被动关联。

    • 特殊关联
      当前表中有ManyToMany关联其他表格,或其他表中有 ManyToMany关联到该表,或有第三张额外的表中包括两个ForeignKey,将两个表关联起来的方式为特殊关联。

    这里只是本人自己区分的一种方式!

    这里的删除功能需要的是被动关联和特殊关联的关系显示。

    2.1 shell中查询关系

    这里以Customer表和UserProfile表为例:

     1 >>> python  manage.py  shell
     2 
     3 >>> from  CRM import  models
     4 >>> a = models.Customer
     5 >>> a
     6 <class 'CRM.models.Customer'>
     7 >>> a._meta
     8 <Options for Customer>
     9 >>> a._meta.get_fields(include_hidden=True)
    10 (<ManyToOneRel: CRM.customer_tags>, <ManyToOneRel: CRM.customerfollowup>, <ManyToOneRel: CRM.enrollment>, <ManyToOneRel: CRM.payment>, <django.db.models.fields.AutoField: id>, <djan
    11 go.db.models.fields.CharField: name>, <django.db.models.fields.CharField: qq>, <django.db.models.fields.CharField: qq_name>, <django.db.models.fields.CharField: phone>, <django.db.m
    12 odels.fields.SmallIntegerField: source>, <django.db.models.fields.CharField: referral_from>, <django.db.models.fields.related.ForeignKey: consult_course>, <django.db.models.fields.T
    13 extField: content>, <django.db.models.fields.SmallIntegerField: status>, <django.db.models.fields.related.ForeignKey: consultant>, <django.db.models.fields.TextField: memo>, <django
    14 .db.models.fields.DateTimeField: date>, <django.db.models.fields.related.ManyToManyField: tags>)

    上面我们能看到所有的字段信息,我们想看的信息如下:

     1 #被动关联
     2 <ManyToOneRel: CRM.customer_tags>
     3 <ManyToOneRel: CRM.customerfollowup>
     4 <ManyToOneRel: CRM.enrollment>
     5 <ManyToOneRel: CRM.payment>
     6 #主动关联
     7 <django.db.models.fields.related.ForeignKey: consult_course>
     8 <django.db.models.fields.related.ForeignKey: consultant>
     9 <django.db.models.fields.related.ManyToManyField: tags>
    10 #特殊关联
    11 <django.db.models.fields.related.ManyToManyField: tags>

    我们需要找到的就是被动关联与特殊关联,其中特殊关联的另外一种形式,我们可以看看UserProfile表:

    1 >>> c = models.UserProfile
    2 >>> c._meta.get_fields(include_hidden=True)
    3 (<ManyToOneRel: CRM.customer>, <ManyToOneRel: CRM.customerfollowup>, <ManyToOneRel: CRM.classlist_teachers>, <ManyToManyRel: CRM.classlist>, <ManyToOneRel: CRM.courserecord>, <ManyT
    4 oOneRel: CRM.enrollment>, <ManyToOneRel: CRM.payment>, <ManyToOneRel: CRM.userprofile_roles>, <django.db.models.fields.AutoField: id>, <django.db.models.fields.related.OneToOneField
    5 : user>, <django.db.models.fields.CharField: name>, <django.db.models.fields.related.ManyToManyField: roles>)

    提取需要的信息如下:

     1 #被动关联
     2 <ManyToOneRel: CRM.customer>
     3 <ManyToOneRel: CRM.customerfollowup>
     4 <ManyToOneRel: CRM.classlist_teachers> 
     5 <ManyToManyRel: CRM.classlist> 
     6 <ManyToOneRel: CRM.courserecord> 
     7 <ManyToOneRel: CRM.enrollment>
     8 <ManyToOneRel: CRM.payment>
     9 <ManyToOneRel: CRM.userprofile_roles>
    10 #主动关联
    11 <django.db.models.fields.related.OneToOneField: user>
    12 <django.db.models.fields.related.ManyToManyField: roles>
    13 #特殊关联
    14 <ManyToManyRel: CRM.classlist> 

    上面两个表,为我们展示了几种关联的基本样式。接下来工作就是如何找到具体的关联样式。

    下面演示的操作以Customer表和UserProfile表为例。

    由于被动关系包括特殊关系,先来查询被动关系:

    1.查询被动关系

    1 Customer表
    2  
    3 >>> models.Customer._meta.related_objects
    4 (<ManyToOneRel: CRM.customerfollowup>, <ManyToOneRel: CRM.enrollment>, <ManyToOneRel: CRM.payment>)
    5 UserProfile表
    6  
    7 >>> models.UserProfile._meta.related_objects
    8 (<ManyToOneRel: CRM.customer>, <ManyToOneRel: CRM.customerfollowup>, <ManyToManyRel: CRM.classlist>, <ManyToOneRel: CRM.courserecord>, <ManyToOneRel: CRM.enrollment>, <ManyToOneRel: CRM.payment>)

    特殊关系是被动和主动关系都有的,这里所查询的应该是主动关系里面的特殊关系:

    2. 查询特殊关系

     1 Customer表
     2  
     3 >>> models.Customer._meta.many_to_many
     4 (<django.db.models.fields.related.ManyToManyField: tags>,)   #元组形式
     5 >>> models.Customer._meta.local_many_to_many
     6 [<django.db.models.fields.related.ManyToManyField: tags>]  #列表形式
     7 UserProfile表
     8  
     9 >>> models.UserProfile._meta.local_many_to_many
    10 [<django.db.models.fields.related.ManyToManyField: roles>]  #列表
    11 >>> models.UserProfile._meta.many_to_many
    12 (<django.db.models.fields.related.ManyToManyField: roles>,)  #元组
    13 2.2 关联数据获取

    2.2 关联数据获取

    上面找到了具体的关联,该怎么获取到相关联的数据呢?
    :请看下面。

    通常情况下,我们跨表查询是使用关联的表名_set进行反向查询,跳转到关联表中,然后在获取数据。在这里也是同样的道理,演示还是在shell中操作。

    Customer表为例:

    1 >>> models.Customer._meta.related_objects
    2 (<ManyToOneRel: CRM.customerfollowup>, <ManyToOneRel: CRM.enrollment>, <ManyToOneRel: CRM.payment>)
    3 >>> a= models.Customer._meta.related_objects
    4 >>> for i in a:print(i,'----',i.get_accessor_name())
    5 ...
    6 <ManyToOneRel: CRM.customerfollowup> ---- customerfollowup_set
    7 <ManyToOneRel: CRM.enrollment> ---- enrollment_set
    8 <ManyToOneRel: CRM.payment> ---- payment_set

    这里的关联的表名_set就是我们所需要的。

    由于在Customer表中没有被动关联中的特殊关联,所以我们以Tag表来反查到Customer表中数据:
    你的数据库中一定要有数据

     1 >>> a = models.Tag.objects.filter(id='4')
     2 >>> a
     3 <QuerySet [<Tag: dsfgb>]>
     4  
     5 #遍历出QuerySet集合里面的每个对象
     6 >>> for obj in a:
     7         #获取到每个对象对应的被动关联
     8 ...     for i in obj._meta.related_objects:
     9             # 通过反查方式获取到关联数据的对象集合
    10 ...         b = getattr(obj,i.get_accessor_name()).select_related()
    11             #遍历对象集合
    12 ...         for data in b:
    13 ...             print(data)
    14 ...
    15 4567467

    好了,我们的目标实现了!下面的工作就交给神器:自定义标签。

    2.3 创建标签函数

    templatetags/tags.py下创建功能函数:

     1 ...
     2 
     3 <-------------------获取删除映射关系--------------------------------
     4 
     5 @register.simple_tag
     6 def display_object_related(object_list):
     7     return mark_safe(recursive_related_objs_lookup(object_list))
     8 
     9 
    10 <-----------------递归获取映射关系--------------------------------
    11 
    12 def recursive_related_objs_lookup(object_list):
    13     #标签的拼接
    14     #最外层ul
    15     print(object_list)
    16     ul_ele = "<ul style='color: pink'>"
    17     for obj in object_list:
    18         print(obj._meta.verbose_name, obj.__str__().strip("<>"))
    19         li_ele = '''<li>{0}:{1}</li>'''.format(obj._meta.verbose_name, obj.__str__().strip("<>"))
    20         ul_ele += li_ele
    21 
    22         #映射关系处理
    23         <---------------------------特殊关联处理-----------------------------------
    24         #多对多关系
    25         for m2m_field in obj._meta.local_many_to_many: #local_many_to_many返回列表,many_to_many返回元祖
    26             sub_ul_ele = "<ul style='color: red'>"
    27             m2m_field_obj = getattr(obj, m2m_field.name)
    28             for m2m_data in m2m_field_obj.select_related():
    29                 sub_li_ele = '''<li>{0}:{1}</li>'''.format(m2m_field.verbose_name, m2m_data.__str__().strip("<>"))
    30                 sub_ul_ele += sub_li_ele
    31 
    32             sub_ul_ele += '</ul>'
    33             #与外层拼接
    34             ul_ele += sub_ul_ele
    35 
    36         <---------------------------被动关联处理------------------------------------
    37         #被动关联中的特殊关联处理
    38         for related_obj in obj._meta.related_objects:
    39             #判断是否存在特殊关联,特殊关联处理
    40             if 'ManyToManyRel' in related_obj.__repr__():
    41                 #判断对象中是否包含反查属性
    42                 if hasattr(obj, related_obj.get_accessor_name()):
    43                     #获取反查对应的对象
    44                     accessor_obj = getattr(obj, related_obj.get_accessor_name())
    45                     #判断有没有获取数据的方法或属性
    46                     if hasattr(accessor_obj, 'select_related'):
    47                         target_object = accessor_obj.select_related()
    48                         #标签拼接
    49                         sub_ul_ele = '<ul style="color: green">'
    50                         for data in target_object:
    51                             sub_li_ele = '''<li>{0}:{1}</li>'''.format(data._meta.verbose_name,
    52                                                                        data.__str__().strip("<>"))
    53                             sub_ul_ele += sub_li_ele
    54                         sub_ul_ele += '</ul>'
    55                         #与外层拼接
    56                         ul_ele += sub_ul_ele
    57             #被动关联处理
    58             elif hasattr(obj, related_obj.get_accessor_name()):
    59                 accessor_obj = getattr(obj, related_obj.get_accessor_name())
    60                 if hasattr(accessor_obj, 'select_related'):
    61                     target_object = accessor_obj.select_related()
    62                     <---------------由于使用递归,下面的标签样会发生重复,就不需要使用了--------------------
    63                     # sub_ul_ele = '<ul style="color: grey">'
    64                     # for data in target_data:
    65                     #     sub_li_ele = '''<li>{0}:{1}</li>'''.format(data._meta.verbose_name,
    66                     #                                                data.__str__().strip("<>"))
    67                     #     sub_ul_ele += sub_li_ele
    68                     # sub_ul_ele += '</ul>'
    69                     # # 与外层拼接
    70                     # ul_ele += sub_ul_ele
    71                 else:
    72                     print('One-To-One:',accessor_obj)
    73                     target_object = accessor_obj
    74                 #判断有无下级对象存在
    75                 if len(target_object) > 0:
    76                     node = recursive_related_objs_lookup(target_object)
    77                     ul_ele += node
    78 
    79     ul_ele += '</ul>'
    80     return ul_ele

    2.4 模板调用标签

    在编辑好的table_object_delete.html文件中添加:

     1 {% extends 'king_admin/table_index.html' %}
     2 {% load tags %}
     3 
     4 {% block body-content %}
     5 
     6     {# 显示映射关系 #}
     7     {% display_object_related object_list %}
     8 
     9     {# 表单提交  #}
    10     <form method="post">
    11         {% csrf_token %}
    12         <input type="submit" class="btn btn-danger" value="Yes,I'm sure">
    13         <input type="hidden" value="yes" name="delete_confirm">
    14         <a class="btn btn-info" href="{% url 'king_admin:table_object_edit' app_name table_name object_id %}">No,Take me back</a>
    15     </form>
    16 {% endblock %}

    删除效果如下:

    其他的修饰内容,可自行添加,反正我是最后套模板。

  • 相关阅读:
    基础
    条件语句/变量和基本数据类型
    编程语言介绍
    asp.net中log4net使用方法
    web布到服务器上出错
    《转》IEnumerable、IEnumerator两个接口的认识
    异步ADO.NET
    Session的使用
    AJAX参数及各种HTTP状态值
    简易的抓取别人网站内容
  • 原文地址:https://www.cnblogs.com/eaglesour/p/8098664.html
Copyright © 2011-2022 走看看