一、项目需求(使用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="#">&laquo;</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_name

    tags.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 res

    utils.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客户关系管理系统知识点总结的更多相关文章

  1. Django CRM客户关系管理系统

    CRM需求分析 随着信息化时代带来的科技创新,CRM客户关系管理系统带来的效益在已经成为很多企业提高竞争优势的一分部,CRM客户关系管理系统将企业管理和客户关系管理集成到统一的平台,其系统功能主要体现 ...

  2. CRM客户关系管理系统-需求概设和详设

    大概设计 大概设计就是对需求进行一个整体性分析,把需要实现的功能都列出来,对于客户关系管理系统,我们需要从角色出发,从而确定有哪些需求,最好是画个思维导图 首先我们是为培训学校这么一个场景来开发的,所 ...

  3. CRM 客户关系管理系统

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

  4. CRM客户关系管理系统 北京易信软科信息技术有限公司

    北京易信软科信息技术有限公司 推出大型erp系统,库存管理系统,客户关系管理系统,车辆登记管理系统,员工管理系统,采购管理系统,销售管理系统,为您的企业提供最优质的产品服务 北京易信软科您可信赖的北京 ...

  5. CRM客户关系管理系统有哪些优缺点?

    CRM系统不仅仅是一种技术,也是面向企业的客户管理系统.客户关系管理软件可以帮助销售员快速地找到客户信息,帮助销售员跟踪客户直到完成订单.为提高企业销售效率,CRM被越来越多的企业所采用. 那么,作为 ...

  6. CRM客户关系管理系统(一)

    第一章.CRM介绍和开发流程 1.1.CRM简介 客户关系管理(CRM) 客户关系管理(customer relationship management)的定义是:企业为提高核心竞争力,利用相应的信息 ...

  7. Django项目:CRM(客户关系管理系统)--84--74PerfectCRM实现CRM权限和权限组限制访问URL

    #models.py # ————————01PerfectCRM基本配置ADMIN———————— from django.db import models # Create your models ...

  8. Django项目:CRM(客户关系管理系统)--85--75PerfectCRM实现CRM扩展权限

    # sales_urls.py # ————————47PerfectCRM实现CRM客户报名流程———————— from django.conf.urls import url from bpm. ...

  9. Django项目:CRM(客户关系管理系统)--82--72PerfectCRM实现CRM动态菜单和角色

    #models.py # ————————01PerfectCRM基本配置ADMIN———————— from django.db import models # Create your models ...

随机推荐

  1. C#基础知识梳理系列

    1. 这个系列深入的从IL层面谈了C#各种基本知识的本质,十分值得学习: http://www.cnblogs.com/solan/category/398748.html

  2. jQuery对象[0]倒底是什么?

    s[0]倒底是什么?(s为jQuery对象)代码:var s=$("div"); alert(s.length);alert(s[0]); jQuery对象默认都有个0索引,s为j ...

  3. OLE剪切板与拖拽

    https://www.xuebuyuan.com/1074399.html https://blog.csdn.net/uda1985/article/details/6179801

  4. Linux SVN 切换用户

    1.   临时切换 在所有命令前强制加上--username 和 --password 例如:svn up --username zhangsan --password 123456 2.   永久切 ...

  5. 用 WEKA 进行数据挖掘 ——第一章:简介

    1.简介数据挖掘.机器学习这些字眼,在一些人看来,是门槛很高的东西.诚然,如果做算法实现甚至算法优化,确实需要很多背景知识.但事实是,绝大多数数据挖掘工程师,不需要去做算法层面的东西.他们的精力,集中 ...

  6. Django之 路由系统

    Django的路由系统 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个URL调用这 ...

  7. ExpressionTree,Emit,反射

    ExpressionTree,Emit,反射 https://www.cnblogs.com/7tiny/p/9861166.html [前言] 前几日心血来潮想研究着做一个Spring框架,自然地就 ...

  8. jenkins部署应用

    1.    系统介绍 Jenkins系统提供了一键部署的作用,整个过程有从提测的分支抓取代码,编译,打包,把打的包部署在应用服务器上,基本有Service,Web和Worker等. 2.    Jen ...

  9. cnn(卷积神经网络)比较系统的讲解

    本文整理了网上几位大牛的博客,详细地讲解了CNN的基础结构与核心思想,欢迎交流. [1]Deep learning简介 [2]Deep Learning训练过程 [3]Deep Learning模型之 ...

  10. Hibernate HQL查询(2)

    hql是面向对象查询,格式:from + 类名 + 类对象 + where + 对象的属性 sql是面向数据库表查询,格式:from + 表名 + where + 表中字段 1.查询 一般在Hiber ...