现在该来添加前面提到的Action功能了,强大的它能干什么,先来体验一下原生admin中的效果。

1. 原生admin体验

默认的删除功能是可以进行批量删除的!

可以在后台进行自定义功能

CRM应用目录下的admin.py中添加:

 1 from django.contrib import admin
 2 from CRM import models
 3 from django.shortcuts import render
 4 # Register your models here.
 5
 6 #自定义操作
 7 class CustomerAdmin(admin.ModelAdmin):
 8     list_display = ('name', 'id','qq','source','consultant','content','status','date')
 9     list_filter = ('source','consultant','date')
10     search_fields = ('qq','name')
11     raw_id_fields = ('consult_course',)
12     filter_horizontal = ('tags',)
13     list_editable = ('status',)
14     #添加如下内容
15     actions = ("test_action", )
16
17     def test_action(self,request,arg2):
18         print('test action:',self,request,arg2)
19         return render(request,"king_admin/table_index.html")

效果图:

跳转到指定的页面:

2. 重写action

2.1基类中添加字段

第一件事还是跟以前一样,需要在基类中添加对应的字段选项:

king_admin_base.py文件中:

1 class ModelAdmin(object):
2     list_display = []
3     list_filter = []
4     search_fields = []
5     ordering = None
6     filter_horizontal = []
7     actions = []  #添加该字段
8     list_per_page = 10

2.2 添加默认的批量删除

我还要在基类中添加默认情况下的批量删除功能,这个同原生admin中定义的方式一样。需要在基类下面定义个批量删除功能的函数。

king_admin_base.py文件中添加要定义的功能函数:

 1 from  django.shortcuts import render
 2
 3 #创建基类
 4 class ModelAdmin(object):
 5     list_display = []
 6     list_filter = []
 7     search_fields = []
 8     ordering = None
 9     filter_horizontal = []
10     actions = ['delete_many_objects']
11     list_per_page = 10
12
13
14     def delete_many_objects(self, request, selected_objects):
15         return render(request, 'king_admin/table_object_delete.html')
16
17 ...

2.3 模板文件编写

2.3.1 模板文件中显示功能

