CRM目录结构

from django.shortcuts import  HttpResponse,render,redirect
from django.conf.urls import url
from django.utils.safestring import mark_safe
from django.urls import reverse
from django.forms import ModelForm
from stark.utils.my_page import Pagination
from django.db.models import Q class ShowList(object):
def __init__(self,config_obj,queryset,request):
self.config_obj = config_obj
self.queryset = queryset
self.request = request
self.page_obj = Pagination(self.request.GET.get('page',1),self.queryset.count(),self.request.GET)
self.page_queryset = self.queryset[self.page_obj.start:self.page_obj.end] def get_header(self):
# 表头数据 [str1,str2,]
head_list = []
for head_field in self.config_obj.get_new_list_display():
if isinstance(head_field, str):
if head_field == '__str__':
val = self.config_obj.model._meta.model_name.upper()
else:
val = self.config_obj.model._meta.get_field(head_field).verbose_name
else:
val = head_field(self.config_obj, is_header=True)
head_list.append(val)
return head_list def get_body(self):
# 表单数据 [[attr1,attr2,],[attr1,attr2,],[]]
body_list = []
for data in self.page_queryset:
tmp = []
for field in self.config_obj.get_new_list_display():
if isinstance(field, str):
val = getattr(data, field)
if field != '__str__':
field_obj = self.config_obj.model._meta.get_field(field)
if field_obj.choices:
val = getattr(data,'get_'+field+'_display')
if field in self.config_obj.list_display_links:
_url = self.config_obj.get_reverse_url('edit', data)
val = mark_safe('<a href="%s">%s</a>' % (_url, val))
else:
val = field(self.config_obj, obj=data)
tmp.append(val)
body_list.append(tmp)
return body_list def get_action(self):
# action标签渲染
tmp = []
for action in self.config_obj.actions:
tmp.append({
'name': action.__name__,
'desc': action.desc
})
return tmp def get_filter(self):
tmp_dict = {}
for field in self.config_obj.list_filter:
rel_model = self.config_obj.model._meta.get_field(field).rel.to
rel_queryset = rel_model.objects.all()
click_id = self.request.GET.get(field)
tmp = [] import copy
params1 = copy.deepcopy(self.request.GET)
if field in params1:
params1.pop(field)
s = mark_safe("<a href='?%s'>All</a>"%params1.urlencode())
else:
s = mark_safe("<a href=''>All</a>")
tmp.append(s) for data in rel_queryset:
import copy
params = copy.deepcopy(self.request.GET)
params[field] = data.pk
if click_id == str(data.pk):
s = mark_safe('<a href="?%s" class="active">%s</a>'%(params.urlencode(),str(data)))
else:
s = mark_safe('<a href="?%s">%s</a>'%(params.urlencode(),str(data)))
tmp.append(s)
tmp_dict[field] = tmp
return tmp_dict class ModelStark(object):
list_display = ['__str__',]
list_display_links = []
model_form_class = None
search_fields = []
actions = []
list_filter = [] def __init__(self,model):
self.model = model
self.app_label = self.model._meta.app_label
self.model_name = self.model._meta.model_name
self.key_word = '' def cho_col(self,is_header=False,obj=None):
if is_header:
return '选择'
return mark_safe("<input type='checkbox' value='%s' name='selected_actions'>"%obj.pk) def edit_col(self,is_header=False,obj=None):
if is_header:
return '编辑'
_url = self.get_reverse_url('edit',obj)
return mark_safe('<a href="%s">编辑</a>'%_url) def del_col(self,is_header=False,obj=None):
if is_header:
return '删除'
_url = self.get_reverse_url('delete',obj)
return mark_safe('<a href="%s">删除</a>'%_url) def get_reverse_url(self,type,obj=None):
if obj:
_url = reverse('%s_%s_%s'%(self.app_label,self.model_name,type),args=(obj.pk,))
else:
_url = reverse('%s_%s_%s'%(self.app_label,self.model_name,type))
return _url def get_new_list_display(self):
tmp = []
tmp.append(ModelStark.cho_col)
tmp.extend(self.list_display)
if not self.list_display_links:
tmp.append(ModelStark.edit_col)
tmp.append(ModelStark.del_col)
return tmp def get_search(self,request,queryset):
key_word = request.GET.get('q')
self.key_word = ''
if key_word:
self.key_word = key_word
q = Q()
q.connector = 'or'
for search_field in self.search_fields:
q.children.append((search_field + '__icontains', key_word))
queryset = queryset.filter(q)
return queryset def get_filter(self,request,queryset):
q = Q()
for field,field_id in request.GET.items():
if field in ['page','q']:
continue
field_id = request.GET.get(field)
q.children.append((field, field_id))
queryset = queryset.filter(q)
return queryset def list_view(self,request):
# action功能
if request.method == 'POST':
pk_list = request.POST.getlist('selected_actions')
action = request.POST.get('action')
if action:
action_func = getattr(self,action)
queryset = self.model.objects.filter(pk__in=pk_list)
action_func(request,queryset) queryset = self.model.objects.all()
# search功能
queryset = self.get_search(request,queryset)
# filter功能
queryset = self.get_filter(request,queryset) show_obj = ShowList(self,queryset,request) url = self.get_reverse_url('add')
return render(request, 'stark/list.html', locals()) def get_model_form_class(self):
if self.model_form_class:
return self.model_form_class
class ModelFormClass(ModelForm):
class Meta:
model = self.model
fields = '__all__'
return ModelFormClass def add_view(self,request):
model_form_class = self.get_model_form_class()
if request.method == 'POST':
model_form_obj = model_form_class(request.POST)
pop_back_id = request.GET.get('pop_back_id')
if model_form_obj.is_valid():
obj = model_form_obj.save()
print(obj)
if pop_back_id:
pk = obj.pk
text = str(obj)
return render(request, 'stark/pop.html', locals())
return redirect(self.get_reverse_url('list'))
model_form_obj = model_form_class()
for form_field in model_form_obj:
from django.forms.models import ModelChoiceField
if isinstance(form_field.field,ModelChoiceField):
form_field.is_pop = True
rel_model = self.model._meta.get_field(form_field.name).rel.to
rel_app_label = rel_model._meta.app_label
rel_model_name = rel_model._meta.model_name
url = reverse('%s_%s_add'%(rel_app_label,rel_model_name))
url = url + '?pop_back_id=' + form_field.auto_id
form_field.url = url
return render(request, 'stark/add.html', locals()) def edit_view(self,request,id):
model_form_class = self.get_model_form_class()
edit_obj = self.model.objects.filter(pk=id).first()
if request.method == 'POST':
model_form_obj = model_form_class(request.POST,instance=edit_obj)
if model_form_obj.is_valid():
model_form_obj.save()
return redirect(self.get_reverse_url('list'))
model_form_obj = model_form_class(instance=edit_obj)
return render(request, 'stark/edit.html', locals()) def delete_view(self,request,id):
delete_obj = self.model.objects.filter(pk=id).delete()
return redirect(self.get_reverse_url('list')) def get_urls(self):
tmp = [
url(r'^$',self.list_view,name='%s_%s_list'%(self.app_label,self.model_name)),
url(r'^add/',self.add_view,name='%s_%s_add'%(self.app_label,self.model_name)),
url(r'edit/(\d+)/',self.edit_view,name='%s_%s_edit'%(self.app_label,self.model_name)),
url(r'delete/(\d+)/',self.delete_view,name='%s_%s_delete'%(self.app_label,self.model_name))
]
tmp.extend(self.extra_url())
return tmp,None,None def extra_url(self):
return [] class AdminSite(object):
def __init__(self, name='admin'):
self._registry = {} # model_class class -> admin_class instance def register(self, model, admin_class=None, **options):
if not admin_class:
admin_class = ModelStark
self._registry[model] = admin_class(model) def get_urls(self):
tmp = []
for class_name,config_obj in self._registry.items():
app_label = class_name._meta.app_label
model_name = class_name._meta.model_name
tmp.append(
url(r'^%s/%s/'%(app_label,model_name),config_obj.get_urls())
)
return tmp @property
def urls(self):
return self.get_urls(), None, None site = AdminSite()

