CRM客户关系管理系统知识点总结
一、项目需求(使用PrecessOn)
二、models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here. class Customer(models.Model):
'''客户信息表'''
name = models.CharField(max_length=32,blank=True,null=True)
qq = models.CharField(max_length=64,unique=True)
qq_name = models.CharField(max_length=64,blank=True,null=True)
phone = models.CharField(max_length=64,blank=True,null=True)
source_choices = ((0,'转介绍'),
(1,'QQ群'),
(2,'官网'),
(3,'百度推广'),
(4,'51CTO'),
(5,'知乎'),
(6,'市场推广'),
) source = models.SmallIntegerField(choices=source_choices)
referral_from = models.CharField(verbose_name="转介绍人qq",max_length=64,blank=True,null=True) consult_course = models.ForeignKey("Course",verbose_name="咨询课程")
content = models.TextField(verbose_name="咨询详情")
tags = models.ManyToManyField("Tag",blank=True,null=True)
status_choices = ((0,'已报名'),
(1,'未报名'),
)
status = models.SmallIntegerField(choices=status_choices,default=1)
consultant = models.ForeignKey("UserProfile")
memo = models.TextField(blank=True,null=True)
date = models.DateTimeField(auto_now_add=True) def __str__(self):
return self.qq class Meta:
verbose_name ="客户表"
verbose_name_plural ="客户表" class Tag(models.Model):
name = models.CharField(unique=True,max_length=32) def __str__(self):
return self.name class Meta:
verbose_name = "标签"
verbose_name_plural = "标签" class CustomerFollowUp(models.Model):
'''客户跟进表'''
customer = models.ForeignKey("Customer")
content = models.TextField(verbose_name="跟进内容")
consultant = models.ForeignKey("UserProfile") intention_choices = ((0,'2周内报名'),
(1,'1个月内报名'),
(2,'近期无报名计划'),
(3,'已在其它机构报名'),
(4,'已报名'),
(5,'已拉黑'),
)
intention = models.SmallIntegerField(choices=intention_choices)
date = models.DateTimeField(auto_now_add=True) def __str__(self):
return "<%s : %s>" %(self.customer.qq,self.intention) class Meta:
verbose_name = "客户跟进记录"
verbose_name_plural = "客户跟进记录" class Course(models.Model):
'''课程表'''
name = models.CharField(max_length=64,unique=True)
price = models.PositiveSmallIntegerField()
period = models.PositiveSmallIntegerField(verbose_name="周期(月)")
outline = models.TextField() def __str__(self):
return self.name class Meta:
verbose_name = "课程表"
verbose_name_plural = "课程表" class Branch(models.Model):
'''校区'''
name = models.CharField(max_length=128,unique=True)
addr = models.CharField(max_length=128)
def __str__(self):
return self.name class Meta:
verbose_name = "校区"
verbose_name_plural = "校区" class ClassList(models.Model):
'''班级表'''
branch = models.ForeignKey("Branch",verbose_name="校区")
course = models.ForeignKey("Course")
class_type_choices = ((0,'面授(脱产)'),
(1,'面授(周末)'),
(2,'网络班')
)
class_type = models.SmallIntegerField(choices=class_type_choices,verbose_name="班级类型")
semester = models.PositiveSmallIntegerField(verbose_name="学期")
teachers = models.ManyToManyField("UserProfile")
start_date = models.DateField(verbose_name="开班日期")
end_date = models.DateField(verbose_name="结业日期",blank=True,null=True) def __str__(self):
return "%s %s %s" %(self.branch,self.course,self.semester) class Meta:
unique_together = ('branch','course','semester')
verbose_name_plural = "班级"
verbose_name = "班级" class CourseRecord(models.Model):
'''上课记录'''
from_class = models.ForeignKey("ClassList",verbose_name="班级")
day_num = models.PositiveSmallIntegerField(verbose_name="第几节(天)")
teacher = models.ForeignKey("UserProfile")
has_homework = models.BooleanField(default=True)
homework_title = models.CharField(max_length=128,blank=True,null=True)
homework_content = models.TextField(blank=True,null=True)
outline = models.TextField(verbose_name="本节课程大纲")
date = models.DateField(auto_now_add=True) def __str__(self):
return "%s %s" %(self.from_class,self.day_num) class Meta:
unique_together = ("from_class", "day_num")
verbose_name_plural = "上课记录" class StudyRecord(models.Model):
'''学习记录'''
student = models.ForeignKey("Enrollment")
course_record = models.ForeignKey("CourseRecord")
attendance_choices = ((0,'已签到'),
(1,'迟到'),
(2,'缺勤'),
(3,'早退'),
)
attendance = models.SmallIntegerField(choices=attendance_choices,default=0)
score_choices = ((100,"A+"),
(90,"A"),
(85,"B+"),
(80,"B"),
(75,"B-"),
(70,"C+"),
(60,"C"),
(40,"C-"),
(-50,"D"),
(-100,"COPY"),
(0,"N/A"),
)
score = models.SmallIntegerField(choices=score_choices,default=0)
memo = models.TextField(blank=True,null=True)
date = models.DateField(auto_now_add=True) def __str__(self):
return "%s %s %s" %(self.student,self.course_record,self.score) class Meta:
unique_together = ('student','course_record')
verbose_name_plural = "学习记录" class Enrollment(models.Model):
'''报名表'''
customer = models.ForeignKey("Customer")
enrolled_class = models.ForeignKey("ClassList",verbose_name="所报班级")
consultant = models.ForeignKey("UserProfile",verbose_name="课程顾问")
contract_agreed = models.BooleanField(default=False,verbose_name="学员已同意合同条款")
contract_approved = models.BooleanField(default=False,verbose_name="合同已审核")
date = models.DateTimeField(auto_now_add=True) def __str__(self):
return "%s %s" %(self.customer,self.enrolled_class) class Meta:
unique_together = ("customer","enrolled_class")
verbose_name_plural = "报名表" class Payment(models.Model):
'''缴费记录'''
customer = models.ForeignKey("Customer")
course = models.ForeignKey("Course",verbose_name="所报课程")
amount = models.PositiveIntegerField(verbose_name="数额",default=500)
consultant = models.ForeignKey("UserProfile")
date = models.DateTimeField(auto_now_add=True) def __str__(self):
return "%s %s" %(self.customer,self.amount) class Meta:
verbose_name_plural = "缴费记录" class UserProfile(models.Model):
'''账号表'''
user = models.OneToOneField(User)
name = models.CharField(max_length=32)
roles = models.ManyToManyField("Role",blank=True,null=True) def __str__(self):
return self.name class Role(models.Model):
'''角色表'''
name = models.CharField(max_length=32,unique=True)
menus = models.ManyToManyField("Menu",blank=True) def __str__(self):
return self.name
class Meta:
verbose_name_plural = "角色" class Menu(models.Model):
'''菜单'''
name = models.CharField(max_length=32)
url_name = models.CharField(max_length=64) def __str__(self):
return self.name
models.py
三、开发中使用的相关技术:
Django\Bootstrap\Jquery等
四、项目各个功能的实现以及知识点:
1、自定义数据库表显示页面
- 页面模板使用:Bootstarp: http://v3.bootcss.com/examples/dashboard/
- base.html\index.html
<!DOCTYPE html>
<!-- saved from url=(0041)http://v3.bootcss.com/examples/dashboard/ -->
<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; 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="">
<!--link rel="icon" href="http://v3.bootcss.com/favicon.ico"--> <title>Oldboy PerfectCRM</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>
{% block body %} {% endblock %} <!-- 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>base.html
{% extends 'base.html' %} {% block body %}
<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="#">Oldboy PefectCRM</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> <div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar">
<ul class="nav nav-sidebar">
{% for role in request.user.userprofile.roles.all %}
{% for menu in role.menus.all %}
<li class=""><a href="{% url menu.url_name %}">{{ menu.name }}</a></li>
{% endfor %}
{% endfor %} </ul> </div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
{% block page-content %}
<h1 class="page-header">Dashboard</h1> <div class="row placeholders"> <div class="col-xs-6 col-sm-3 placeholder">
<img data-src="holder.js/200x200/auto/sky" class="img-responsive" alt="200x200" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgdmlld0JveD0iMCAwIDIwMCAyMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxkZWZzLz48cmVjdCB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgZmlsbD0iIzBEOEZEQiIvPjxnPjx0ZXh0IHg9Ijc1LjUiIHk9IjEwMCIgc3R5bGU9ImZpbGw6I0ZGRkZGRjtmb250LXdlaWdodDpib2xkO2ZvbnQtZmFtaWx5OkFyaWFsLCBIZWx2ZXRpY2EsIE9wZW4gU2Fucywgc2Fucy1zZXJpZiwgbW9ub3NwYWNlO2ZvbnQtc2l6ZToxMHB0O2RvbWluYW50LWJhc2VsaW5lOmNlbnRyYWwiPjIwMHgyMDA8L3RleHQ+PC9nPjwvc3ZnPg==" data-holder-rendered="true">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
<div class="col-xs-6 col-sm-3 placeholder">
<img data-src="holder.js/200x200/auto/vine" class="img-responsive" alt="200x200" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgdmlld0JveD0iMCAwIDIwMCAyMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxkZWZzLz48cmVjdCB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgZmlsbD0iIzM5REJBQyIvPjxnPjx0ZXh0IHg9Ijc1LjUiIHk9IjEwMCIgc3R5bGU9ImZpbGw6IzFFMjkyQztmb250LXdlaWdodDpib2xkO2ZvbnQtZmFtaWx5OkFyaWFsLCBIZWx2ZXRpY2EsIE9wZW4gU2Fucywgc2Fucy1zZXJpZiwgbW9ub3NwYWNlO2ZvbnQtc2l6ZToxMHB0O2RvbWluYW50LWJhc2VsaW5lOmNlbnRyYWwiPjIwMHgyMDA8L3RleHQ+PC9nPjwvc3ZnPg==" data-holder-rendered="true">
<h4>Label</h4>
<span class="text-muted">Something else</span>
</div>
</div> <h2 class="sub-header">Section title</h2> {% endblock %}
</div>
</div>
</div> </body> {% endblock %}index.html
显示页面:table_index.html
{% extends 'base.html' %}
{% load tags %} {% block body %}
<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="#">Oldboy PefectCRM</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> <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">Panel title</h3>
</div>
<div class="panel-body">
{{ table_list }}
{% for app_name,app_tables in table_list.items %} <table class="table table-hover">
<thead>
<tr>
<th>{{ app_name }}</th>
</tr>
</thead>
<tbody>
{% for table_name,admin in app_tables.items %}
<tr>
<td>
<a href="{% url 'table_objs' app_name table_name %}">
{% render_app_name admin %}
</a>
</td>
<td>add</td>
<td>change</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %} </div>
</div>
</div>
{% endblock %}
</div> </body> {% endblock %}table_index.html
- 页面的显示
from django.conf.urls import url,include
from django.contrib import admin urlpatterns = [
url(r'^king_admin/', include("king_admin.urls")),
]from django.conf.urls import url
from king_admin import views urlpatterns = [
url(r'^$', views.index,name="table_index"),
] 注册要显示的表,自定义显示信息项king_admin.py
#__author: Administrator
#date: 2017/1/5 from crm import models enabled_admins = {} class BaseAdmin(object):
list_display = []
list_filters = []
search_fields = []
list_per_page = 20
ordering = None class CustomerAdmin(BaseAdmin):
list_display = ["id",'qq','name','source','consultant','consult_course','date','status']
list_filters = ['source','consultant','consult_course','status','date']
search_fields = ['qq','name',"consultant__name"] #model = models.Customer
list_per_page = 5
ordering = "qq"
class CustomerFollowUpAdmin(BaseAdmin):
list_display = ('customer','consultant','date') def register(model_class,admin_class=None):
if model_class._meta.app_label not in enabled_admins:
enabled_admins[model_class._meta.app_label] = {} #enabled_admins['crm'] = {}
#admin_obj = admin_class()
admin_class.model = model_class #绑定model 对象和admin 类
enabled_admins[model_class._meta.app_label][model_class._meta.model_name] = admin_class
#enabled_admins['crm']['customerfollowup'] = CustomerFollowUpAdmin register(models.Customer,CustomerAdmin)
register(models.CustomerFollowUp,CustomerFollowUpAdmin)<div class="panel-body">
{{ table_list }}
{% for app_name,app_tables in table_list.items %} <table class="table table-hover">
<thead>
<tr>
<th>{{ app_name }}</th>
</tr>
</thead>
<tbody>
{% for table_name,admin in app_tables.items %}
<tr>
<td>
<a href="{% url 'table_objs' app_name table_name %}">
{% render_app_name admin %}
</a>
</td>
<td>add</td>
<td>change</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endfor %} </div>HTML
from django.shortcuts import render,redirect
import importlib
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from king_admin.utils import table_filter,table_sort,table_search
# Create your views here.
from king_admin import king_admin
from king_admin.forms import create_model_form def index(request):
#print(king_admin.enabled_admins['crm']['customerfollowup'].model )
return render(request, "king_admin/table_index.html",{'table_list':king_admin.enabled_admins}) def display_table_objs(request,app_name,table_name): print("-->",app_name,table_name)
#models_module = importlib.import_module('%s.models'%(app_name))
#model_obj = getattr(models_module,table_name)
admin_class = king_admin.enabled_admins[app_name][table_name]
#admin_class = king_admin.enabled_admins[crm][userprofile] #object_list = admin_class.model.objects.all()
object_list,filter_condtions = table_filter(request,admin_class) #过滤后的结果 object_list = table_search(request,admin_class,object_list) object_list,orderby_key = table_sort(request, admin_class, object_list) #排序后的结果
print("orderby key ", orderby_key)
paginator = Paginator(object_list, admin_class.list_per_page) # Show 25 contacts per page page = request.GET.get('page')
try:
query_sets = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
query_sets = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
query_sets = paginator.page(paginator.num_pages) return render(request,"king_admin/table_objs.html",{"admin_class":admin_class,
"query_sets":query_sets,
"filter_condtions":filter_condtions,
"orderby_key":orderby_key,
"previous_orderby": request.GET.get("o",''),
"search_text":request.GET.get('_q','')}) def table_obj_add(request,app_name,table_name):
admin_class = king_admin.enabled_admins[app_name][table_name]
model_form_class = create_model_form(request,admin_class) if request.method == "POST":
form_obj = model_form_class(request.POST) #
if form_obj.is_valid():
form_obj.save()
return redirect(request.path.replace("/add/","/"))
else:
form_obj = model_form_class() return render(request, "king_admin/table_obj_add.html", {"form_obj": form_obj}) def table_obj_change(request,app_name,table_name,obj_id): admin_class = king_admin.enabled_admins[app_name][table_name]
model_form_class = create_model_form(request,admin_class) obj = admin_class.model.objects.get(id=obj_id)
if request.method == "POST":
form_obj = model_form_class(request.POST,instance=obj) #更新
if form_obj.is_valid():
form_obj.save()
else: form_obj = model_form_class(instance=obj) return render(request,"king_admin/table_obj_change.html",{"form_obj":form_obj})views.py
注解:
enabled_admins :register(model_class:表名,admin_class=None:表相关的类)
model_class._meta.app_label:相当于models.Customer._meta.app_label 结果为:app名:'crm'
model_class._meta.model_name:相当于models.Customer._meta.model_name 结果:'customer'
models.Customer._meta.verbose_name获取表的中文名
admin_class.model = model_class相当于models.Customer
enabled_admins[model_class._meta.app_label][model_class._meta.model_name] = admin_class 实例化类 (CustomerAdmin)
table_list: table_list = king_admin.enabled_admins 当前已经注册的表, enabled_admins 中存的app、表名
页面跳转的实现:
<a href="{% url 'table_objs' app_name table_name %}">url(r'^(\w+)/(\w+)/$', views.display_table_objs,name="table_objs"),
相当于:def table_objs((w+),(w+))的两个参数为app_name table_name 表详细信息显示页面:{% extends 'king_admin/table_index.html' %}
{% load tags %} {% block container %}
{{ admin_class.list_display }}
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">{% get_model_name admin_class %}
<a href="{{ request.path }}add/" class="pull-right">Add</a>
</h3> </div>
<div class="panel-body">
<div class="row">
<form class="" method="get">
{% for filter_field in admin_class.list_filters %}
<div class="col-lg-2">
<span>{{ filter_field }}</span>
{% render_filter_ele filter_field admin_class filter_condtions %}
</div> {% endfor %} <button type="SUBMIT" class="btn btn-success">检索</button> <hr>
<div class="row">
<div class="col-lg-2" >
<input type="search" name="_q" class="form-control" style="margin-left:15px" value="{{ search_text }}" placeholder="search by {% for search_field in admin_class.search_fields %}{{ search_field }},{% endfor %} ">
</div>
<div class="col-lg-2" >
<button type="SUBMIT" class="btn btn-success">search</button>
</div>
</div>
</form> </div> <table class="table table-hover">
<thead>
<tr>
{% for column in admin_class.list_display %}
{% build_table_header_column column orderby_key filter_condtions %}
{% endfor %}
</tr>
</thead>
<tfoot>
<tr>
<td>总计{{ query_sets.paginator.count }}条</td></tr>
</tfoot>
<tbody>
{# {% get_query_sets admin_class as query_sets %}#}
{% for obj in query_sets %}
<tr>
{% build_table_row request obj admin_class %}
</tr>
{% endfor %}
</tbody> </table> <nav>
<ul class="pagination">
{% if query_sets.has_previous %}
<li class=""><a href="?page={{ query_sets.previous_page_number }}">上页</a></li>
{% endif %}
{# <li class="active"><a>{{ query_sets.number }}</a></li>#} {# {% for loop_counter in query_sets.paginator.page_range %}#}
{# {% render_page_ele loop_counter query_sets filter_condtions%}#}
{# {% endfor %}#} {% build_paginators query_sets filter_condtions previous_orderby search_text%} {% if query_sets.has_next %}
<li class=""><a href="?page={{ query_sets.next_page_number }}">下页</a></li>
{% endif %} {# <li class="disabled"><a href="#">«</a></li>#}
{# <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li>#}
{# #}
</ul>
</nav> </div>
</div>
{% endblock %}table_objs.html
from django.shortcuts import render,redirect
import importlib
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from king_admin.utils import table_filter,table_sort,table_search
# Create your views here.
from king_admin import king_admin
from king_admin.forms import create_model_form def index(request):
#print(king_admin.enabled_admins['crm']['customerfollowup'].model ) return render(request, "king_admin/table_index.html",{'table_list':king_admin.enabled_admins}) def display_table_objs(request,app_name,table_name): print("-->",app_name,table_name)
#models_module = importlib.import_module('%s.models'%(app_name))
#model_obj = getattr(models_module,table_name)
admin_class = king_admin.enabled_admins[app_name][table_name]
#admin_class = king_admin.enabled_admins[crm][userprofile] #object_list = admin_class.model.objects.all()
object_list,filter_condtions = table_filter(request,admin_class) #过滤后的结果 object_list = table_search(request,admin_class,object_list) object_list,orderby_key = table_sort(request, admin_class, object_list) #排序后的结果
print("orderby key ", orderby_key)
paginator = Paginator(object_list, admin_class.list_per_page) # Show 25 contacts per page page = request.GET.get('page')
try:
query_sets = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
query_sets = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
query_sets = paginator.page(paginator.num_pages) return render(request,"king_admin/table_objs.html",{"admin_class":admin_class,
"query_sets":query_sets,
"filter_condtions":filter_condtions,
"orderby_key":orderby_key,
"previous_orderby": request.GET.get("o",''),
"search_text":request.GET.get('_q','')}) def table_obj_add(request,app_name,table_name):
admin_class = king_admin.enabled_admins[app_name][table_name]
model_form_class = create_model_form(request,admin_class) if request.method == "POST":
form_obj = model_form_class(request.POST) #
if form_obj.is_valid():
form_obj.save()
return redirect(request.path.replace("/add/","/"))
else:
form_obj = model_form_class() return render(request, "king_admin/table_obj_add.html", {"form_obj": form_obj}) def table_obj_change(request,app_name,table_name,obj_id): admin_class = king_admin.enabled_admins[app_name][table_name]
model_form_class = create_model_form(request,admin_class) obj = admin_class.model.objects.get(id=obj_id)
if request.method == "POST":
form_obj = model_form_class(request.POST,instance=obj) #更新
if form_obj.is_valid():
form_obj.save()
else: form_obj = model_form_class(instance=obj) return render(request,"king_admin/table_obj_change.html",{"form_obj":form_obj})views
#__author: Administrator
#date: 2017/1/5 from django import template
from django.utils.safestring import mark_safe
from django.utils.timezone import datetime,timedelta
register = template.Library() @register.simple_tag
def render_app_name(admin_class):
return admin_class.model._meta.verbose_name @register.simple_tag
def get_query_sets(admin_class):
return admin_class.model.objects.all() @register.simple_tag
def build_table_row(request, obj,admin_class):
row_ele = ""
for index,column in enumerate(admin_class.list_display):
field_obj = obj._meta.get_field(column)
if field_obj.choices:#choices type
column_data = getattr(obj,"get_%s_display" % column)()
else:
column_data = getattr(obj,column) if type(column_data).__name__ == 'datetime':
column_data = column_data.strftime("%Y-%m-%d %H:%M:%S") if index == 0: #add a tag, 可以跳转到修改页
column_data = "<a href='{request_path}{obj_id}/change/'>{data}</a>".format(request_path=request.path,
obj_id=obj.id,
data=column_data)
row_ele += "<td>%s</td>" % column_data return mark_safe(row_ele) @register.simple_tag
def build_paginators(query_sets,filter_condtions,previous_orderby,search_text):
'''返回整个分页元素'''
page_btns = ''
filters = ''
for k,v in filter_condtions.items():
filters += "&%s=%s" %(k,v) added_dot_ele = False #
for page_num in query_sets.paginator.page_range:
if page_num < 3 or page_num > query_sets.paginator.num_pages -2 \
or abs(query_sets.number - page_num) <= 2: #代表最前2页或最后2页 #abs判断前后1页
ele_class = ""
if query_sets.number == page_num:
added_dot_ele = False
ele_class = "active"
page_btns += '''<li class="%s"><a href="?page=%s%s&o=%s&_q=%s">%s</a></li>''' % (
ele_class, page_num, filters,previous_orderby, search_text,page_num)
# elif abs(query_sets.number - page_num) <= 1: #判断前后1页
# ele_class = ""
# if query_sets.number == page_num:
# added_dot_ele = False
# ele_class = "active"
# page_btns += '''<li class="%s"><a href="?page=%s%s">%s</a></li>''' % (
# ele_class, page_num, filters, page_num)
else: #显示...
if added_dot_ele == False: #现在还没加...
page_btns += '<li><a>...</a></li>'
added_dot_ele = True return mark_safe(page_btns) @register.simple_tag
def render_page_ele(loop_counter,query_sets,filter_condtions):
filters = ''
for k,v in filter_condtions.items():
filters += "&%s=%s" %(k,v) if loop_counter <3 or loop_counter > query_sets.paginator.num_pages -2 : #代表这是前2页 or 最后2页
ele_class = ""
if query_sets.number == loop_counter:
ele_class = "active"
ele = '''<li class="%s"><a href="?page=%s%s">%s</a></li>''' %(ele_class,loop_counter,filters,loop_counter) return mark_safe(ele) if abs(query_sets.number - loop_counter) <= 1:
ele_class = ""
if query_sets.number == loop_counter:
ele_class = "active"
ele = '''<li class="%s"><a href="?page=%s%s">%s</a></li>''' %(ele_class,loop_counter,filters,loop_counter) return mark_safe(ele)
else:
return '...'
return '' @register.simple_tag
def render_filter_ele(filter_field,admin_class,filter_condtions):
#select_ele = '''<select class="form-control" name='%s' ><option value=''>----</option>''' %filter_field
select_ele = '''<select class="form-control" name='{filter_field}' ><option value=''>----</option>'''
field_obj = admin_class.model._meta.get_field(filter_field)
if field_obj.choices:
selected = ''
for choice_item in field_obj.choices:
print("choice",choice_item,filter_condtions.get(filter_field),type(filter_condtions.get(filter_field)))
if filter_condtions.get(filter_field) == str(choice_item[0]):
selected ="selected" select_ele += '''<option value='%s' %s>%s</option>''' %(choice_item[0],selected,choice_item[1])
selected ='' if type(field_obj).__name__ == "ForeignKey":
selected = ''
for choice_item in field_obj.get_choices()[1:]:
if filter_condtions.get(filter_field) == str(choice_item[0]):
selected = "selected"
select_ele += '''<option value='%s' %s>%s</option>''' %(choice_item[0],selected,choice_item[1])
selected = ''
if type(field_obj).__name__ in ['DateTimeField','DateField']:
date_els = []
today_ele = datetime.now().date()
date_els.append(['今天', datetime.now().date()])
date_els.append(["昨天",today_ele - timedelta(days=1)])
date_els.append(["近7天",today_ele - timedelta(days=7)])
date_els.append(["本月",today_ele.replace(day=1)])
date_els.append(["近30天",today_ele - timedelta(days=30)])
date_els.append(["近90天",today_ele - timedelta(days=90)])
date_els.append(["近180天",today_ele - timedelta(days=180)])
date_els.append(["本年",today_ele.replace(month=1,day=1)])
date_els.append(["近一年",today_ele - timedelta(days=365)]) selected = ''
for item in date_els:
select_ele += '''<option value='%s' %s>%s</option>''' %(item[1],selected,item[0]) filter_field_name = "%s__gte" % filter_field else:
filter_field_name = filter_field
select_ele += "</select>"
select_ele = select_ele.format(filter_field=filter_field_name) return mark_safe(select_ele) @register.simple_tag
def build_table_header_column(column,orderby_key,filter_condtions):
filters = ''
for k,v in filter_condtions.items():
filters += "&%s=%s" %(k,v) ele = '''<th><a href="?{filters}&o={orderby_key}">{column}</a>
{sort_icon}
</th>'''
if orderby_key:
if orderby_key.startswith("-"):
sort_icon = '''<span class="glyphicon glyphicon-chevron-up"></span>'''
else:
sort_icon = '''<span class="glyphicon glyphicon-chevron-down"></span>''' if orderby_key.strip("-") == column: #排序的就是这个字段
orderby_key =orderby_key
else:
orderby_key = column
sort_icon = '' else: #没有排序
orderby_key = column
sort_icon = '' ele = ele.format(orderby_key=orderby_key, column=column,sort_icon=sort_icon,filters=filters)
return mark_safe(ele ) @register.simple_tag
def get_model_name(admin_class): return admin_class.model._meta.verbose_nametags.py
#__author: Administrator
#date: 2017/1/5
from django.db.models import Q def table_filter(request,admin_class):
'''进行条件过滤并返回过滤后的数据'''
filter_conditions = {}
keywords = ['page','o','_q']
for k,v in request.GET.items():
if k in keywords:#保留的分页关键字 and 排序关键字
continue
if v:
filter_conditions[k] =v
print("filter coditions",filter_conditions) return admin_class.model.objects.filter(**filter_conditions).\
order_by("-%s" % admin_class.ordering if admin_class.ordering else "-id"),\
filter_conditions def table_sort(request,admin_class,objs):
orderby_key = request.GET.get("o")
if orderby_key:
res = objs.order_by(orderby_key)
if orderby_key.startswith("-"):
orderby_key = orderby_key.strip("-")
else:
orderby_key = "-%s"%orderby_key
else:
res = objs
return res,orderby_key def table_search(request,admin_class,object_list):
search_key = request.GET.get("_q","")
q_obj = Q()
q_obj.connector = "OR"
for column in admin_class.search_fields:
q_obj.children.append(("%s__contains"%column, search_key)) res = object_list.filter(q_obj)
return resutils.py
注解:admin_class = king_admin.enabled_admins[app_name][table_name] 相当于:admin_class = {'crm':{'Customer':" ",'CustomerFollow':" "]}
request.GET:获取网址红色的部分:http://127.0.0.1:8000/king_admin/crm/customer/?source=0&consultant=1&consult_course=1&status=0&date__gte=&_q=
以字典的形式展示:{'date__gte': [''], 'consult_course': ['1'], 'status': ['0'], 'source': ['0'], 'consultant': ['1'], '_q': ['']}>
filter coditions {'source': '0', 'status': '0', 'consult_course': '1', 'consultant': '1'}admin_class.model.objects.filter(**filter_conditions).order_by("-%s" % admin_class.ordering if admin_class.ordering else "-id"),
order_by:以" "分组 (**filter_conditions):查找条件字典格式filter_conditions:过滤后的数据
CRM客户关系管理系统知识点总结的更多相关文章
- Django CRM客户关系管理系统
CRM需求分析 随着信息化时代带来的科技创新,CRM客户关系管理系统带来的效益在已经成为很多企业提高竞争优势的一分部,CRM客户关系管理系统将企业管理和客户关系管理集成到统一的平台,其系统功能主要体现 ...
- CRM客户关系管理系统-需求概设和详设
大概设计 大概设计就是对需求进行一个整体性分析,把需要实现的功能都列出来,对于客户关系管理系统,我们需要从角色出发,从而确定有哪些需求,最好是画个思维导图 首先我们是为培训学校这么一个场景来开发的,所 ...
- CRM 客户关系管理系统
CRM(Customer Relationship Manager)客户关系管理系统 企业为提高核心竞争力,利用相应的信息技术以及互联网技术协调企业与顾客间在销售.营销和服务上的交互,从而提升其管理方 ...
- CRM客户关系管理系统 北京易信软科信息技术有限公司
北京易信软科信息技术有限公司 推出大型erp系统,库存管理系统,客户关系管理系统,车辆登记管理系统,员工管理系统,采购管理系统,销售管理系统,为您的企业提供最优质的产品服务 北京易信软科您可信赖的北京 ...
- CRM客户关系管理系统有哪些优缺点?
CRM系统不仅仅是一种技术,也是面向企业的客户管理系统.客户关系管理软件可以帮助销售员快速地找到客户信息,帮助销售员跟踪客户直到完成订单.为提高企业销售效率,CRM被越来越多的企业所采用. 那么,作为 ...
- CRM客户关系管理系统(一)
第一章.CRM介绍和开发流程 1.1.CRM简介 客户关系管理(CRM) 客户关系管理(customer relationship management)的定义是:企业为提高核心竞争力,利用相应的信息 ...
- Django项目:CRM(客户关系管理系统)--84--74PerfectCRM实现CRM权限和权限组限制访问URL
#models.py # ————————01PerfectCRM基本配置ADMIN———————— from django.db import models # Create your models ...
- Django项目:CRM(客户关系管理系统)--85--75PerfectCRM实现CRM扩展权限
# sales_urls.py # ————————47PerfectCRM实现CRM客户报名流程———————— from django.conf.urls import url from bpm. ...
- Django项目:CRM(客户关系管理系统)--82--72PerfectCRM实现CRM动态菜单和角色
#models.py # ————————01PerfectCRM基本配置ADMIN———————— from django.db import models # Create your models ...
随机推荐
- C#当中利用Attribute实现简易AOP
首先看一段简单的代码: public partial class Form1 : Form { public Form1() { InitializeComponent(); } //来自UI层的调用 ...
- js中的函参(arguments)
函参,顾名思义,就是函数的参数,一般我们的js函数这么写: function sum(a,b){ console.log(a+b); } 不难看出,这实现了两个数的相加,比如sum(1,2),打印结果 ...
- Git介绍及基本操作
Git基本概念 在Git中,我们将需要进行版本控制的文件目录叫做一个仓库(repository),每个仓库可以简单理解成一个目录,这个目录里面的所有文件都通过Git来实现版本管理,Git都能跟踪并记录 ...
- animal farm 第一章阅读笔记
chapter 1 Old Major's dream. paragraph 1 //Mr Jones is the mastor of the Manor Farm.That night ...
- c语言编译执行过程
<h4>认识C编译执行过程</h4>认识C编译执行过程,是C学习的开端.简单说C语言从编码编译到执行要经历一下过程: C源代码编译---->形成目标代码,目标代码是在目标 ...
- 缓存(Cache)管理 ---- 系列文章
利用Cache防止同一帐号重复登录 .net中Cache管理操作 系统缓存全解析 (下) 系统缓存全解析 (中) 系统缓存全解析 (上) 出处:http://www.cnblogs.com/luckd ...
- java工具类mht转html格式文件 及简单的HTML解析
package com.szy.project.utils; import java.io.BufferedInputStream; import java.io.BufferedOutputStre ...
- 使用VS2017 编写Linux系统上的Opencv程序
背景 之前写图像算法的程序都是在window10下使用VS编写,VS这个IDE结合“ImageWatch.vsix“插件,用于调试opencv相关的图像算法程序十分方便.后因项目需要,需将相关程序移植 ...
- java代码 求和1+1/2+1/3+1/4+1/5+1/6+.......+1/n 的值~~~~
总结:很简单的练习: s=1+1/2+1/3+1/4+1/5+1/6+.......+1/n的值:注意这里的s是float型,绝对记住不能留整数型 即s+=1/i; package com.c2; i ...
- appium控制Android按键
按键的keycode,如下: KEYCODE_HOME Home键 3 KEYCODE_BACK 返回键 4 KEYCODE_CALL 拨号键 5 KEYCODE_ENDCALL 挂机键 6 KEYC ...