要在模板文件中显示这个功能函数,我们必须在table_objs.html文件中添加,只需要简单的添加一些标签:

 1 ...
 2
 3                   <button type="SUBMIT" class="btn btn-success">search</button>
 4                   </div>
 5                 </form>
 6                </div>
 7                 {# 添加action #}
 8                 <div class="row" style="margin-top: 10px">
 9                       <div class="col-lg-2">
10                           <select id="action_list" name="action" class="form-control" style="margin-left:15px">
11                               <option value="">---------</option>
12                               {% for action in admin_class.actions %}
13                                   <option value="{{ action }}">{{ action }}</option>
14                               {% endfor %}
15                           </select>
16                       </div>
17                       <div class="col-lg-1">
18                         <button type="submit" class="btn  " >Go</button>
19                       </div>
20                 </div>
21               {#具体的表格内容展示 #}
22
23 ...

显示效果如下:

有的朋友会问:你没有传admin_class变量?是的,这里没有必要再传了,因为在该模板文件中已经存在了!

2.3.2 模板中添加表单功能

上面只是简单的显示了功能,并没有实现具体的功能。然而实现具体的功能我们需要进行传递一些必要的值,传输这些值就需要表单组件来提供功能。

还是上面的代码,套一层表单标签即可:

 1  </div>
 2                 </form>
 3                </div>
 4                 {# 添加action #}
 5                 <div class="row" style="margin-top: 10px">
 6                     <form οnsubmit="return ActionSubmit(this)" method="POST">
 7                       {% csrf_token %}
 8                       <div class="col-lg-2">
 9                           <select id="action_list" name="action" class="form-control" style="margin-left:15px">
10                               <option value="">---------</option>
11                               {% for action in admin_class.actions %}
12                                   <option value="{{ action }}">{{ action }}</option>
13                               {% endfor %}
14                           </select>
15                       </div>
16                       <div class="col-lg-1">
17                         <button type="submit" class="btn">Go</button>
18                       </div>
19                     </form>
20                 </div>
21               {#具体的表格内容展示 #}

2.3.3 中文显示功能

说到中文显示,我们就不得不用到自定义标签了。但在使用之前先来看看原生的admin是怎么实现中文显示的吧:

1 ...
2
3     def test_action(self,request,arg2):
4         print('test action:',self,request,arg2)
5         return render(request,"king_admin/table_index.html")
6     test_action.short_description = '测试'  #添加这行代码
7
8 ...

显示效果:

开始我们自己的中文显示吧,就为我们刚刚写到默认批量删除功能添加显示中文:

 1 ...
 2 class ModelAdmin(object):
 3     list_display = []
 4     list_filter = []
 5     search_fields = []
 6     ordering = None
 7     filter_horizontal = []
 8     actions = ['delete_many_objects']
 9     list_per_page = 10
10
11
12     def delete_many_objects(self, request, queryset):
13         return render(request, 'king_admin/table_object_delete.html')
14     delete_many_objects.short_description = '批量删除'
15 ...

模板文件修改如下:  

 1 {# 添加action #}
 2                 <div class="row" style="margin-top: 10px">
 3                     <form οnsubmit="return ActionSubmit(this)" method="POST">
 4                       {% csrf_token %}
 5                       <div class="col-lg-2">
 6                           <select id="action_list" name="action" class="form-control" style="margin-left:15px">
 7                               <option value="">---------</option>
 8                               {% for action in admin_class.actions %}
 9                                   <option value="{{ action }}">{% get_action_name admin_class action %}</option>
10                               {% endfor %}
11                           </select>
12                       </div>

templates/tags.py文件中,添加的内容如下:

 1 ...
 2
 3 <------------------------显示默认action中文--------------------------
 4 @register.simple_tag
 5 def get_action_name(admin_class, action):
 6     action_func = getattr(admin_class, action)
 7     if hasattr(action_func, 'short_description'):
 8         return action_func.short_description
 9     else:
10         return action

渲染后的效果:

2.4 视图函数

上面我们已经查不到将模板文件所需要的都已经编写完毕,接下来就是数据的收发,涉及到数据的收发我们必须要用到视图。这里是在table_objs.html文件基础上添加的功能,视图中,我们同样要使用它来接收来自该模板文件的数据请求。

2.4.1 模板文件的数据发送

前面刚刚建立了表单功能,向后台提交数据就需要使用POST方式进行,同时我们还要将那些选中的checkbox中的行id一同传送到后端。

在前面建立表单的时候,已经添加了传送方式和提交的函数:<form onsubmit="return ActionSubmit(this)" method="POST">,这里将具体的提交函数编写一下:

 1 ...
 2
 3         function  ActionSubmit(self) {
 4             var selected_ids = [];
 5             $("input[tag='object_checkbox']:checked").each(function () {
 6                 selected_ids.push($(this).val());
 7             });
 8             var selected_action = $("#action_list").val();
 9             if  (selected_ids.length == 0){
10                 alert("No object got selected!");
11                 return;
12             }
13             if (!selected_action){
14                 alert("No action got selected!");
15             }
16            //添加隐藏标签,用来存储提交的数据key/value
17             var selected_ids_ele = "<input  name='selected_ids' type='hidden' value='" + selected_ids.toString() + "'>";
18             $(self).append(selected_ids_ele);
19             return true;
20         }

这些脚本同样放在该文件的最下面。

2.4.2 视图函数的数据接收

上面的数据已经发送,该接收数据了。接收数据的功能函数我们使用display_objects(request, app_name, table_name)即可,我们只需要添加几行代码:

 1 ...
 2
 3 def display_objects(request, app_name, table_name):
 4     #获取自定义的admin_class
 5     admin_class = site.enabled_admins[app_name][table_name]
 6     #数据查询
 7     #query_set = admin_class.model.objects.all()
 8
 9     <------------------接收action数据----------------------------
10     if request.method == 'POST':
11         #获取提交的数据
12         selected_ids = request.POST.get("selected_ids")
13         action = request.POST.get("action")
14         #后台判断
15         if selected_ids:
16             selected_objs = admin_class.model.objects.filter(id__in=selected_ids.split(','))
17         else:
18             raise KeyError("No object selected.")
19         if hasattr(admin_class, action):
20             action_func = getattr(admin_class, action)
21             #将action存储在请求体中便于调用
22             request._admin_action = action
23             return action_func(admin_class, request, selected_objs)
24
25 ...

2.5 编写具体批量删除功能

还记得之前编写的删除功能吗?这里我们要复用一下,在此基础上简单的添加一标签用来提交数据。

2.5.1 批量删除功能编写

继续填补之前编写的批量删除功能的架子,默认情况的GET请求页面获取,在king_admin_base.py中:

 1 ...
 2     def delete_many_objects(self, request, selected_objects):
 3         app_name = self.model._meta.app_label
 4         table_name = self.model._meta.model_name
 5         selected_ids = ','.join([str(i.id) for i in selected_objects])
 6         return render(request, 'king_admin/table_object_delete.html',{'selected_objects': selected_objects,
 7                                                                       'action': request._admin_action,
 8                                                                       'selected_ids': selected_ids,
 9                                                                       'app_name': app_name,
10                                                                       'table_name': table_name})
11     delete_many_objects.short_description = '批量删除'

2.5.2 复用编辑页面的删除功能主页面

table_object_delete.html文件中修改如下:

 1 {% extends 'king_admin/table_index.html' %}
 2 {% load tags %}
 3
 4 {% block body-content %}
 5
 6     {% if not action %}
 7         {# 显示映射关系 #}
 8         {% display_object_related object_list %}
 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     {% else %}
17         {# 显示映射关系 #}
18         {% display_object_related selected_objects %}
19         {# 批量删除 #}
20         <form method="post">
21         {% csrf_token %}
22             <input type="submit" class="btn btn-danger" value="Yes,I'm sure">
23             <input type="hidden" value="yes" name="delete_confirm">
24             <input type="hidden" value="{{ action }}" name="action"/>
25             <input type="hidden" value="{{ selected_ids }}" name="selected_ids"/>
26             <a class="btn btn-info" href="/king_admin/{{ app_name }}/{{ table_name }}/?page={{ get_page }}">No,Take me back</a>
27         </form>
28     {% endif %}
29 {% endblock %}

2.5.3 删除数据

上面完成了数据的发送与接收,最后剩下的就是数据的删除:

king_admin_base.py文件的函数修改:

 1 ...
 2     def delete_many_objects(self, request, selected_objects):
 3         app_name = self.model._meta.app_label
 4         table_name = self.model._meta.model_name
 5         selected_ids = ','.join([str(i.id) for i in selected_objects])
 6         #添加如下判断
 7         if request.method == 'POST':
 8             if request.POST.get('delete_confirm') == 'yes':
 9                 selected_objects.delete()
10                 return redirect('/king_admin/{app_name}/{table_name}'.format(app_name=app_name,
11                                                                              table_name=table_name))
12         return render(request, 'king_admin/table_object_delete.html',{'selected_objects': selected_objects,
13                                                                       'action': request._admin_action,
14                                                                       'selected_ids': selected_ids,
15                                                                       'app_name': app_name,
16                                                                       'table_name': table_name,
17                                                                       'get_page': request.GET.get('page')})
18     delete_many_objects.short_description = '批量删除'
19
20 ...

效果查看:

Good!批量删除功能搞定了,同时也意味着action的告终。如果你想要实现其他功能,基本的流程就是这样的,仅供参考。

大致的思路如下:

1. modeladmin中需要定义自定义action,同时将该action的函数定义需要写在这里;

 1 from CRM import models
 2 from django.shortcuts import render, HttpResponse, redirect
 3
 4
 5 class BaseAdmin(object):
 6     """构建后台管理的基类,模仿dango的admin"""
 7     list_display = []
 8     list_filter = []
 9     list_per_page = 10
10     search_fields = []
11     filter_horizontal = []
12     model = None
13     ordering = None
14     actions = []
15
16
17 # 构建字典数据结构,存储的数据类型是:
18 # {'CRM': {'customerinfo': <class 'kingadmin.kingadmin.CustomerInfoAdmin'>}}
19 # {'app名称': {'数据表名' : 管理界面需要显示的数据表类}
20 enabled_admins = {}
21
22
23 def register(model_class, admin_class=None):
24     """
25     注册管理类(管理界面要显示的数据表类),主要是将数据表定义类与后台管理数据表定义类进行关联;
26     将所有的数据表与项目名称做一个关联,存储在全局变量中:enabled_admins;
27     :param model_class: 数据表的定义类
28     :param admin_class: 后台管理数据表定义类
29     :return:
30     """
31     if model_class._meta.app_label not in enabled_admins:
32         enabled_admins.update({model_class._meta.app_label: {}})
33     # 给后台管理数据表定义类添加一个model属性,该属性就是数据表的定义类,
34     # 方便以后通过后台管理数据表定义类取相关的数据表的定义类中的先关信息
35     admin_class.model = model_class
36     # model_class._meta.app_label 当前数据表所在的APP的名称
37     # model_class._meta.model_name 当前数据表的名称
38     enabled_admins[model_class._meta.app_label][model_class._meta.model_name] = admin_class
39
40
41 class CustomerInfoAdmin(BaseAdmin):
42     """客户信息表管理类"""
43     list_display = ['id', 'qq', 'name', 'refer_path', 'consultant', 'consult_course', 'date', 'status', 'tags']
44     list_filter = ['refer_path', 'consultant', 'consult_course', 'status']
45     list_per_page = 10
46     search_fields = ['qq', 'name', 'consult_course__name']
47     ordering = 'date'
48     filter_horizontal = ['tags', ]
49     actions = ['delete_many_objects', ]
50
51     def delete_many_objects(self, request, selected_objects):
52         """
53
54         :param request:
55         :param selected_objects:
56         :return:
57         """
58         print(self, request, selected_objects)
59         app_name = self.model._meta.app_label
60         table_name = self.model._meta.model_name
61         object_ids = ','.join([str(i.id) for i in selected_objects])
62         print(app_name, table_name, object_ids, selected_objects, request._admin_action)
63         # 添加如下判断
64         if request.method == 'POST':
65             if request.POST.get('delete_confirm') == 'yes':
66                 selected_objects.delete()
67                 return redirect('/kingadmin/{0}/{1}'.format(app_name, table_name))
68         return render(request, 'kingadmin/table_object_delete.html', {'app_name': app_name,
69                                                                       'table_name': table_name,
70                                                                       'object_id': object_ids,
71                                                                       'object_list': selected_objects,
72                                                                       'action': request._admin_action,
73                                                                       })
74     delete_many_objects.short_description = '批量删除'

这其中需要注意的问题是在该函数定义中,如果需要返回一个模板文件,需要将对应的view处理函数需要的参数传递进去,如果不传递的话,系统会报错。

因此,这里是有可能引起urls.py的变动的,目前我的urls.py如下:

 1 from django.conf.urls import url, include
 2 from django.contrib import admin
 3 from . import views
 4
 5 urlpatterns = [
 6     url(r'^$', views.default),
 7     url(r'^(\w+)/(\w+)$', views.table_list, name='table_list'),
 8     url(r'^(\w+)/(\w+)/((\d+\,*)+)/delete$', views.table_object_delete, name='table_object_delete'),
 9     url(r'^(\w+)/(\w+)/((\d+\,*)+)/edit$', views.table_object_edit, name='table_object_edit'),
10     url(r'^(\w+)/(\w+)/add$', views.table_object_add, name='table_object_add'),

2. views.py需要做相应的变动,需要将POST和GET请求进行分开处理:

 1 def table_object_edit(request, app_name, table_name, object_id, form_object):
 2     """
 3     编辑表中的一条数据
 4     :param request:
 5     :param app_name:
 6     :param table_name:
 7     :param object_id:
 8     :param form_object:
 9     :return:
10     """
11     admin_class = kingadmin.enabled_admins[app_name][table_name]
12     model_form = create_model_form(request, admin_class)
13     object_list = admin_class.model.objects.get(id=object_id)
14     query_sets, filter_conditions = table_filter(request, admin_class)
15     page = request.GET.get('page', default='')
16     order = request.GET.get('o', '')
17     search_text = table_search(request, admin_class, query_sets)[1]
18     filter_conditions = custom_filter(request, admin_class)[1]
19     filter_text = filters_to_text(filter_conditions)
20     if request.method == 'POST':
21         form_object = model_form(request.POST, instance=object_list)
22         if form_object.is_valid():
23             form_object.save()
24             return redirect('/kingadmin/{0}/{1}?page={2}&o={3}&_q={4}&{5}'.format(
25                 app_name,
26                 table_name,
27                 page,
28                 order,
29                 search_text,
30                 filter_text,
31             ))
32         # else:                  # 目前可以删除(无论检验成功与否都是要返回table_object_edit.html)
33         #     return render(request, 'kingadmin/table_object_edit.html', {'form_object': form_object,
34         #                                                                 'admin_class': admin_class,
35         #                                                                 'app_name': app_name,
36         #                                                                 'table_name': table_name,
37         #                                                                 })              # 目前可以删除
38     else:
39         form_object = model_form(instance=object_list)
40     return render(request, 'kingadmin/table_object_edit.html', {'app_name': app_name,
41                                                                 'table_name': table_name,
42                                                                 'object_id': object_id,
43                                                                 'form_object': form_object,
44                                                                 'admin_class': admin_class,
45                                                                 })
46
47
48 def table_object_add(request, app_name, table_name):
49     """
50     添加页面
51     :param request:
52     :param app_name:
53     :param table_name:
54     :return:
55     """
56     admin_class = kingadmin.enabled_admins[app_name][table_name]
57     model_form = create_model_form(request, admin_class)
58
59     query_string = request.META.get('QUERY_STRING', '')
60     redirect_url = '/kingadmin/{0}/{1}?{2}'.format(app_name, table_name, query_string)
61     if request.method == 'POST':
62         form_object = model_form(request.POST)
63         if form_object.is_valid():
64             form_object.save()
65             return redirect(redirect_url)
66     else:
67         form_object = model_form()
68     return render(request, 'kingadmin/table_object_add.html', {'app_name': app_name,
69                                                                'table_name': table_name,
70                                                                'admin_class': admin_class,
71                                                                'form_object': form_object,
72                                                                })
73
74
75 def table_object_delete(request, app_name, table_name, object_id):
76     """
77
78     :param request:
79     :param app_name:
80     :param table_name:
81     :param object_id:
82     :return:
83     """
84     admin_class = kingadmin.enabled_admins[app_name][table_name]
85     object_list = admin_class.model.objects.filter(id=object_id)
86     if request.method == 'POST':
87         # print(dir(request.POST))
88         # print(request.POST)
89         if request.POST.get('delete_confirm', '') == 'yes':
90             object_list.delete()
91             return redirect('/kingadmin/{app_name}/{table_name}'.format(
92                 app_name=app_name,
93                 table_name=table_name,
94             ))
95     return render(request, 'kingadmin/table_object_delete.html', {'app_name': app_name,
96                                                                   'table_name': table_name,
97                                                                   'object_id': object_id,
98                                                                   'object_list': object_list,
99                                                                   })

需要特别注意的是:

 1 def table_list(request, app_name, table_name):
 2     """
 3     列出数据表中的所有数据
 4     :param request:
 5     :param app_name: app名称
 6     :param table_name: 数据表名称
 7     :return:
 8     """
 9     # app_name & table_name都存在enabled_admins中,取出其中的数据
10     # for item in request.GET.items():
11     #     print(item)
12     if app_name in kingadmin.enabled_admins.keys() and \
13             table_name in kingadmin.enabled_admins[app_name].keys():
14         admin_class = kingadmin.enabled_admins[app_name][table_name]
15
16         # 检索过滤数据
17         # query_sets = admin_class.model.objects.all()
18         query_sets, filter_conditions_customer = custom_filter(request, admin_class)
19         # 搜索过滤数据
20         query_sets, search_text = table_search(request, admin_class, query_sets)
21         # query_sets 排序
22         query_sets, order_before, order_after = table_sort(request, admin_class, query_sets)
23         filter_conditions_preset = admin_class.list_filter
24
25         if request.method == 'POST':
26             # 获取提交数据
27             selected_ids = request.POST.get("selected_ids")
28             action = request.POST.get("selected_action")
29             print(selected_ids, action)
30             if selected_ids:
31                 selected_objs = admin_class.model.objects.filter(id__in=selected_ids.split(','))
32             else:
33                 raise KeyError('No object selected')
34             if hasattr(admin_class, action):
35                 action_func = getattr(admin_class, action)
36                 # 将action存储在请求体中便于调用
37                 request._admin_action = action
38                 return action_func(admin_class, request, selected_objs)
39         else:
40             # list_display中的所有字段对应的verbose_name
41             field_verbose_names = []
42             field_names = []
43             fields = []
44             for field_name in admin_class.list_display:
45                 for field in admin_class.model._meta.get_fields():
46                     if field.name == field_name:
47                         fields.append(field)
48                         # field_names.append(field_name)
49                         # field_verbose_names.append(field.verbose_name)
50
51             # 分页
52             page = request.GET.get('page', '')
53
54             paginator = Paginator(query_sets, admin_class.list_per_page)
55             # 检索参数
56             filter_text = filters_to_text(filter_conditions_customer)
57             try:
58                 contacts = paginator.page(page)
59             except PageNotAnInteger:
60                 # If page is not an integer, deliver first page.
61                 contacts = paginator.page(1)
62             except EmptyPage:
63                 # If page is out of range (e.g. 9999), deliver last page of results.
64                 contacts = paginator.page(paginator.num_pages)
65             contacts_count = len(contacts)
66             return render(request, 'kingadmin/table_list.html', {'app_name': app_name,
67                                                                  'table_name': table_name,
68                                                                  'query_sets': query_sets,
69                                                                  'admin_class': admin_class,
70                                                                  # 'field_verbose_names': field_verbose_names,
71                                                                  # 'field_names': field_names,
72                                                                  'order_before': order_before,
73                                                                  'order_after': order_after,
74                                                                  'fields': fields,
75                                                                  'contacts': contacts,
76                                                                  'contacts_count': contacts_count,
77                                                                  'filter_conditions': filter_conditions_preset,
78                                                                  'filter_conditions_customer': filter_conditions_customer,
79                                                                  'search_text': search_text,
80                                                                  'page': page,
81                                                                  'filter_text': filter_text,
82                                                                  })
83     # app_name | table_name不存在enabled_admin中,就返回错误信息
84     else:
85         error = '应用名称或数据表名称不存在或未注册'
86         return render(request,
87                       'kingadmin/table_list.html',
88                       {'error': error,
89                        'app_name': app_name,
90                        'table_name': table_name,
91                        })

selected_ids与selected_action都是通过POST方法返回的,在模板文件中进行确认的时候,隐藏字段的值也需要一一对应,否则,获取到的selected_ids/selected_action都是None,系统就会出错。

3. 模板文件做相应的修改:

 1 {% extends 'project/head.html' %}
 2 {% load tags %}
 3 {% block main %}
 4     {% if not action %}
 5         {% get_relationships object_list %}
 6         <form method="post">
 7             {% csrf_token %}
 8             <input type="submit" class="btn btn-danger" value="Yes, I'm sure">
 9             <input type="hidden" value="yes" name="delete_confirm">
10             <a class="btn btn-info" href="{% url 'table_object_edit' app_name table_name object_id %}">No, Take me
11                 back</a>
12         </form>
13     {% else %}
14         {% get_relationships object_list %}
15         <form method="post">
16             {% csrf_token %}
17             <input type="submit" class="btn btn-danger" value="Yes, I'm sure">
18             <input type="hidden" value="yes" name="delete_confirm">
19             <input type="hidden" value="{{ action }}" name="selected_action">
20             <input type="hidden" value="{{ object_id }}" name="selected_ids">
21             <a class="btn btn-info" href="/kingadmin/{{ app_name }}/{{ table_name }}">No, Take me
22                 back</a>
23         </form>
24     {% endif %}
25
26 {% endblock %}

转载于:https://www.cnblogs.com/eaglesour/p/8098711.html

项目一:CRM(客户关系管理系统)--9---自定制action相关推荐

  1. Java Web项目源代码|CRM客户关系管理系统项目实战(Struts2+Spring+Hibernate)解析+源代码+教程

    客户关系管理 (CRM) CRM一般指客户关系管理 客户关系管理是指企业为提高核心竞争力,利用相应的信息技术以及互联网技术协调企业与顾客间在销售.营销和服务上的交互,从而提升其管理方式,向客户提供创新 ...

  2. Java项目:CRM客户关系管理系统(Spring+SpringMVC+MyBatis + maven)

    目录 1. 项目概述 2. 环境搭建 2.1 创建项目 2.2 导入jsp页面 2.3 配置类 2.3.1 MyBatis 配置 2.3.2 Spring 配置 2.3.3 Spring MVC 配置 ...

  3. Django项目:CRM(客户关系管理系统)--69--59PerfectCRM实现king_admin行内编辑

    1 #base_admin.py 2 3 4 # --------24PerfectCRM实现King_admin自定义操作数据-------- 5 from django.shortcuts imp ...

  4. Django项目:CRM(客户关系管理系统)--12--05PerfectCRM实现King_admin注册功能获取内存01...

    1 #base_admin.py 2 #Django admin 注册功能的形式 3 # sites = { 4 # 'crm':{ 5 # 'customers':CustomerAdmin, 6 ...

  5. Django项目:CRM(客户关系管理系统)--50--41PerfectCRM实现全局账号密码修改

    1 # gbacc_urls.py 2 # --------38PerfectCRM实现全局账号登录注销-------- 3 from django.conf.urls import url 4 fr ...

  6. Django项目:CRM(客户关系管理系统)--83--73PerfectCRM实现CRM模板统一

    1 {#king_index.html#} 2 {## --------73PerfectCRM实现CRM模板统一--------#} 3 {% extends "master/sample ...

  7. Java项目:springboot客户关系管理系统

    作者主页:夜未央5788 简介:Java领域优质创作者.Java项目.学习资料.技术互助 文末获取源码 项目介绍 CRM客户关系管理系统.本系统共分为三种角色:超级管理员.经理.销售人员: 超级管理员 ...

  8. Java项目:CRM客户关系管理系统(java+Springboot+maven+mysql)

    源码获取:博客首页 "资源" 里下载! Springboot项目CRM客户关系管理系统: 系统实现了CRM客户关系系统的基本功能,主要有看板(当月参与的业务机会.当月转化情况.将要 ...

  9. JavaWeb实训项目:基于SSM框架的CRM客户关系管理系统(文章最后有源码)

    JavaWeb实训项目:基于SSM框架的CRM客户关系管理系统(附部分源码) 一.项目背景 项目演示 二.项目介绍 三.涉及技术 总结 源码地址 一.项目背景 "世上本来没有CRM,大家的生 ...

  10. 联系人管理-客户拜访记录| CRM客户关系管理系统项目 实战七(Struts2+Spring+Hibernate)解析+源代码

    联系人管理-客户拜访记录| CRM客户关系管理系统项目 实战七(Struts2+Spring+Hibernate)解析+源代码 客户拜访记录的列表的显示, 客户拜访记录的保存, 客户拜访记录查询(条件 ...

最新文章

  1. 除了CRUD也要注意IO
  2. php 旋转图片 并保存,如何在PHP中旋转并保存图像
  3. MyIbatis :不使用XML和注解@Mapper以及MapperScan
  4. Ubuntu on Windows,在Windows上的Ubuntu
  5. Swing表格JTable通过JTableModel插入行
  6. MT9 二维数组打印(Python)
  7. python400集 高淇主讲pdf_高淇python400集全套视频教程 相关实例(示例源码)下载 - 好例子网...
  8. 蓝牙bluez进行HCI编程
  9. 燃烧的远征java(三)-Struts+Spring+Hibernate:java的几种对象(PO,VO,DAO,BO,POJO)解释
  10. 实现java多线程的3种方式
  11. linux给变量加单引号,grep中加单引号与不加引号的区别
  12. 怎么用python编简单游戏大全_适合新手练手的三个python简单小游戏
  13. 盘点一下分布式模式下的服务治理和监控优化方案
  14. python符号计算 漂亮地打印出来_让Python输出更漂亮:PrettyPrinter
  15. Codeforces 1087 - 题集
  16. 支付宝扫码验签实例php,PHP 支付宝支付,支付宝回调
  17. 2018-2019-2 20175227张雪莹 《Java程序设计》 实验一 Java开发环境的熟悉
  18. 2017目标跟踪算法综述
  19. 上传多组带标题的图片
  20. 静态时序分析 第六章 串扰和噪声

热门文章

  1. 快速上手 Token 登录认证
  2. Springboot旧教材交易系统a6151计算机毕业设计-课程设计-期末作业-毕设程序代做
  3. ceph monitor paxos算法
  4. 射频微波芯片设计7:详解基于ADS的低噪声放大器芯片设计
  5. 【陈秀秀往事】---一个战痘8年成功的感人故事!
  6. pytorch深度学习中每个epoch运行时间的统计代码
  7. hello yocto
  8. H5 Vue 视频 video 支持预览图 poster
  9. Strings and Runes
  10. golang合并支付二维码到背景图片