Django Form 组件用于对页面进行初始化,生成 HTML 标签,此外还可以对用户提交对数据进行校验(显示错误信息)。
models.py
class UserInfo(models.Model):
username = models.CharField(verbose_name='用户名', max_length=32, db_index=True) # db_index=True 添加索引
email = models.EmailField(verbose_name='邮箱', max_length=32)
phone = models.CharField(verbose_name='手机号', max_length=32)
password = models.CharField(verbose_name='密码', max_length=32)
login.html
{% extends 'layout/base.html' %}
{% load static %}
{% block title %}
用户登录
{% endblock %}
{% block css %}
<link rel="stylesheet" href="{% static 'css/account.css' %}">
{% endblock %}
{% block content %}
<div class="account">
<div class="title">密码登录</div>
<form method="POST" novalidate>
{% csrf_token %}
{% for field in form %}
{% if field.name == 'img_code' %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
<div class="row">
<div class="col-md-7">
{{ field }}
<span class="error-msg">{{ field.errors.0 }}</span>
</div>
<div class="col-md-5">
<img src="/user/image/code/" id="imageCode" title="点击更换图片">
</div>
</div>
</div>
{% else %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field }}
<span class="error-msg">{{ field.errors.0 }}</span>
</div>
{% endif %}
{% endfor %}
<div>
<div style="float: right">
<a href="/user/login/sms/">短信验证码登录?</a>
</div>
</div>
<div class="row">
<div class="col-xs-3" style="padding-top: 20px;">
<input type="submit" class="btn btn-primary" value="登 录">
</div>
</div>
</form>
</div>
{% endblock %}
{% block js %}
<script>
$(function () {
$("#imageCode").click(function () {
var oldSrc = $(this).attr("src");
$(this).attr("src", oldSrc + "?");
})
})
</script>
{% endblock %}
user_forms.py
class RegisterModelForm(BootStrapForm, forms.ModelForm):
"""
ModelForm组件,一个一个校验
"""
password = forms.CharField(
label="密码",
min_length=8,
max_length=64,
error_messages={
"min_length": "密码长度不能小于8个字符",
"max_length": "密码长度不能大于64个字符"
},
widget=forms.PasswordInput
)
password_2 = forms.CharField(
label="重复密码",
min_length=8,
max_length=64,
error_messages={
"min_length": "重复密码长度不能小于8个字符",
"max_length": "重复密码长度不能大于64个字符"
},
widget=forms.PasswordInput)
phone = forms.CharField(
label="手机号码",
validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号码格式错误')]
)
code = forms.CharField(label="验证码", widget=forms.TextInput())
class Meta:
model = UserInfo
# fields = "__all__"
fields = ['username', 'email', 'password', 'password_2', 'phone', 'code'] # 之低昂返回的顺序
def clean_username(self):
username = self.cleaned_data["username"]
exists = UserInfo.objects.filter(username=username).exists()
if exists:
return ValidationError('用户名已存在')
return username
def clean_email(self):
email = self.cleaned_data["email"]
exists = UserInfo.objects.filter(email=email).exists()
if exists:
return ValidationError('邮箱已存在')
return email
def clean_password(self):
"""在这里对密码进行加密"""
password = self.cleaned_data["password"]
return encrypt.md5(password)
def clean_password_2(self):
"""cleaned_data: 已校验的字段"""
password = self.cleaned_data["password"]
password2 = encrypt.md5(self.cleaned_data["password_2"])
if password != password2:
raise ValidationError("两次密码不一致")
return password2
def clean_phone(self):
phone = self.cleaned_data["phone"]
exists = UserInfo.objects.filter(phone=phone).exists()
if exists:
raise ValidationError("当前手机已注册")
return phone
def clean_code(self):
"""校验验证码的时候,取出之后就把redis中的数据删除"""
code = self.cleaned_data["code"]
# phone = self.data["phone"]
# 异常的处理
phone = self.cleaned_data.get("phone")
if not phone:
return code
conn = get_redis_connection()
redis_code = conn.get(phone)
if not redis_code:
raise ValidationError("验证码失效或未发送,请重新发送")
redis_str_code = redis_code.decode('utf-8')
if code.strip() != redis_str_code:
raise ValidationError("验证码错误,请重新输入")
return code
middleware.py
class Tracer(object):
"""
在中间件中封装tracer对象
"""
def __init__(self):
self.user = None
self.price_policy = None
class AuthMiddleware(MiddlewareMixin):
@staticmethod
def process_request(request):
# 实例化一个Tracer()对象
request.tracer = Tracer()
# 如果用户登录了, 在request中赋值
user_id = request.session.get("user_id", 0)
user_obj = UserInfo.objects.filter(id=user_id).first()
request.tracer.user = user_obj
if request.path_info in WHITE_REGEX_URL_LIST:
return
if not request.tracer.user:
return redirect('/user/login/user/')
# 登录成功之后,进入后台管理时:获取当前用户所拥有的空间额度
# 1. 免费额度在交易记录中存储
# 获取用户ID值最大(最近的一次交易记录)
_obj = Transaction.objects.filter(user=user_obj, status=2).order_by('-id').first()
# 判断当前用户的最后交易记录是否过期
current_datetime = datetime.now()
# 如果交易记录存在,并且交易记录未过期
# 没有交易记录的时候,说明当前用户是免费版
if _obj.end_datetime and _obj.end_datetime < current_datetime:
# _obj = Transaction.objects.filter(user=user_obj, status=2).order('id').first()
_obj = Transaction.objects.filter(
user=user_obj, status=2, pro_policy__category=1
).first()
request.tracer.price_policy = _obj.pro_policy
# 2. 免费额度存储在配置文件中
"""
transaction_obj = Transaction.objects.filter(
user=user_obj, status=2
).order_by('-id').first()
if not transaction_obj:
# 没有购买
request.price_policy = PricePolicy.objects.filter(
category=1, title="个人免费版"
).first()
else:
# 付费版: 判断当前用户的最后交易记录是否过期
current_datetime = datetime.now()
if transaction_obj.end_datetime and transaction_obj.end_datetime<current_datetime:
request.price_policy = PricePolicy.objects.filter(
category=1, title="个人免费版"
).first()
else:
request.price_policy = transaction_obj.price_policy
"""
评论区