CRM、用戶管理權限

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 Qclass ShowList(object):def __init__(self,config_obj,queryset,request):self.config_obj = config_objself.queryset = querysetself.request = requestself.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_nameelse:val = head_field(self.config_obj, is_header=True)head_list.append(val)return head_listdef 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_listdef get_action(self):# action標簽渲染tmp = []for action in self.config_obj.actions:tmp.append({'name': action.__name__,'desc': action.desc})return tmpdef get_filter(self):tmp_dict = {}for field in self.config_obj.list_filter:rel_model = self.config_obj.model._meta.get_field(field).rel.torel_queryset = rel_model.objects.all()click_id = self.request.GET.get(field)tmp = []import copyparams1 = 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 copyparams = copy.deepcopy(self.request.GET)params[field] = data.pkif 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] = tmpreturn tmp_dictclass ModelStark(object):list_display = ['__str__',]list_display_links = []model_form_class = Nonesearch_fields = []actions = []list_filter = []def __init__(self,model):self.model = modelself.app_label = self.model._meta.app_labelself.model_name = self.model._meta.model_nameself.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 _urldef 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 tmpdef get_search(self,request,queryset):key_word = request.GET.get('q')self.key_word = ''if key_word:self.key_word = key_wordq = Q()q.connector = 'or'for search_field in self.search_fields:q.children.append((search_field + '__icontains', key_word))queryset = queryset.filter(q)return querysetdef get_filter(self,request,queryset):q = Q()for field,field_id in request.GET.items():if field in ['page','q']:continuefield_id = request.GET.get(field)q.children.append((field, field_id))queryset = queryset.filter(q)return querysetdef 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_classclass ModelFormClass(ModelForm):class Meta:model = self.modelfields = '__all__'return ModelFormClassdef 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.pktext = 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 ModelChoiceFieldif isinstance(form_field.field,ModelChoiceField):form_field.is_pop = Truerel_model = self.model._meta.get_field(form_field.name).rel.torel_app_label = rel_model._meta.app_labelrel_model_name = rel_model._meta.model_nameurl = reverse('%s_%s_add'%(rel_app_label,rel_model_name))url = url + '?pop_back_id=' + form_field.auto_idform_field.url = urlreturn 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,Nonedef extra_url(self):return []class AdminSite(object):def __init__(self, name='admin'):self._registry = {}  # model_class class -> admin_class instancedef register(self, model, admin_class=None, **options):if not admin_class:admin_class = ModelStarkself._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_labelmodel_name = class_name._meta.model_nametmp.append(url(r'^%s/%s/'%(app_label,model_name),config_obj.get_urls()))return tmp@propertydef urls(self):return self.get_urls(), None, Nonesite = 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 = 1if current_page < 1:current_page = 1self.current_page = current_pageself.all_count = all_countself.per_page_num = per_page_num# 總頁碼all_pager, tmp = divmod(all_count, per_page_num)if tmp:all_pager += 1self.all_pager = all_pagerself.pager_count = pager_countself.pager_count_half = int((pager_count - 1) / 2)import copyself.params = copy.deepcopy(params)@propertydef start(self):return (self.current_page - 1) * self.per_page_num@propertydef end(self):return self.current_page * self.per_page_numdef page_html(self):# 如果總頁碼 < 11個:if self.all_pager <= self.pager_count:pager_start = 1pager_end = self.all_pager + 1# 總頁碼  > 11else:# 當前頁如果<=頁面上最多顯示11/2個頁碼if self.current_page <= self.pager_count_half:pager_start = 1pager_end = self.pager_count + 1# 當前頁大于5else:# 頁碼翻到最后if (self.current_page + self.pager_count_half) > self.all_pager:pager_end = self.all_pager + 1pager_start = self.all_pager - self.pager_count + 1else:pager_start = self.current_page - self.pager_count_halfpager_end = self.current_page + self.pager_count_half + 1page_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.paramsfor i in range(pager_start, pager_end):res['page'] = iif 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 reclass 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_rexres = re.search(permission_rex,current_path)if res:return Nonereturn 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_listrequest.session['permission_list'] = permission_listreturn 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,HttpResponseclass 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 tmplist_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.pkreturn 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>"%kelse:s = "<option  value='%s' >%s</option>"%khtml += sreturn 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 tmplist_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.nameclass Role(models.Model):title = models.CharField(max_length=32)permissions = models.ManyToManyField(to='Permission')def __str__(self):return self.titleclass 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.titleclass Course(models.Model):"""課程表如:Linux基礎Linux架構師Python自動化開發精英班Python自動化開發架構師班Python基礎班go基礎班"""name = models.CharField(verbose_name='課程名稱', max_length=32)def __str__(self):return self.nameclass 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.titleclass 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.nameclass 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.nameclass 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.nameclass 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.nameclass 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

