CRM项目(二)
CRM项目开发(二)
|
文章目录
|
CRM系统是一个相对较复杂的软件,其中重构admin是最为繁琐的过程,这个解决掉其他都是松松的!路漫漫其修远兮,重写admin也是一个漫长的过程。
接下来是重写admin的过程:
构造Home首页
创建应用
将新的admin作为一个应用,便于扩展和移植。根目录下,创建应用,并命名为:king_admin(根据自己的喜好)
————》:django-Admin startapp king_admin
原生admin首页分析
在Django自带的后台中,首页显示的是项目名称和数据库表中的字段名称,并显示添加和修改功能。(其中,数据库中绑定了url的映射关系,添加对应的映射名称即可)
这里不显示,原生后台的Users和Groups内容,将在后面的权限管理中独立出来!
构造应用路由
from django.conf.urls import url from king_admin import views
urlpatterns = [ url(r'^$', views.index, name='table_index'), #name是对应数据库中的映射关系 ]
构建前端模板
创建静态文件目录
使用Bootsrap框架,项目中创建statics目录并在settings.py中添加对应路径:
STATIC_URL = '/static/'
#添加以下内容
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'statics'),
)
构造底层基础母板
在templates目录下添加base.html作为所有可继承模板的母板,主要是用来引入样式CSS和JS。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Django Admin</title>
<!-- Bootstrap core CSS -->
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="/static/css/dashboard.css" rel="stylesheet">
<!-- Just for debugging purposes. Don't actually copy these 2 lines! -->
<!--[if lt IE 9]><script src="../../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
<script src="/static/js/ie-emulation-modes-warning.js"></script>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href='{% url 'crm_index' %}'>PerfectCRM</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="#">{{ request.user }}</a></li>
</ul>
</div>
</div>
</nav>
{% block body-content %}{% endblock %}
</body>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<script src="/static/js/docs.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="/static/js/ie10-viewport-bug-workaround.js"></script>
</html>
创建项目所需主页
为了更好的扩展和区分,在templates目录下单独建立对应项目的存储模板文件的目录king_admin,然后创建table_index.html文件。
table_index.html文件内容如下:
{% extends 'base.html' %} #继承母板
{% block body-content %} #继承块内容
<div class="container " style="margin: 50px;width: auto">
{% block container %} #为后面继承的块
<div class="row">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">King_Admin</h3>
</div>
<div class="panel-body">
<table class="table table-hover">
<thead>
<tr>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>显示字段</td>
<td>添加</td>
<td>修改</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}
</div>
{% endblock %}
编写视图函数
from django.shortcuts import render
def index(request):
return render(request, 'king_admin/table_index.html')
访问结果,如下图:
按钮修饰自己按照bootstrap耍吧