service/stark.py

class Pagination(object):
def __init__(self, current_page, all_count,params, per_page_num=10, pager_count=11):
"""
封装分页相关数据
:param current_page: 当前页
:param all_count: 数据库中的数据总条数
:param per_page_num: 每页显示的数据条数
:param pager_count: 最多显示的页码个数 用法:
queryset = model.objects.all()
page_obj = Pagination(current_page,all_count)
page_data = queryset[page_obj.start:page_obj.end]
获取数据用page_data而不再使用原始的queryset
获取前端分页样式用page_obj.page_html
"""
try:
current_page = int(current_page)
except Exception as e:
current_page = 1 if current_page < 1:
current_page = 1 self.current_page = current_page self.all_count = all_count
self.per_page_num = per_page_num # 总页码
all_pager, tmp = divmod(all_count, per_page_num)
if tmp:
all_pager += 1
self.all_pager = all_pager self.pager_count = pager_count
self.pager_count_half = int((pager_count - 1) / 2) import copy
self.params = copy.deepcopy(params) @property
def start(self):
return (self.current_page - 1) * self.per_page_num @property
def end(self):
return self.current_page * self.per_page_num def page_html(self):
# 如果总页码 < 11个:
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
# 总页码 > 11
else:
# 当前页如果<=页面上最多显示11/2个页码
if self.current_page <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1 # 当前页大于5
else:
# 页码翻到最后
if (self.current_page + self.pager_count_half) > self.all_pager:
pager_end = self.all_pager + 1
pager_start = self.all_pager - self.pager_count + 1
else:
pager_start = self.current_page - self.pager_count_half
pager_end = self.current_page + self.pager_count_half + 1 page_html_list = []
# 添加前面的nav和ul标签
page_html_list.append('''
<nav aria-label='Page navigation>'
<ul class='pagination'>
''')
first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
page_html_list.append(first_page) if self.current_page <= 1:
prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
else:
prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,) page_html_list.append(prev_page) res = self.params
for i in range(pager_start, pager_end):
res['page'] = i
if i == self.current_page:
temp = '<li class="active"><a href="?%s">%s</a></li>' % (res.urlencode(), i,)
else:
temp = '<li><a href="?%s">%s</a></li>' % (res.urlencode(), i,)
page_html_list.append(temp) if self.current_page >= self.all_pager:
next_page = '<li class="disabled"><a href="#">下一页</a></li>'
else:
next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
page_html_list.append(next_page) last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
page_html_list.append(last_page)
# 尾部添加标签
page_html_list.append('''
</nav>
</ul>
''')
return ''.join(page_html_list)

