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 ...
随机推荐
- eclipse mars4.5安装hibernate开发环境
在安装hibernate插件过程中遇到下面前三张图片所示的现象是没关系的,只要最后能看到第四张图的结果就说明安装成功,我一开始不知道走了好多弯路.我用的eclipse mars4.5,采用了在线安装的 ...
- JSP的三大指令
三大指令:page指令.include指令和taglib指令. page指令: * import:等同与import语句 <%@ page import="java.util.*& ...
- PhotoPicker 从头到脚
1. 简介 PhotoPicker, 是一款开源的图片选择器.效果上和微信相似. 2. 使用方法 2.1 添加依赖 dependencies { compile 'me.iwf.photopicker ...
- Build ios app with Delphi Xe4. Lazy Social Talker ready for sale.
Yes, it is build with Delphi XE4. try it. now. What is Lazy Social Talker? Lazy Social Talker is a ...
- InnoSetup使用笔记
今天用InnoSetup做安装包时,因为要装的驱动区分32位.64位,64位系统中要安装32位+64位驱动. 想在脚本中进行判断.折腾一阵,终于搞定: 参考了:http://379910987.blo ...
- HihoCoder 1185 : 连通性·三(强连通缩点)
连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出去,就拜托小Hi ...
- #507. 「LibreOJ NOI Round #1」接竹竿 dp
题目: 题解: 我们考虑把每对花色相同的牌看作区间. 那么如果我们设 \(f_i\) 表示决策在 \([1,i]\) 内的最优答案. 那么有 \(f_i = max\{max\{(f_{j-1}+\s ...
- noip积木大赛
先要覆盖一号位置的高度,(现在你的目的只是想要覆盖一号位置). 每次你可以选区间[l,r]高度+1,这个作为一个操作. 为什么不选的范围大一点,让更多的区间增加高度呢. 所以红色的地方是,在我的目的是 ...
- 数据库模型类转换实体类的dbToPojoUtil工具类开发
idea颜色说明http://blog.csdn.net/saindy5828/article/details/53319693 1,中途运用了properties,properties.getPro ...
- Flex布局(转载)
网页布局(layout)是 CSS 的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性.它对于那些特殊布局非常不方便,比如,垂 ...