首页 > 其他分享 >django form使用

django form使用

时间:2025-01-07 22:33:50浏览次数:12  
标签:form self request django dict 使用 query page

示例代码:

form

from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django_redis import get_redis_connection

from utils.encrypt import md5
from utils import ytx
from web import models


class LoginForm(forms.Form):
    role = forms.ChoiceField(
        label="角色",
        required=True,
        choices=settings.NB_ROLES,
        widget=forms.Select(attrs={"class": "form-control"})
    )

    username = forms.CharField(
        label="用户名",
        max_length=8,
        widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "用户名"})
    ) 
    """以CharField举例,max_length参数传入,会在字段初始化时,将max_length校验添加self.validators,也可以直接通过validators参数直接传入其他校验类,校验类base类BaseValidator
@deconstructible
class MaxLengthValidator(BaseValidator):
    message = ngettext_lazy(
        'Ensure this value has at most %(limit_value)d character (it has %(show_value)d).',
        'Ensure this value has at most %(limit_value)d characters (it has %(show_value)d).',
        'limit_value')
    code = 'max_length'

    def compare(self, a, b): #a为传入,b为限制值,b=8为例,如果a>8会抛出异常,自定义时需确保符合条件是,compare返回false,否则返回为true
        return a > b

    def clean(self, x):
        return len(x)
"""

    password = forms.CharField(
        label="密码",
        widget=forms.PasswordInput(attrs={"class": "form-control", "placeholder": "密码"}, render_value=True) #render_value默认校验失败页面不渲染密码,为true可渲染
    )

    def clean_username(self):
        if len(self.cleaned_data['username']) <3:
            raise forms.ValidationError("用户名最少3个字符")
        return self.cleaned_data['username']

    def clean_password(self): # 单字段校验,按字段在类声明的顺序校验
        if len(self.cleaned_data['password'])<5:
            raise forms.ValidationError("密码最少5个字符")
        return md5(self.cleaned_data["password"])

    def clean(self): #整体校验
        username = self.cleaned_data.get("username")
        password = self.cleaned_data.get("password")
        print(self.cleaned_data)
        if username and password:
            return self.cleaned_data
        raise forms.ValidationError("用户名和密码不能为空")


class SmsLoginForm(forms.Form): #短信登录校验
    role = forms.ChoiceField(
        label="角色",
        required=True,
        choices=(("2", "客户"), ("1", "管理员")),
        widget=forms.Select(attrs={"class": "form-control"})
    )

    mobile = forms.CharField(
        label="手机号",
        validators=[RegexValidator(r'^1[358]\d{9}$', '手机格式错误'), ],
        widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "手机号"})
    )

    code = forms.CharField(
        label="短信验证码",
        validators=[RegexValidator(r'^[0-9]{4}$', '验证码格式错误'), ],
        widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "短信验证码"})
    )


    def clean_code(self):
        mobile = self.cleaned_data.get('mobile')
        code = self.cleaned_data['code']
        if not mobile:
            return code

        conn = get_redis_connection("default")
        cache_code = conn.get(mobile)
        if not cache_code:
            raise ValidationError("短信验证码未发送或失效")

        if code != cache_code.decode('utf-8'):
            raise ValidationError("短信验证码未发送或失效")

        return code

class MobileForm(forms.Form): #点击发送验证码,ajax发送校验,若成功发送短信验证码则通过校验
    role = forms.ChoiceField(
        label="角色",
        required=True,
        choices=(("2", "客户"), ("1", "管理员")),
        widget=forms.Select(attrs={"class": "form-control"})
    )

    mobile = forms.CharField(
        label="手机号",
        required=True,
        validators=[RegexValidator(r'^1[358]\d{9}$', '手机格式错误'), ]
    )

    def clean_mobile(self):
        role = self.cleaned_data.get('role')
        mobile = self.cleaned_data['mobile']
        if not role:
            return mobile

        if role == "1":
            exists = models.Administrator.objects.filter(active=1, mobile=mobile).exists()
        else:
            exists = models.Customer.objects.filter(active=1, mobile=mobile).exists()
        if not exists:
            raise ValidationError("手机号不存在")

        # 2.发送短信 + 生成验证码
        sms_code=ytx.get_code(4)
        is_success = ytx.send_sms(mobile, sms_code)
        if not is_success:
            raise ValidationError("短信发送失败")

        # 3.将手机号和验证码保存(以便于下次校验) redis -> 超时时间
        conn = get_redis_connection("default")
        conn.set(mobile, sms_code, ex=120)

        return mobile