utils/my_page

templates/stark

{% extends 'stark/base.html' %}

{% block css %}
<link rel="stylesheet" href="/static/css/common.css">
{% endblock %}
{% block content %} <h3>添加数据</h3>
<form action="" method="post">
{% csrf_token %}
{% for foo in model_form_obj %}
<div class="form-inline fa-plus">
<p>{{ foo.label }}{{ foo }}</p>
{% if foo.is_pop %}
<span class="plus" onclick="openWindow('{{ foo.url }}')">+</span>
{% endif %}
</div>
{% endfor %}
<input type="submit" class="btn btn-info pull-right">
</form> <script>
function openWindow(url) {
window.open(url,'','width=800px,height=400px');
} function add_options(pop_back_id,pk,text) {
var opEle = document.createElement('option');
opEle.value = pk;
opEle.innerText = text;
opEle.selected = 'selected';
var seEle = document.getElementById(pop_back_id);
seEle.appendChild(opEle);
}
</script> {% endblock %}

add.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<style>
.table {
margin-top: 10px;
}
.active {
color: red;
}
.fa-plus {
position: relative;
}
.plus {
font-size: 24px;
color: #336699;
position: absolute;
right: -31px;
top: 19px;
}
</style>
{% block css %} {% endblock %}
</head>
<body>
{# 导航条开始 #}
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="#">CRM</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>{% if request.session.user %}
<a href="">{{ request.session.user }}</a>
{% else %}
<a href="/login/">登陆</a>
{% endif %}</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="/logout/">注销</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{# 导航条结束 #} <div class="container">
<div class="row">
<div class="col-md-3">
<div class="menu">
<p><a href="/index">首页</a></p>
{% for foo in request.session.permission_menu_list %}
<p><a href="{{ foo.url }}">{{ foo.title }}</a></p>
{% endfor %}
</div>
</div>
<div class="col-md-9">
{% block content %} {% endblock %}
</div>
</div>
</div> </body>
</html>

base.html

{% extends 'stark/base.html' %}

{% block css %}
<link rel="stylesheet" href="/static/css/common.css">
{% endblock %}
{% block content %} <h3>编辑数据</h3>
<form action="" method="post">
{% csrf_token %}
{% for foo in model_form_obj %}
<p>{{ foo.label }}{{ foo }}</p>
{% endfor %}
<input type="submit" class="btn btn-success pull-right">
</form> {% endblock %}

edit.html

{% extends 'stark/base.html' %}

{% block content %}
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>...</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}

index

{% extends 'stark/base.html' %}

{% block css %}
<script src="/static/js/check.js"></script>
{% endblock %} {% block content %}
<h3>查看数据</h3>
<a href="{{ url }}" class="btn btn-primary">添加数据</a>
{# search功能开始#}
{% if show_obj.config_obj.search_fields %}
<form class="form-inline pull-right">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" id="exampleInputAmount" placeholder="关键字" name="q"
value="{{ show_obj.config_obj.key_word }}">
</div>
</div>
<button type="submit" class="btn btn-danger">Search</button>
</form>
{% endif %}
{# search功能结束#}
{# action功能开始#}
<form action="" class="form-inline" method="post">
{% csrf_token %}
<select class="form-control" name="action">
<option value="">-------------------------</option>
{% for foo in show_obj.get_action %}
<option value="{{ foo.name }}">{{ foo.desc }}</option>
{% endfor %}
</select>
<input type="submit" value="Go!" class="btn btn-info">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
{% for head in show_obj.get_header %}
<th>{{ head }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for data in show_obj.get_body %}
<tr>
{% for foo in data %}
<td>{{ foo }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</form>
{{ show_obj.page_obj.page_html|safe }} {% if show_obj.config_obj.list_filter %}
<div class="col-md-3">
<div class="alert-info text-center">FILTER</div>
{% for foo,data_list in show_obj.get_filter.items %}
<div class="panel panel-default">
<div class="panel-heading">By {{ foo }}</div>
<div class="panel-body">
{% for data in data_list %}
<p>{{ data }}</p>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
{% endif %} {% endblock %}

list.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
window.opener.add_options('{{ pop_back_id }}','{{ pk }}','{{ text }}');
window.close(); </script> </body>
</html>

pop.html

permissionmiddle

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,HttpResponse
import re class PermissionMiddleWare(MiddlewareMixin):
def process_request(self,request):
# 当前用户访问路径
current_path = request.path
# 用户访问白名单
white_list = ['/login/','/admin/*']
for white_permission in white_list:
res = re.search(white_permission,current_path)
if res:
return None
# 校验是否登陆
if not request.session.get('user'):
return redirect('/login')
# 获取当前用户访问权限
permission_list = request.session.get('permission_list') # 判断是否有权访问 for permission_rex in permission_list:
permission_rex = '^%s$'%permission_rex
res = re.search(permission_rex,current_path)
if res:
return None
return HttpResponse('没有访问权限')

permission.py

static/js

window.onload = function () {
$('.xxx').change(function () {
var status = $(this).val();
var pk = $(this).attr('pk');
$.ajax({
url:'/stark/app01/studentstudyrecord/check_work/',
type:'post',
data:{
status:status,
pk:pk
},
success:function (data) {
console.log(data)
}
})
})
};

check.js

app01

from django.shortcuts import render,redirect
from app01 import models
# Create your views here.
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user_obj = models.User.objects.filter(name=username,pwd=password).first()
if user_obj:
# 记录登陆状态
request.session['user'] = username
# 记录权限列表
permission_list = []
permission_menu_list = []
res = user_obj.roles.values('permissions__url','permissions__title','permissions__code').distinct()
for permission in res:
permission_list.append(permission.get('permissions__url'))
if permission.get('permissions__code') == 'list':
permission_menu_list.append({
'url':permission.get('permissions__url'),
'title':permission.get('permissions__title'),
})
request.session['permission_menu_list'] = permission_menu_list
request.session['permission_list'] = permission_list
return redirect('/index')
return render(request,'login.html') def logout(request):
request.session.clear()
return redirect('/index') def index(request):
return render(request,'stark/index.html')

views.py

from app01 import models
from stark.service.stark import site,ModelStark
from django.utils.safestring import mark_safe
from django.conf.urls import url
from django.shortcuts import render,redirect,HttpResponse class UserConfig(ModelStark):
list_display = ['name','pwd','roles'] site.register(models.User,UserConfig)
site.register(models.Role)
class PermissionConfig(ModelStark):
list_display = ['title','url']
list_display_links = ['title']
site.register(models.Permission,PermissionConfig) # CRM相关表
site.register(models.School)
site.register(models.Course)
site.register(models.Department)
site.register(models.UserInfo)
site.register(models.ClassList) class CustomerConfig(ModelStark):
def show_consult_course(self,is_header=False,obj=None):
if is_header:
return '咨询课程'
course_list = []
for course in obj.course.all():
course_list.append('<a href="/stark/app01/customer/cancel_course/%s/%s/" style="border: 1px solid blue;padding: 3px 6px">%s</a>'%(obj.pk,course.pk,course.name))
return mark_safe(' '.join(course_list)) def cancel_course(self, request, customer_id, course_id):
customer_obj = models.Customer.objects.filter(pk=customer_id).first()
customer_obj.course.remove(course_id)
return redirect(self.get_reverse_url('list')) def extra_url(self):
tmp = []
tmp.append(
url(r'^cancel_course/(\d+)/(\d+)/', self.cancel_course)
)
return tmp
list_display = ['name','gender',show_consult_course] site.register(models.Customer,CustomerConfig) site.register(models.ConsultRecord)
site.register(models.Student) class ClassStudyRecordConfig(ModelStark):
def patch_init(self,request,queryset):
# queryset是选中的某个班级当天的课程记录
tmp = []
for course_record_obj in queryset:
student_list = models.Student.objects.filter(class_list=course_record_obj.class_obj.pk)
for student_obj in student_list:
obj = models.StudentStudyRecord(classstudyrecord=course_record_obj,student=student_obj)
tmp.append(obj)
models.StudentStudyRecord.objects.bulk_create(tmp)
patch_init.desc = '批量生成学生学习记录'
actions = [patch_init] def record(self,is_header=False,obj=None):
if is_header:
return '记录'
_url = '/stark/app01/studentstudyrecord/?classstudyrecord=%s'%obj.pk
return mark_safe("<a href='%s'>记录</a>"%_url) list_display = ['class_obj','day_num',record]
site.register(models.ClassStudyRecord,ClassStudyRecordConfig)
class StudentStudyRecordConfig(ModelStark):
def patch_late(self,request,queryset):
queryset.update(record='late')
patch_late.desc = '批量处理迟到'
actions = [patch_late] def work(self,is_header=False,obj=None):
if is_header:
return '考勤'
html = ''
for k in obj.record_choices:
if obj.record == k[0]:
s = "<option value='%s' selected>%s</option>"%k
else:
s = "<option value='%s' >%s</option>"%k
html += s
return mark_safe("<select class='xxx' pk=%s>%s</select>"%(obj.pk,html)) def check(self,request):
status = request.POST.get('status')
pk = request.POST.get('pk')
print(status,pk)
models.StudentStudyRecord.objects.filter(pk=pk).update(record=status)
return HttpResponse('ok') def extra_url(self):
tmp = []
tmp.append(
url(r'^check_work/',self.check)
)
return tmp list_display = ['classstudyrecord', 'student', 'record', 'score',work]
site.register(models.StudentStudyRecord,StudentStudyRecordConfig)

stark.py

from django.db import models

# Create your models here.
# rbac权限相关表格
class User(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
roles = models.ManyToManyField(to='Role') def __str__(self):
return self.name class Role(models.Model):
title = models.CharField(max_length=32)
permissions = models.ManyToManyField(to='Permission') def __str__(self):
return self.title class Permission(models.Model):
title = models.CharField(max_length=32)
url = models.CharField(max_length=32)
code = models.CharField(max_length=32,default='list') def __str__(self):
return self.title # CRM相关内部表
class School(models.Model):
"""
校区表
如:
北京沙河校区
上海校区 """
title = models.CharField(verbose_name='校区名称', max_length=32) def __str__(self):
return self.title class Course(models.Model):
"""
课程表
如:
Linux基础
Linux架构师
Python自动化开发精英班
Python自动化开发架构师班
Python基础班
go基础班
"""
name = models.CharField(verbose_name='课程名称', max_length=32) def __str__(self):
return self.name class Department(models.Model):
"""
部门表
市场部 1000
销售 1001 """
title = models.CharField(verbose_name='部门名称', max_length=16)
code = models.IntegerField(verbose_name='部门编号', unique=True, null=False) def __str__(self):
return self.title class UserInfo(models.Model):
"""
员工表
""" name = models.CharField(verbose_name='员工姓名', max_length=16)
email = models.EmailField(verbose_name='邮箱', max_length=64)
depart = models.ForeignKey(verbose_name='部门', to="Department",to_field="code")
user=models.OneToOneField("User",default=1)
def __str__(self):
return self.name class ClassList(models.Model):
"""
班级表
如:
Python全栈 面授班 5期 10000 2017-11-11 2018-5-11
"""
school = models.ForeignKey(verbose_name='校区', to='School')
course = models.ForeignKey(verbose_name='课程名称', to='Course')
semester = models.IntegerField(verbose_name="班级(期)") price = models.IntegerField(verbose_name="学费")
start_date = models.DateField(verbose_name="开班日期")
graduate_date = models.DateField(verbose_name="结业日期", null=True, blank=True)
memo = models.CharField(verbose_name='说明', max_length=256, blank=True, null=True, ) teachers = models.ManyToManyField(verbose_name='任课老师', to='UserInfo',limit_choices_to={'depart':1002})
tutor = models.ForeignKey(verbose_name='班主任', to='UserInfo',related_name="class_list",limit_choices_to={'depart':1006}) def __str__(self):
return "{0}({1}期)".format(self.course.name, self.semester) class Customer(models.Model):
"""
客户表
"""
qq = models.CharField(verbose_name='qq', max_length=64, unique=True, help_text='QQ号必须唯一') name = models.CharField(verbose_name='学生姓名', max_length=16)
gender_choices = ((1, '男'), (2, '女'))
gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choices) education_choices = (
(1, '重点大学'),
(2, '普通本科'),
(3, '独立院校'),
(4, '民办本科'),
(5, '大专'),
(6, '民办专科'),
(7, '高中'),
(8, '其他')
)
education = models.IntegerField(verbose_name='学历', choices=education_choices, blank=True, null=True, )
graduation_school = models.CharField(verbose_name='毕业学校', max_length=64, blank=True, null=True)
major = models.CharField(verbose_name='所学专业', max_length=64, blank=True, null=True) experience_choices = [
(1, '在校生'),
(2, '应届毕业'),
(3, '半年以内'),
(4, '半年至一年'),
(5, '一年至三年'),
(6, '三年至五年'),
(7, '五年以上'),
]
experience = models.IntegerField(verbose_name='工作经验', blank=True, null=True, choices=experience_choices)
work_status_choices = [
(1, '在职'),
(2, '无业')
]
work_status = models.IntegerField(verbose_name="职业状态", choices=work_status_choices, default=1, blank=True,
null=True)
company = models.CharField(verbose_name="目前就职公司", max_length=64, blank=True, null=True)
salary = models.CharField(verbose_name="当前薪资", max_length=64, blank=True, null=True) source_choices = [
(1, "qq群"),
(2, "内部转介绍"),
(3, "官方网站"),
(4, "百度推广"),
(5, "360推广"),
(6, "搜狗推广"),
(7, "腾讯课堂"),
(8, "广点通"),
(9, "高校宣讲"),
(10, "渠道代理"),
(11, "51cto"),
(12, "智汇推"),
(13, "网盟"),
(14, "DSP"),
(15, "SEO"),
(16, "其它"),
]
source = models.SmallIntegerField('客户来源', choices=source_choices, default=1)
referral_from = models.ForeignKey(
'self',
blank=True,
null=True,
verbose_name="转介绍自学员",
help_text="若此客户是转介绍自内部学员,请在此处选择内部学员姓名",
related_name="internal_referral"
)
course = models.ManyToManyField(verbose_name="咨询课程", to="Course") status_choices = [
(1, "已报名"),
(2, "未报名")
]
status = models.IntegerField(
verbose_name="状态",
choices=status_choices,
default=2,
help_text=u"选择客户此时的状态"
) consultant = models.ForeignKey(verbose_name="课程顾问", to='UserInfo', related_name='consultanter',limit_choices_to={'depart':1001}) date = models.DateField(verbose_name="咨询日期", auto_now_add=True)
recv_date = models.DateField(verbose_name="当前课程顾问的接单日期", null=True)
last_consult_date = models.DateField(verbose_name="最后跟进日期", ) def __str__(self):
return self.name class ConsultRecord(models.Model):
"""
客户跟进记录
"""
customer = models.ForeignKey(verbose_name="所咨询客户", to='Customer')
consultant = models.ForeignKey(verbose_name="跟踪人", to='UserInfo',limit_choices_to={'depart':1001})
date = models.DateField(verbose_name="跟进日期", auto_now_add=True)
note = models.TextField(verbose_name="跟进内容...") def __str__(self):
return self.customer.name + ":" + self.consultant.name class Student(models.Model):
"""
学生表(已报名)
"""
customer = models.OneToOneField(verbose_name='客户信息', to='Customer')
class_list = models.ManyToManyField(verbose_name="已报班级", to='ClassList', blank=True) emergency_contract = models.CharField(max_length=32, blank=True, null=True, verbose_name='紧急联系人')
company = models.CharField(verbose_name='公司', max_length=128, blank=True, null=True)
location = models.CharField(max_length=64, verbose_name='所在区域', blank=True, null=True)
position = models.CharField(verbose_name='岗位', max_length=64, blank=True, null=True)
salary = models.IntegerField(verbose_name='薪资', blank=True, null=True)
welfare = models.CharField(verbose_name='福利', max_length=256, blank=True, null=True)
date = models.DateField(verbose_name='入职时间', help_text='格式yyyy-mm-dd', blank=True, null=True)
memo = models.CharField(verbose_name='备注', max_length=256, blank=True, null=True) def __str__(self):
return self.customer.name class ClassStudyRecord(models.Model):
"""
上课记录表 (班级记录)
"""
class_obj = models.ForeignKey(verbose_name="班级", to="ClassList")
day_num = models.IntegerField(verbose_name="节次", help_text=u"此处填写第几节课或第几天课程...,必须为数字")
teacher = models.ForeignKey(verbose_name="讲师", to='UserInfo',limit_choices_to={'depart':1002})
date = models.DateField(verbose_name="上课日期", auto_now_add=True) course_title = models.CharField(verbose_name='本节课程标题', max_length=64, blank=True, null=True)
course_memo = models.TextField(verbose_name='本节课程内容概要', blank=True, null=True)
has_homework = models.BooleanField(default=True, verbose_name="本节有作业")
homework_title = models.CharField(verbose_name='本节作业标题', max_length=64, blank=True, null=True)
homework_memo = models.TextField(verbose_name='作业描述', max_length=500, blank=True, null=True)
exam = models.TextField(verbose_name='踩分点', max_length=300, blank=True, null=True) def __str__(self):
return "{0} day{1}".format(self.class_obj, self.day_num) class StudentStudyRecord(models.Model):
'''
学生学习记录
'''
classstudyrecord = models.ForeignKey(verbose_name="第几天课程", to="ClassStudyRecord")
student = models.ForeignKey(verbose_name="学员", to='Student') record_choices = (('checked', "已签到"),
('vacate', "请假"),
('late', "迟到"),
('noshow', "缺勤"),
('leave_early', "早退"),
)
record = models.CharField("上课纪录", choices=record_choices, default="checked", max_length=64)
score_choices = ((100, 'A+'),
(90, 'A'),
(85, 'B+'),
(80, 'B'),
(70, 'B-'),
(60, 'C+'),
(50, 'C'),
(40, 'C-'),
(0, ' D'),
(-1, 'N/A'),
(-100, 'COPY'),
(-1000, 'FAIL'),
)
score = models.IntegerField("本节成绩", choices=score_choices, default=-1)
homework_note = models.CharField(verbose_name='作业评语', max_length=255, blank=True, null=True)
note = models.CharField(verbose_name="备注", max_length=255, blank=True, null=True) homework = models.FileField(verbose_name='作业文件', blank=True, null=True, default=None)
stu_memo = models.TextField(verbose_name='学员备注', blank=True, null=True)
date = models.DateTimeField(verbose_name='提交作业日期', auto_now_add=True) def __str__(self):
return "{0}-{1}".format(self.classstudyrecord, self.student)

models.py

 

最新文章

  1. Rebuild Instance 操作详解 - 每天5分钟玩转 OpenStack(37)
  2. MVC中Control和View之间数据传递的方式
  3. WPF-拖动面板移动窗口&amp;设置窗口状态
  4. Codeforces Round #275 Div.1 B Interesting Array --线段树
  5. [Locked] Paint Fence
  6. hdu 2896 病毒侵袭 AC自动机 基础题
  7. 《Java从入门到精通》src0-8
  8. Spring MVC ajax:post/get 的具体实现
  9. Python Celery队列
  10. HDU 6200 2017沈阳网络赛 树上区间更新,求和
  11. Day14 Javascript 点击添加出弹窗,取消隐藏弹窗小练习 反选,全选,取消边框
  12. Layui使用心得(1)---- 数据表格
  13. BUAAOO第一单元的总结
  14. C# 使用System.Speech 进行语音播报和识别
  15. 滑雪(dp)
  16. uvalive 3415 Guardian Of Decency
  17. python--json&amp;pickle模块
  18. Three.js开发指南---使用高级几何体和二元操作(第六章)
  19. 强化学习 平台 openAI 的 gym 安装 (Ubuntu环境下如何安装Python的gym模块)
  20. Python全局变量和局部变量

热门文章

  1. python 02 if while
  2. CSS动画实例:太极图在旋转
  3. JDBC理论知识
  4. 团队作业4:第四篇Scrum冲刺博客(歪瑞古德小队)
  5. DVWA之文件上传(二)
  6. ent orm笔记2---schema使用(下)
  7. 树(Tree)解题总结
  8. jQuery捕获-获取DOM元素内容和属性
  9. 你懂RocketMQ 的架构原理吗?
  10. JavaScript(es6)数组常用的方法