构造admin注册功能
前面我们先简单的编写了能够访问的首页,但是需要显示数据库的字段名称和项目名称,必须要有向admin注册的功能。
原生admin注册功能分析
在开始,我们访问原生的admin时,我们需要先注册数据库的表名及类的名称和自定义的类名称。这流程看起来简单,后台实现起来其实也是很简单的!
仿写注册功能
在king_admin应用下面添加king_admin.py文件,并编写以下内容:
#创建基类 class BaseAdmin(object): list_display = [] list_filter = [] list_per_page = 2 #数据结构容器 enabled_admins = {} """ {项目名: {表名1: 自定义类1, 表名2: 自定义类2, }, } """ #构造数据结构--->通过models类和自定义类注册获取 def register(model_class, admin_class=None): if model_class._meta.app_label not in enabled_admins: #添加项目名称 enabled_admins.update({model_class._meta.app_label: {}}) #添加自定义类属性为models类 admin_class.model = model_class #通过表名获取到自定义类 enabled_admins[model_class._meta.app_label][model_class._meta.model_name] = admin_class
进行注册
from CRM import models
#创建基类
class BaseAdmin(object):
list_display = []
list_filter = []
list_per_page = 2
#数据结构容器
enabled_admins = {}
"""
{项目名: {表名1: 自定义类1,
表名2: 自定义类2,
},
}
"""
#构造数据结构--->通过models类和自定义类注册获取
def register(model_class, admin_class=None):
if model_class._meta.app_label not in enabled_admins:
#添加项目名称
enabled_admins.update({model_class._meta.app_label: {}})
#添加自定义类属性为models类
admin_class.model = model_class
#通过表名获取到自定义类
enabled_admins[model_class._meta.app_label][model_class._meta.model_name] = admin_class
#自定义类,显示特定字段
class CustomerAdmin(BaseAdmin):
list_display = ['qq','name','source','consultant','consult_course','date','status']
list_filters = ['source','consultant','consult_course','status']
#model = models.Customer
class CustomerFollowUpAdmin(BaseAdmin):
list_display = ('customer','consultant','date')
#进行注册,构造数据结构
register(models.Customer, CustomerAdmin)
register(models.CustomerFollowUp, CustomerFollowUpAdmin)
上面这样写在同一个文件中,是不是很别扭,为什么不将注册功能和注册行为分开呢??
其实,注册行为和功能的分开是很有必要的,方便功能的扩展和避免与行为的混淆,更利于架构的优化!
解决如下:
待解决。。。
添加项目名称和字段
添加的内容,我们需要使用到Django的shell进行测试查询我们需要的方法、属性。
终端中,进入到shell
>>>python manage.py shell Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>>
查询项目名称
在king_admin.py中自定义的enable_admins中遍历即可。
查询字段名称
查询字段名称,最先想到的是当我们操作数据库时,models中的最接近字段名称应该是类的名称也就是表名。因此,先查询表名下的属性和方法:
>>> from CRM import models >>> a = models.Customer >>> >>> dir(a) ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__modul e__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slotnames__', '__str__', '__subclasshook__', '__weakref__', '_constructor_arg s', '_db', '_get_queryset_methods', '_hints', '_insert', '_originating_model', '_queryset_class', '_set_creation_counter', '_update', 'aggregate', 'all', 'annotate', 'auto_created ', 'bulk_create', 'check', 'complex_filter', 'contribute_to_class', 'count', 'create', 'creation_counter', 'dates', 'datetimes', 'db', 'db_manager', 'deconstruct', 'defer', 'disti nct', 'earliest', 'exclude', 'exists', 'extra', 'filter', 'first', 'from_queryset', 'get', 'get_or_create', 'get_queryset', 'in_bulk', 'iterator', 'last', 'latest', 'model', 'name ', 'none', 'only', 'order_by', 'prefetch_related', 'raw', 'reverse', 'select_for_update', 'select_related', 'update', 'update_or_create', 'use_in_migrations', 'using', 'values', ' values_list']
在上面会看到很多方法和属性,其中一个很是关键:_meta,是对改类的操作。继续:
>>> a._meta <Options for Customer> >>> dir(a._meta) ['FORWARD_PROPERTIES', 'REVERSE_PROPERTIES', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash_ _', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__we akref__', '_expire_cache', '_forward_fields_map', '_get_fields', '_get_fields_cache', '_ordering_***', '_populate_directed_relation_graph', '_prepare', '_relation_tree', 'abstra ct', 'add_field', 'add_manager', 'app_config', 'app_label', 'apps', 'auto_created', 'auto_field', 'base_manager', 'base_manager_name', 'can_migrate', 'concrete_fields', 'concrete_ model', 'contribute_to_class', 'db_table', 'db_tablespace', 'default_apps', 'default_manager', 'default_manager_name', 'default_permissions', 'default_related_name', 'fields', 'fi elds_map', 'get_ancestor_link', 'get_base_chain', 'get_field', 'get_fields', 'get_latest_by', 'get_parent_list', 'has_auto_field', 'index_together', 'installed', 'label', 'label_l ower', 'local_concrete_fields', 'local_fields', 'local_managers', 'local_many_to_many', 'managed', 'manager_inheritance_from_future', 'managers', 'managers_map', 'many_to_many', ' model', 'model_name', 'object_name', 'order_with_respect_to', 'ordering', 'original_attrs', 'parents', 'permissions', 'pk', 'private_fields', 'proxy', 'proxy_for_model', 'related_ fkey_lookups', 'related_objects', 'required_db_features', 'required_db_vendor', 'select_on_save', 'setup_pk', 'setup_proxy', 'swappable', 'swapped', 'unique_together', 'verbose_na me', 'verbose_name_plural', 'verbose_name_raw', 'virtual_fields']
很显然,上面有我们所需要的:
>>> a._meta.verbose_name '客户表'
模板中添加名称
既然,我们所要的数据都找到了来源,剩下的就是在模板中添加进行渲染了。
在table_index.html中,添加内容如下(自行对比前面):
{% extends 'base.html' %}
{% load tags %} #引入自定标签
{% block body-content %}
<div class="container " style="margin: 50px;width: auto">
{% block container %}
<div class="row">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">King_Admin</h3>
</div>
<div class="panel-body">
{{ table_list }}
{% for app_name, table_names in table_list.items %}
<table class="table table-hover">
<thead>
<tr>
<th>{{ app_name }}</th>
</tr>
</thead>
<tbody>
{% for table_name, admin in table_names.items %}
<tr>
{#1.链接:url/应用名/表名,2. 显示中文表名--使用自定义标签进行处理#}
<td>{% render_verbose_name admin %}</td>
<td>添加</td>
<td>修改</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %}
</div>
</div>
</div>
{% endblock %}
</div>
{% endblock %}
文件中,需要使用到自定义标签的功能,具体的使用请看官网或后边会有自定义标签!
模板标签文件的内容如下:
from django import template
register = template.Library()
#------------------------显示表名称-->中文---------------------------
@register.simple_tag
def render_verbose_name(admin_class):
return admin_class.model._meta.verbose_name
现实如下:


浙公网安备 33010602011771号