crm项目之登录验证(密码使用密文),前端使用django的form组件
crm项目01 登录验证(密码使用md5密文)
项目要点
0.自定义form类
exclude[ ] 除去列表中的字段
1.验证使用django的form组件
其中,注意is_valid()判断前端传过来的值是否全部正确.如果正确是True,查看源码之后,其中进行的顺序是
is bound and errors 局部钩子, 全局钩子同时可以报出异常
获取组件的最后传过来的值使用.cleaned_data方法,cleaned_data是一个字典,使用get获取时要如图片写,防止值为空时获取不到报错,
定义全局钩子时,一定要记得返回全局的cleaned_data

2.要将form表单的样式渲染,要在自定义的form表单类定义初始化方法.
def __init__(self, *args, **kwargs): super().__init__(*args,**kwargs) # print(self.fields) for field in self.fields.values(): field.widget.attrs.update({'class':'form-control'})
self.fields的结果是一个有序字典,所以遍历它,获取它的value并更新字典

3.将form表单传给前端渲染字段,前端要这样写
<div class="form-group"> <label for="{{ form_obj.mobile.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.mobile.label }}</label> <div class="col-sm-10"> {{ form_obj.mobile }}{{ form_obj.mobile.errors.0 }} </div> </div>
其中的from_obj来自视图函数中定义的obj,其中 form_obj = RegForm(request.POST)就是将post过来的数据传递给regform这个自己写的表单类
# 注册 def reg(request): # 判断请求方式 if request.method == 'POST': form_obj = RegForm(request.POST) # 对数据进行校验 if form_obj.is_valid(): # 数据正确 插入数据库 # print(form_obj.cleaned_data) # form_obj.cleaned_data.pop('re_password') # models.UserProfile.objects.create(**form_obj.cleaned_data) form_obj.save() return redirect(reverse('login')) else: form_obj = RegForm() return render(request, 'reg.html', {'form_obj': form_obj})
4.form表单的label默认传给前端页面时使用的是models里面创建时的字段,
会出现如下情况,有的字段标签是英文.修改这里有两种方法,一种是在自定义的Regform类中修改,一种是在models文件的字段中添加verbose_name='密码' 这样的参数

------1.在models.py的字段中修改

图中没有使用verbose_name的原因是 charfield的源码中 第一个位置参数就是verbose_name,最好还是写上比较好

-------2. 在Regform即自定义的form类中创建

5.前端页面不让浏览器弹出要在form表单标签中加入novalidate属性

为了防止这种效果发生,这样加入属性
![]()
项目目录结构:

views.py
from django.shortcuts import render, redirect, reverse, HttpResponse from crm import models from crm.froms import RegForm import hashlib def index(request): return HttpResponse('index') def login(request): if request.method == 'POST': user = request.POST.get('username') pwd = request.POST.get('password') md5 = hashlib.md5() md5.update(pwd.encode('utf-8')) pwd = md5.hexdigest() obj = models.UserProfile.objects.filter(username=user, password=pwd, is_active=True).first() if obj: # 登录成功 跳转到主页面 return redirect(reverse('index')) else: # 登录失败 return render(request, 'login.html', {'error': '用户名或密码错误'}) return render(request, 'login.html') # 注册 def reg(request): # 判断请求方式 if request.method == 'POST': form_obj = RegForm(request.POST) # 对数据进行校验 if form_obj.is_valid(): # 数据正确 插入数据库 # print(form_obj.cleaned_data) # form_obj.cleaned_data.pop('re_password') # models.UserProfile.objects.create(**form_obj.cleaned_data) form_obj.save() return redirect(reverse('login')) else: form_obj = RegForm() return render(request, 'reg.html', {'form_obj': form_obj})
froms.py
from django import forms from crm import models from django.core.exceptions import ValidationError import hashlib # 注册的form class RegForm(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: model = models.UserProfile # 指定model fields = '__all__' # ['username','password'] # 指定字段 exclude = ['is_active'] labels = { 'username': '用户名' } widgets = { 'username': forms.TextInput(attrs={'class': 'form-control', 'placeholder': '用户名'}), # 'password': forms.PasswordInput(attrs={'class': 'form-control'}) } error_messages={ 'min_length':'不能少于6位' } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 自定义操作 for field in self.fields.values(): # field.widget.attrs['class'] = 'form-control' 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: # 密码加密 md5 = hashlib.md5() md5.update(pwd.encode('utf-8')) pwd = md5.hexdigest() self.cleaned_data['password'] = pwd return self.cleaned_data # 两次密码不一致 self.add_error('re_password', '两次密码不一致!!') raise ValidationError('两次密码不一致')
reg.html
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> <title></title> {% load static %} <link rel="stylesheet" href="{% static 'plugins/bootstrap/css/bootstrap.css' %}"> </head> <body> <div class="col-lg-8 col-lg-offset-2 " style="margin-top: 80px"> <form class="form-horizontal" novalidate method="post"> {% 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.mobile.id_for_label }}" class="col-sm-2 control-label">{{ form_obj.mobile.label }}</label> <div class="col-sm-10"> {{ form_obj.mobile }} {{ form_obj.mobile.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">注册</button> </div> </div> </form> </div> </body> </html>
urls.py
from django.conf.urls import url from crm import views urlpatterns = [ url(r'^login/',views.login,name='login'), url(r'^reg/',views.reg,name='reg'), url(r'^index/',views.index,name='index'), ]
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 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,verbose_name='部门') 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="选择客户此时的状态") last_consult_date = models.DateField("最后跟进日期", auto_now_add=True) next_date = models.DateField("预计再次跟进时间", blank=True, null=True) 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')
数据库的表关系


浙公网安备 33010602011771号