view.py代码

import random

from django.http import JsonResponse
from django.shortcuts import render, redirect
from django_redis import get_redis_connection

from web import models
from utils.encrypt import md5
from utils.reponse import BaseResponse
from web.forms.account import LoginForm, MobileForm, SmsLoginForm
from django.conf import settings


def login(request):
    if request.method == "GET":
        form = LoginForm()
        return render(request, "login.html", {"form": form})

    # 1.接收并获取数据(数据格式或是否为空验证 - Form组件 & ModelForm组件)
    form = LoginForm(data=request.POST)
    if not form.is_valid():
        return render(request, "login.html", {"form": form})

    # 2.去数据库校验  1管理员  2客户
    data_dict = form.cleaned_data
    role = data_dict.pop('role')
    if role == "1":
        user_object = models.Administrator.objects.filter(active=1).filter(**data_dict).first()
    else:
        user_object = models.Customer.objects.filter(active=1).filter(**data_dict).first()

    # 2.1 校验失败
    if not user_object:
        form.add_error("username", "用户名或密码错误")
        return render(request, "login.html", {'form': form})

    # 2.2 校验成功,用户信息写入session+进入项目后台
    mapping = {"1": "ADMIN", "2": "CUSTOMER"}
    request.session[settings.NB_SESSION_KEY] = {'role': mapping[role], 'name': user_object.username,
                                                'id': user_object.id}
    return redirect(settings.LOGIN_HOME)


def sms_send(request):
    """ 发送短信  """
    res = BaseResponse()

    # 校验数据合法性:手机号的格式 + 角色
    form = MobileForm(data=request.POST)
    if not form.is_valid():
        res.detail = form.errors
        return JsonResponse(res.dict, json_dumps_params={"ensure_ascii": False})
    res.status = True
    return JsonResponse(res.dict)


def sms_login(request):
    if request.method == "GET":
        form = SmsLoginForm()
        return render(request, "sms_login.html", {'form': form})

    res = BaseResponse()
    # 1.手机格式校验
    form = SmsLoginForm(data=request.POST)
    if not form.is_valid():
        res.detail = form.errors
        return JsonResponse(res.dict)

    role = form.cleaned_data['role']
    mobile = form.cleaned_data['mobile']
    # 3.登录成功 + 注册  (监测手机号是否存在)
    #     - 未注册,自动注册
    #     - 已注册,直接登录
    if role == "1":
        user_object = models.Administrator.objects.filter(active=1, mobile=mobile).first()
    else:
        user_object = models.Customer.objects.filter(active=1, mobile=mobile).first()

    if not user_object:
        res.detail = {"mobile": ["手机号不存在"]}
        return JsonResponse(res.dict)

    # 2.2 校验成功,用户信息写入session+进入项目后台
    mapping = {"1": "ADMIN", "2": "CUSTOMER"}
    request.session[settings.NB_SESSION_KEY] = {'role': mapping[role], 'name': user_object.username,
                                                'id': user_object.id}

    res.status = True
    res.data = settings.LOGIN_HOME
    return JsonResponse(res.dict)

html:

{% 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' %}">
    <style>
        .box {
            width: 450px;
            border: 1px solid #f0f0f0;
            margin-left: auto;
            margin-right: auto;
            margin-top: 100px;

            padding-left: 40px;
            padding-right: 40px;
            padding-bottom: 30px;

            box-shadow: 5px 10px 10px rgb(0 0 0 / 5%);
        }
    </style>
</head>
<body>

<div class="box">
    <h2 style="text-align: center;">用户登录</h2>
    <form method="post">
        {% csrf_token %}

        {% for field in form %}
            <div class="form-group" style="position: relative;margin-bottom: 25px">
                <label>{{ field.label }}</label>
                {{ field }}
                <span style="color: red;position: absolute;">{{ field.errors.0 }}</span>
            </div>
        {% endfor %}

        <button type="submit" class="btn btn-primary">登 录</button>

        <a href='{% url 'sms_login' %}' style="float: right;">短信登录</a>
    </form>
</div>

</body>
</html>

分页类

"""
v1版本
    在视图函数:
        def customer_list(request):
            # 所有数据
            queryset = models.Customer.objects.filter(active=1).select_related('level')

            pager = Pagination(request, queryset)
            context = {
                "queryset": queryset[pager.start:pager.end],
                "pager_string": obj.html()
            }
            return render(request, 'customer_list.html', context)

    在页面上:
        {% for row in queryset %}
            {{row.id}}
        {% endfor %}

        <ul class="pagination">
            {{ pager_string }}
        </ul>

v2版本
    在视图函数:
        def customer_list(request):
            # 所有数据
            queryset = models.Customer.objects.filter(active=1).select_related('level')

            pager = Pagination(request, queryset)
            return render(request, 'customer_list.html', {"pager":pager})

    在页面上:
        {% for row in pager.queryset %}
            {{row.id}}
        {% endfor %}

        <ul class="pagination">
            {{ pager.html }}
        </ul>

"""
import copy
from django.utils.safestring import mark_safe


class Pagination(object):
    """ 分页 """

    def __init__(self, request, query_set, per_page_count=10):

        self.query_dict = copy.deepcopy(request.GET)
        self.query_dict._mutable = True

        self.query_set = query_set
        total_count = query_set.count()
        self.total_count = total_count
        # 计算出总共有多少页面
        self.total_page, div = divmod(total_count, per_page_count)
        if div:
            self.total_page += 1

        page = request.GET.get('page')
        if not page:
            page = 1
        else:
            if not page.isdecimal():
                page = 1
            else:
                page = int(page)
                if page <= 0:
                    page = 1
                else:
                    if page > self.total_page:
                        page = self.total_page

        self.page = page
        self.per_page_count = per_page_count

        self.start = (page - 1) * per_page_count
        self.start = 0 if self.start<0 else self.start
        self.end = page * per_page_count

    def html(self):
        pager_list = []
        if not self.total_page:
            return ""

        # 总页码小于11
        if self.total_page <= 11:
            start_page = 1
            end_page = self.total_page
        else:
            # 总页码比较多
            # 判断当前页 <=6: 1~11
            if self.page <= 6:
                start_page = 1
                end_page = 11
            else:
                if (self.page + 5) > self.total_page:
                    start_page = self.total_page - 10
                    end_page = self.total_page
                else:
                    start_page = self.page - 5
                    end_page = self.page + 5

        self.query_dict.setlist('page', [1])
        pager_list.append('<li><a href="?{}">首页</a></li>'.format(self.query_dict.urlencode()))

        if self.page > 1:
            self.query_dict.setlist('page', [self.page - 1])
            pager_list.append('<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode()))

        for i in range(start_page, end_page + 1):
            self.query_dict.setlist('page', [i])
            if i == self.page:
                item = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
            else:
                item = '<li><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
            pager_list.append(item)

        if self.page < self.total_page:
            self.query_dict.setlist('page', [self.page + 1])
            pager_list.append('<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode()))

        self.query_dict.setlist('page', [self.total_page])
        pager_list.append('<li><a href="?{}">尾页</a></li>'.format(self.query_dict.urlencode()))

        pager_list.append('<li class="disabled"><a>数据{}条{}页</a></li>'.format(self.total_count, self.total_page))
        pager_string = mark_safe("".join(pager_list))
        return pager_string

    def queryset(self):
        if self.total_count:
            return self.query_set[self.start:self.end]
        return self.query_set

标签:form,self,request,django,dict,使用,query,page
From: https://www.cnblogs.com/liuzhiyangz/p/18658542

相关文章