?

轉載于:https://www.cnblogs.com/ShenJunHui6/p/10850093.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/386831.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/386831.shtml
英文地址,請注明出處:http://en.pswp.cn/news/386831.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Boot集成Druid監控

package com.xxxxxxx.framework.datasource.druid;import com.alibaba.druid.support.http.WebStatFilter;import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam;/*** druid過濾器.*/ WebFilter(filterName "druidWebStatFilter&qu…

hexo個人博客搭建

使用gitee托管平臺搭配hexo工具搭建個人博客 燁然的個人博客 第一部分 HEXO安裝(win10安裝過程) 1.安裝git 安裝后配置環境變量 C:\Program Files\Git\bin C:\Program Files\Git\libexec\git-core 2.安裝Node.js 快速下載鏈接 安裝后配置環境變量 環境變量寫入C:\Program Files…

GAN生成對抗網絡基本概念及基于mnist數據集的代碼實現

本文主要總結了GAN(Generative Adversarial Networks) 生成對抗網絡的基本原理并通過mnist數據集展示GAN網絡的應用。 GAN網絡是由兩個目標相對立的網絡構成的&#xff0c;在所有GAN框架中都至少包含了兩個部分&#xff0c;生成模型部分和判別模型部分。生成模型的目標是制造出…

dump查詢Java 狀態

代碼文件 dump.sh #!/usr/bin/env bash### use demo ### # 1)upload dump.sh # 2)dos2unix dump.sh;chmod x dump.sh # 3)usage: # 1. /data/sh/java/dump.sh /tmp/dump /usr/local/java/jdk1.8.0_05 23554 # 2. /data/sh/java/dump.sh /tmp/dump /usr/local/java/jdk1…

jdk、jre、jvm區別與聯系

JVM &#xff1a;英文名稱&#xff08;Java Virtual Machine&#xff09;&#xff0c;就是我們耳熟能詳的 Java 虛擬機。它只認識 xxx.class 這種類型的文件&#xff0c;它能夠將 class 文件中的字節碼指令進行識別并調用操作系統向上的 API 完成動作。所以說&#xff0c;jvm 是…

autoencoder自編碼器原理以及在mnist數據集上的實現

Autoencoder是常見的一種非監督學習的神經網絡。它實際由一組相對應的神經網絡組成&#xff08;可以是普通的全連接層&#xff0c;或者是卷積層&#xff0c;亦或者是LSTMRNN等等&#xff0c;取決于項目目的&#xff09;&#xff0c;其目的是將輸入數據降維成一個低維度的潛在編…

vscode編寫插件詳細過程

vscode編寫插件詳細過程 前言 之前編寫了一個vscode插件用vscode寫博客和發布&#xff0c;然后有園友要求寫一篇來介紹如何開發一個vscode擴展插件&#xff0c;或者說介紹開發這個插件的過程。然而文章還沒有寫&#xff0c;園子里面已經有人發布一個文章&#xff0c;是園友上…

cannot find output in imported module librosa報錯解決

librosa一直都是用處很廣泛的python聲音信號處理模塊&#xff0c;但在最近的版本更新中&#xff0c;將原本的librosa.output給刪去了。 為了代替之前的librosa.output.write_wav函數將音頻寫入wav文件中&#xff0c;現可以用模塊soundfile代替。 soundfile.write(file, data, …

2018-2019-2 20175328 《Java程序設計》第十一周學習總結

十三章主要內容——Java網絡編程 一、URL類 URL類是java.net包中的一個重要的類&#xff0c;URL的實例封裝著一個統一資源定位符(Uniform Resource Locator)&#xff0c;使用URL創建對象的應用程序稱作客戶端程序。 一個URL對象通常包含最基本的三部分信息&#xff1a;協議、地…

修改Header方法

/*** 修改header信息&#xff0c;key-value鍵值對兒加入到header中,如果存在&#xff0c;替換* param request* param key* param value*/ public static void reflectRequestParam(HttpServletRequest request, String key, String value){Class<? extends HttpServletReq…

pytorch學習筆記 1. pytorch基礎 tensor運算

pytorch與tensorflow是兩個近些年來使用最為廣泛的機器學習模塊。開個新坑記錄博主學習pytorch模塊的過程&#xff0c;不定期更新學習進程。 文章較為適合初學者&#xff0c;歡迎對代碼和理解指點討論&#xff0c;下面進入正題。 import torch import numpy as npt1 torch.te…

2019年區塊鏈的主旋律是中間層協議

2019年區塊鏈的主旋律是中間層協議 過去一年加密資產市場從其峰值下跌超過85%的市值。但對我&#xff0c;一個堅定的區塊鏈企業家&#xff0c;這實際上是一件好事&#xff0c;區塊鏈的未來看起來比以往任何時候都更有希望。2017年ICO熱潮開始的瘋狂至少產生了一個強烈的積極影響…

Java枚舉的內容可以使用map的方式

枚舉的內容可以使用map的方式 package com.chinamobile.framework.common.enums;import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import jav…

tensorflow gpu windows配置步驟教學

本文主要針對在windows10環境下的tensorflow配置問題&#xff0c;在linux和mac等其他環境中的配置就不過多贅述(windows總是那個問題最多的環境&#xff0c;建議使用linux &#x1f603;)。 本文中配置的環境為 python 3.8.5 tensorflow-gpu 2.4.1 1. 更新nvidia顯卡驅動至最…

numpy一維數組永遠為列向量

import numpy as np a np.array([1,3,4,5]) print(a.shape) a np.transpose(a) print(a.shape) print(a)a np.ravel(a) print(a.shape) print(a)a a.reshape((1,4)) print(a.shape)輸出如下 (4,) (4,) [1 3 4 5] (4,) [1 3 4 5] (1, 4)我們會發現&#xff0c;對于一維的數…

【BJOI 2019】奧術神杖

題意 你有一個長度為 $n$ 的模板串&#xff08;由 $0-9$ 這 $10$ 個數字和通配符 $.$ 組成&#xff09;&#xff0c;還有 $m$ 個匹配串&#xff08;只由 $0-9$ 這 $10$ 個數字組成&#xff09;&#xff0c;每個匹配串有一個魔力值 $v_i$。你要把模板串的每個 $.$ 都換成一個數字…

keras模型中的默認初始化權重

權重的初始化&#xff0c;決定了模型訓練的起點。一個良好的初始化可以加快訓練過程&#xff0c;同時避免模型收斂至局部最小值。為了在訓練過程中避免使得權重的變化總沿著同一個方向&#xff0c;我們盡量避免將所有權重都初始化為同一個值&#xff0c;如全0矩陣或全1矩陣。 …

java oracle的枚舉錯誤

public enum OracleErrorTypeEnum implements BaseEnum {ORA00001("ORA-00001","不允許有重復的數據"),ORA00017("ORA-00017","請求會話以設置跟蹤事件"),ORA00018("ORA-00018","超出最大會話數"),ORA00019(&quo…

C# 篇基礎知識10——多線程

1.線程的概念 單核CPU的計算機中&#xff0c;一個時刻只能執行一條指令&#xff0c;操作系統以“時間片輪轉”的方式實現多個程序“同時”運行。操作系統以進程&#xff08;Process&#xff09;的方式運行應用程序&#xff0c;進程不但包括應用程序的指令流&#xff0c;也包括運…