crm 系统项目(一) 登录,注册,校验
首先创建一个Django项目,关于配置信息不多说,前面有~
models.py文件下创建需要的表格信息,之后导入数据库
from django.db import models from multiselectfield import MultiSelectField course_choices = (('Linux', 'Linux中高级'), ('PythonFullStack', 'Python高级全栈开发'),) class_type_choices = (('fulltime', '脱产班',), ('online', '网络班'), ('weekend', '周末班',),) source_type = (('qq', "qq群"), ('referral', "内部转介绍"), ('website', "官方网站"), ('baidu_ads', "百度推广"), ('office_direct', "直接上门"), ('WoM', "口碑"), ('public_class', "公开课"), ('website_luffy', "路飞官网"), ('others', "其它"),) enroll_status_choices = (('signed', "已报名"), ('unregistered', "未报名"), ('studying', '学习中'), ('paid_in_full', "学费已交齐")) seek_status_choices = (('A', '近期无报名计划'), ('B', '1个月内报名'), ('C', '2周内报名'), ('D', '1周内报名'), ('E', '定金'), ('F', '到班'), ('G', '全款'), ('H', '无效'),) pay_type_choices = (('deposit', "订金/报名费"), ('tuition', "学费"), ('transfer', "转班"), ('dropout', "退学"), ('refund', "退款"),) attendance_choices = (('checked', "已签到"), ('vacate', "请假"), ('late', "迟到"), ('absence', "缺勤"), ('leave_early', "早退"),) 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'),) class Department(models.Model): """ 部门表 """ name = models.CharField(max_length=32, verbose_name="部门名称") count = models.IntegerField(verbose_name="人数", default=0) # class Meta: # db_table = 'xxx' # 表名 class UserProfile(models.Model): """ 用户表 """ username = models.EmailField(max_length=255, unique=True,) password = models.CharField(max_length=128) name = models.CharField('名字', max_length=32) department = models.ForeignKey('Department', default=None, blank=True, null=True) mobile = models.CharField('手机', max_length=32, default=None, blank=True, null=True) memo = models.TextField('备注', blank=True, null=True, default=None) date_joined = models.DateTimeField(auto_now_add=True) is_active = models.BooleanField(default=True) class Customer(models.Model): """ 客户表 """ qq = models.CharField('QQ', max_length=64, unique=True, help_text='QQ号必须唯一') qq_name = models.CharField('QQ昵称', max_length=64, blank=True, null=True) name = models.CharField('姓名', max_length=32, blank=True, null=True, help_text='学员报名后,请改为真实姓名') sex_type = (('male', '男'), ('female', '女')) sex = models.CharField("性别", choices=sex_type, max_length=16, default='male', blank=True, null=True) birthday = models.DateField('出生日期', default=None, help_text="格式yyyy-mm-dd", blank=True, null=True) phone = models.BigIntegerField('手机号', blank=True, null=True) source = models.CharField('客户来源', max_length=64, choices=source_type, default='qq') introduce_from = models.ForeignKey('self', verbose_name="转介绍自学员", blank=True, null=True) course = MultiSelectField("咨询课程", choices=course_choices) class_type = models.CharField("班级类型", max_length=64, choices=class_type_choices, default='fulltime') customer_note = models.TextField("客户备注", blank=True, null=True, ) status = models.CharField("状态", choices=enroll_status_choices, max_length=64, default="unregistered", help_text="选择客户此时的状态") network_consult_note = models.TextField(blank=True, null=True, verbose_name='网络咨询师咨询内容') date = models.DateTimeField("咨询日期", auto_now_add=True) last_consult_date = models.DateField("最后跟进日期", auto_now_add=True) next_date = models.DateField("预计再次跟进时间", blank=True, null=True) network_consultant = models.ForeignKey('UserProfile', blank=True, null=True, verbose_name='咨询师', related_name='network_consultant') consultant = models.ForeignKey('UserProfile', verbose_name="销售", related_name='customers', blank=True, null=True, ) class_list = models.ManyToManyField('ClassList', verbose_name="已报班级", ) class Campuses(models.Model): """ 校区表 """ name = models.CharField(verbose_name='校区', max_length=64) address = models.CharField(verbose_name='详细地址', max_length=512, blank=True, null=True) class ClassList(models.Model): """ 班级表 """ course = models.CharField("课程名称", max_length=64, choices=course_choices) semester = models.IntegerField("学期") campuses = models.ForeignKey('Campuses', verbose_name="校区") price = models.IntegerField("学费", default=10000) memo = models.CharField('说明', blank=True, null=True, max_length=100) start_date = models.DateField("开班日期") graduate_date = models.DateField("结业日期", blank=True, null=True) teachers = models.ManyToManyField('UserProfile', verbose_name="老师") class_type = models.CharField(choices=class_type_choices, max_length=64, verbose_name='班额及类型', blank=True, null=True) class Meta: unique_together = ("course", "semester", 'campuses') class ConsultRecord(models.Model): """ 跟进记录表 """ customer = models.ForeignKey('Customer', verbose_name="所咨询客户") note = models.TextField(verbose_name="跟进内容...") status = models.CharField("跟进状态", max_length=8, choices=seek_status_choices, help_text="选择客户此时的状态") consultant = models.ForeignKey("UserProfile", verbose_name="跟进人", related_name='records') date = models.DateTimeField("跟进日期", auto_now_add=True) delete_status = models.BooleanField(verbose_name='删除状态', default=False) class Enrollment(models.Model): """ 报名表 """ why_us = models.TextField("为什么报名", max_length=1024, default=None, blank=True, null=True) your_expectation = models.TextField("学完想达到的具体期望", max_length=1024, blank=True, null=True) contract_agreed = models.BooleanField("我已认真阅读完培训协议并同意全部协议内容", default=False) contract_approved = models.BooleanField("审批通过", help_text="在审阅完学员的资料无误后勾选此项,合同即生效", default=False) enrolled_date = models.DateTimeField(auto_now_add=True, verbose_name="报名日期") memo = models.TextField('备注', blank=True, null=True) delete_status = models.BooleanField(verbose_name='删除状态', default=False) customer = models.ForeignKey('Customer', verbose_name='客户名称') school = models.ForeignKey('Campuses') enrolment_class = models.ForeignKey("ClassList", verbose_name="所报班级") class Meta: unique_together = ('enrolment_class', 'customer') class PaymentRecord(models.Model): """ 缴费记录表 """ pay_type = models.CharField("费用类型", choices=pay_type_choices, max_length=64, default="deposit") paid_fee = models.IntegerField("费用数额", default=0) note = models.TextField("备注", blank=True, null=True) date = models.DateTimeField("交款日期", auto_now_add=True) course = models.CharField("课程名", choices=course_choices, max_length=64, blank=True, null=True, default='N/A') class_type = models.CharField("班级类型", choices=class_type_choices, max_length=64, blank=True, null=True, default='N/A') enrolment_class = models.ForeignKey('ClassList', verbose_name='所报班级', blank=True, null=True) customer = models.ForeignKey('Customer', verbose_name="客户") consultant = models.ForeignKey('UserProfile', verbose_name="销售") delete_status = models.BooleanField(verbose_name='删除状态', default=False) status_choices = ( (1, '未审核'), (2, '已审核'), ) status = models.IntegerField(verbose_name='审核', default=1, choices=status_choices) confirm_date = models.DateTimeField(verbose_name="确认日期", null=True, blank=True) confirm_user = models.ForeignKey(verbose_name="确认人", to='UserProfile', related_name='confirms', null=True, blank=True) class CourseRecord(models.Model): """课程记录表""" day_num = models.IntegerField("节次", help_text="此处填写第几节课或第几天课程...,必须为数字") date = models.DateField(auto_now_add=True, verbose_name="上课日期") course_title = models.CharField('本节课程标题', max_length=64, blank=True, null=True) course_memo = models.TextField('本节课程内容', max_length=300, blank=True, null=True) has_homework = models.BooleanField(default=True, verbose_name="本节有作业") homework_title = models.CharField('本节作业标题', max_length=64, blank=True, null=True) homework_memo = models.TextField('作业描述', max_length=500, blank=True, null=True) scoring_point = models.TextField('得分点', max_length=300, blank=True, null=True) re_class = models.ForeignKey('ClassList', verbose_name="班级") teacher = models.ForeignKey('UserProfile', verbose_name="讲师") class Meta: unique_together = ('re_class', 'day_num') class StudyRecord(models.Model): """ 学习记录 """ attendance = models.CharField("考勤", choices=attendance_choices, default="checked", max_length=64) score = models.IntegerField("本节成绩", choices=score_choices, default=-1) homework_note = models.CharField(max_length=255, verbose_name='作业批语', blank=True, null=True) date = models.DateTimeField(auto_now_add=True) note = models.CharField("备注", max_length=255, blank=True, null=True) homework = models.FileField(verbose_name='作业文件', blank=True, null=True, default=None) course_record = models.ForeignKey('CourseRecord', verbose_name="某节课程") student = models.ForeignKey('Customer', verbose_name="学员") class Meta: unique_together = ('course_record', 'student')
urls.py
from django.contrib import admin from django.conf.urls import url from app1 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), url(r'^index', views.index), url(r'^reg', views.reg), ]
login.html 登录页面
css样式以及js用到 Bootscraipt,
{% load static %} {#静态文件的方式#} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录界面</title> <link rel="stylesheet" href="{% static 'css/reset.css' %}"> <link rel="stylesheet" href="{% static 'css/style.css' %}"> </head> <div id="particles-js"> <div class="login"> <div class="login-top"> 登录 </div> <form action="" method="post"> {% csrf_token %} {# 由于没有注释中间件csrf, 需要在form 后 加此, 否则post失败#} <div class="login-center clearfix"> <div class="login-center-img"><img src="{% static 'img/name.png' %}"></div> <div class="login-center-input"> <input type="text" name="user" value="admin" placeholder="请输入您的用户名" onfocus="this.placeholder=''" onblur="this.placeholder='请输入您的用户名'"> <div class="login-center-input-text">用户名</div> </div> </div> <div class="login-center clearfix"> <div class="login-center-img"><img src="{% static 'img/password.png' %}"></div> <div class="login-center-input"> <input type="password" name="pwd" value="" placeholder="请输入您的密码" onfocus="this.placeholder=''" onblur="this.placeholder='请输入您的密码'"> <div class="login-center-input-text">密码</div> </div> </div> <p style="color: red;text-align: center">{{ err_msg }}</p> <div style="text-align: center"> <button class="login-button">登录</button> </div> </form> </div> <div class="sk-rotating-plane"></div> <canvas class="particles-js-canvas-el" width="1343" height="163" style=" 100%; height: 100%;"></canvas> </div> <script src="{% static 'js/particles.min.js' %}"></script> <script src="{% static 'js/app.js' %}"></script> <script type="text/javascript"> function hasClass(elem, cls) { cls = cls || ''; if (cls.replace(/s/g, '').length == 0) return false; //当cls没有参数时,返回false return new RegExp(' ' + cls + ' ').test(' ' + elem.className + ' '); } function addClass(ele, cls) { if (!hasClass(ele, cls)) { ele.className = ele.className == '' ? cls : ele.className + ' ' + cls; } } function removeClass(ele, cls) { if (hasClass(ele, cls)) { var newClass = ' ' + ele.className.replace(/[ ]/g, '') + ' '; while (newClass.indexOf(' ' + cls + ' ') >= 0) { newClass = newClass.replace(' ' + cls + ' ', ' '); } ele.className = newClass.replace(/^s+|s+$/g, ''); } } document.querySelector(".login-button").onclick = function () { addClass(document.querySelector(".login"), "active") setTimeout(function () { addClass(document.querySelector(".sk-rotating-plane"), "active") document.querySelector(".login").style.display = "none" }, 800) setTimeout(function () { removeClass(document.querySelector(".login"), "active") removeClass(document.querySelector(".sk-rotating-plane"), "active") document.querySelector(".login").style.display = "block" alert("登录成功") }, 5000) } </script> </html>
reg.html 注册页面
css样式以及js用到 Bootscraipt,
form 标签加上novalidate 前段不进行校验
{{ form_obj.as_p }} ——》 生成所有的p标签 label input
{{ form_obj.errors }} ——》所有字段的错误
{{ form_obj.user }} ——》 该字段的input框
{{ form_obj.user.label }} ——》 该字段的label 中文提示
{{ form_obj.user.id_for_label }} ——》 该字段的id
{{ form_obj.user.errors }} ——》 该字段的所有的错误信息
{{ form_obj.user.errors.0 }} ——》 该字段的第一个的错误信息
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %}"> </head> <body> <div class="container"> <div class="row" style="margin-top: 70px"> <div class="col-sm-6 col-sm-offset-3"> <form class="form-horizontal" method="post" action="" novalidate> {% csrf_token %} <div class="form-group"> <label for="{{ form_obj.username.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.username.label }}</label> <div class="col-sm-10"> {{ form_obj.username }} {{ form_obj.username.errors.0 }} </div> </div> <div class="form-group"> <label for="{{ form_obj.password.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.password.label }}</label> <div class="col-sm-10"> {{ form_obj.password }} {{ form_obj.password.errors.0 }} </div> </div> <div class="form-group"> <label for="{{ form_obj.re_password.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.re_password.label }}</label> <div class="col-sm-10"> {{ form_obj.re_password }} {{ form_obj.re_password.errors.0 }} </div> </div> <div class="form-group"> <label for="{{ form_obj.name.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.name.label }}</label> <div class="col-sm-10"> {{ form_obj.name }} {{ form_obj.name.errors.0 }} </div> </div> <div class="form-group"> <label for="{{ form_obj.department.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.department.label }}</label> <div class="col-sm-10"> {{ form_obj.department }} {{ form_obj.department.errors.0 }} </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default">Sign in</button> </div> </div> </form> </div> </div> </div> </body> </html>
app下新建 form.py 用于注册时 form表单 建立校验等
from django import forms from app1 import models from django.core.exceptions import ValidationError import hashlib # md5加密 def enc_md5(str=''): md = hashlib.md5() #创建MD5对象 md.update(str.encode(encoding='utf-8')) return md.hexdigest() # 注册form class ReForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput(), label='密码', min_length=6) re_password = forms.CharField(widget=forms.PasswordInput(), label='确认密码', min_length=6) class Meta: #通过models 自动创建表单 model = models.UserProfile fields = "__all__" # 所有字段 # fields = ['username','password'] exclude = ['is_active'] # 排除某些字段 labels = { 'username': '用户名', 'password': '密码', # 're_password': '确认密码', 'department': '部门', } widgets = { # 'password': forms.PasswordInput(attrs={'class': 'form-control'}) } error_messages = { 'username': { 'required': '不能为空', 'invalid': '格式错误' } } # 给某些表单添加bootscript 类名 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for field in self.fields.values(): field.widget.attrs.update({'class': 'form-control'}) # 全局钩子验证 def clean(self): pwd = self.cleaned_data.get('password') re_pwd = self.cleaned_data.get('re_password') if pwd == re_pwd and pwd: # 对密码进行加密 # md5 = hashlib.md5() # md5.update(pwd.encode("utf-8")) # pwd = md5.hexdigest() # print(pwd) enc_md5(pwd) print(enc_md5(pwd)) self.cleaned_data['password'] = pwd return self.cleaned_data self.add_error('re_password', '两次密码不一致') raise ValidationError('两次密码不一致')
views.py 视图
from django.shortcuts import render, redirect, HttpResponse from app1 import models import hashlib from app1.forms import ReForm # md5加密 def enc_md5(str=''): md = hashlib.md5() #创建MD5对象 md.update(str.encode(encoding='utf-8')) return md.hexdigest() def index(request): HttpResponse('hahahhahh') # 登录 def login(request): err_msg = '' if request.method == 'POST': user = request.POST.get('user') pwd = request.POST.get('pwd') print(user) # md5 = hashlib.md5() # md5.update(pwd.encode('utf-8')) # pwd = md5.hexdigest() enc_md5(pwd) # 按照输入账户密码从数据库中查找 obj = models.UserProfile.objects.filter(username=user, password=pwd, is_active=True).first() if obj: return redirect('/index/') err_msg = '用户名或密码错误' return render(request, 'login.html', {'err_msg': err_msg}) # 注册 def reg(request): form_obj = ReForm() #form表单校验之后的结果 if request.method == 'POST': form_obj = ReForm(request.POST) #把 POST 请求放入到form 验证 if form_obj.is_valid(): #如果通过验证 form_obj.save() #保存数据 return redirect('/login/') return render(request, 'reg.html',{'form_obj':form_obj})
效果图:
登录 >>>>>>>>>
注册 >>>>>>>>>>>>>>