python_day22_Django-6 (form)

form介绍

form主要功能: 页面可用的HTML标签,对用户提交的数据进行校验,保留上次输入内容

普通注册

1、html页面
reg.html
<form action="/reg/" method="post" novalidate>
    {% csrf_token %}
    <div>
        用户名: <input type="text" name="username">
    </div>
    <div>
        密码: <input type="password" name="pwd">
        <span>{{ error.pwd }}</span>
    </div>

    <input type="submit" value="提交">
</form>

2、urls.py
urlpatterns = [
    path('admin/', admin.site.urls),
    path('reg/', views.register),
]

3、views.py
def register(request):
    error_msg = {"pwd": "", "username": ""}
    if request.method == "POST":
        username = request.POST.get("username")
        pwd = request.POST.get("pwd")

        if len(pwd) < 6:
            error_msg["pwd"] = "长度不能小于6"

    return render(request, "reg.html", {"error": error_msg})

python_day22_Django-6 (form)

使用form注册

1、html页面
<form action="/regs2/" method="post" novalidate>
    {% csrf_token %}    
    {{ form_obj.as_p }}   {# 生成html页面 #}
    {{ form_obj.errors.pwd }}  {# 打印错误提示 #}
    <input type="submit" value="提交">
</form>

2、 urls.py与 普通注册的一样

3、views.py 
from app01 import formd
def register2(request):
    form_obj = formd.RgeForm()

    if request.method == "POST":
        form_obj = formd.RgeForm(request.POST)   # django自动生成的 html页面
        print(form_obj)  
                    #<tr><th><label for="id_name">用户名:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="name" maxlength="16" required id="id_name" /></td></tr>
    return render(request, "reg2.html", {"form_obj": form_obj})

4、formd.py
在项目中创建一个formd.py文件 
from django import forms   # 引用forms模块

# 创建注册函数
class RgeForm(forms.Form):
    name = forms.CharField(
        label="用户名",   
        max_length=16,     # 最大长度以及错误提示
        error_messages={
            "max_length": "最大长度16"
        }
    )

    pwd = forms.CharField(
        label="密码",
        min_length=6,
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "最少6位",
        }
    )

form的功能: 来源: https://www.cnblogs.com/liwenzhou/p/8747872.html
• 前端页面是form类的对象生成的 -->生成HTML标签功能
• 当用户名和密码输入为空或输错之后 页面都会提示 -->用户提交校验功能
• 当用户输错之后 再次输入 上次的内容还保留在input框 -->保留上次输入内容

1.1、error_messages

错误重写

        error_messages={ 
            "required": "不能为空",    # 当请求为空时提示
            "invalid": "格式错误",       # 格式错误
            "min_length": "最少6位",  # 最小长度
            "max_length":" 最大N位"  # 最大长度
        }

1.2、password

    pwd = forms.CharField(
        label="密码",
        min_length=6,
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "最少6位",
        },
        # widget=forms.widgets.PasswordInput()     # 插件widgets
    )

不加 widget=forms.widgets.PasswordInput()
python_day22_Django-6 (form)
加上widget=forms.widgets.PasswordInput()
python_day22_Django-6 (form)

增加类

    pwd = forms.CharField(
        label="密码",
        min_length=6,
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "最少6位",
        },
        widget=forms.widgets.PasswordInput(
            attrs={"class":"ap1"}
        )
    )

python_day22_Django-6 (form)

1.3选择框

choices 单选框

    hobby221 = forms.ChoiceField(
        choices=((1,"吃饭"), (2,"睡觉"),(3,"做梦"),),
        label="爱好",
        initial=1,
        widget=forms.widgets.Select()
    )

python_day22_Django-6 (form)

MultipleChoiceField 多选框

    hobby2 = forms.MultipleChoiceField(
        choices=((1, "吃饭"), (2, "睡觉"), (3, "做梦"),),
        label="多选爱好",
        initial=3,    # 初始化选择框
        widget=forms.widgets.SelectMultiple()
    )

python_day22_Django-6 (form)

单选CheckboxInput

    keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

python_day22_Django-6 (form)

多选框 CheckboxSelectMultiple

    keep2 = forms.MultipleChoiceField(
        choices=((1, "吃饭"), (2, "睡觉"), (3, "做梦"),),
        label="多选爱好",
        initial="checked",    # 初始化选择框
        widget=forms.widgets.CheckboxSelectMultiple()
    )

css中可以直接去掉li的点

python_day22_Django-6 (form)

2、实例

2.1、实例(form简化版注册)

1、Html页面
    <link rel="stylesheet" href="/static/bootstrap_3.3.7_css_bootstrap.min.css">
<div class="container">
    <div class="row form-top">
        <div class="col-md-5 col-sm-offset-3">
            <form action="/reg/" method="post" novalidate>
                {% csrf_token %}
                <div class="form-group">
                    <label for={{ form_obj.name.id_for_label }}>{{ form_obj.name.label }}</label>
                    {{ form_obj.name }}
                    <span class="help-block">{{ form_obj.name.errors.0 }}</span>
                </div>
                <div class="form-group">
                    <label for={{ form_obj.passwd.id_for_label }}>{{ form_obj.passwd.label }}</label>
                    {{ form_obj.passwd }}
                    <span class="help-block">{{ form_obj.passwd.errors.0 }}</span>
                </div>
                <input type="submit" value="提交">
            </form>

        </div>
    </div>
</div>

2、urls.py
urlpatterns = [
    path("reg/", views.reg),
]

3、html_form.py
在应用下创建html_form.py文件

# 导入模块,并且继承引用
from django import forms     

class RegForm(forms.Form):
    name = forms.CharField(
        label="帐号:",
        min_length=6,
        error_messages={
            "min_length": "最小长度为6",
            "required": "输入不能为空",
        },
        widget=forms.widgets.Input(
            attrs=({"class":"form-control"})
        )
    )

    passwd = forms.CharField(
        label="密码",
        min_length=6,
        max_length=16,
        error_messages={
            "min_length": "最小长度为6",
            "max_length": "超过最大长度",
            "required": "输入不能为空",
        },
        widget=forms.widgets.PasswordInput(
            attrs=({"class":"ap1 form-control"})
        ),
    )

4、models.py文件    创建一个用户注册使用的数据库
from django.db import models

# Create your models here.
class UserRegister(models.Model):
    name = models.CharField(max_length=16, unique=True, null=False)
    passwd = models.CharField(max_length=16, null=False)

控制台下使用
python manage.py makemigrations
python manage.py migrate   创建数据库

5、views.py   视图函数
from django.shortcuts import render, redirect, HttpResponse
from login.html_forms import  RegForm
from login import models

def reg(request):  
    form_obj = RegForm()      # 初始化类
    if request.method == "POST":     # 当它是post时才执行这个
        form_obj = RegForm(request.POST)
        if form_obj.is_valid():      # 当输入的检验通过时才继续往下执行
      # cleaned_data (当校验通过时forms字典,类似于各种request.POST.get("xxxxxx"))
            form_register_list = form_obj.cleaned_data    
          # 获取用户是否存在数据库中,如果存在就返回注册界面,如果不存在就创建
            ret = models.UserRegister.objects.filter(name=form_register_list.get("name"))
            print(ret)
            if ret:
                return redirect("/reg/")
            else:
                models.UserRegister.objects.create(**form_register_list)
            return HttpResponse("注册成功")

    return render(request, "reg.html", {"form_obj": form_obj})

python_day22_Django-6 (form)
python_day22_Django-6 (form)
python_day22_Django-6 (form)

2.2、校验判断用户及密码

1、html页面
<div class="container">
    <div class="row form-top">
        <div class="col-md-5 col-sm-offset-3">
            <form action="/reg/" method="post" novalidate>
                {% csrf_token %}
                <div class="form-group">
                    <label for={{ form_obj.name.id_for_label }}>{{ form_obj.name.label }}</label>
                    {{ form_obj.name }}
                    <span class="help-block">{{ form_obj.name.errors.0 }}</span>
                </div>

                <div class="form-group">
                    <label for={{ form_obj.pwd.id_for_label }}>{{ form_obj.pwd.label }}</label>
                    {{ form_obj.pwd }}
                    <span class="help-block">{{ form_obj.pwd.errors.0 }}</span>
                </div>

                <div class="form-group">
                    <label for={{ form_obj.re_pwd.id_for_label }}>{{ form_obj.re_pwd.label }}</label>
                    {{ form_obj.re_pwd }}
                    <span class="help-block">{{ form_obj.re_pwd.errors.0 }}</span>
                </div>

                <input type="submit" value="提交">
            </form>

        </div>
    </div>
</div>

2、urls.py 不变

3、html_forms.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-

from django import forms
from login import models
from django.core.exceptions import ValidationError

class RegForm(forms.Form):
    name = forms.CharField(
        label="帐号:",
        min_length=6,
        error_messages={
            "min_length": "最小长度为6",
            "required": "输入不能为空",
        },
        widget=forms.widgets.Input(
            attrs=({"class": "form-control"})
        )
    )

    pwd = forms.CharField(
        label="密码",
        min_length=6,
        max_length=16,
        error_messages={
            "min_length": "最小长度为6",
            "max_length": "超过最大长度",
            "required": "输入不能为空",
        },
        widget=forms.widgets.PasswordInput(
            attrs=({"class":"form-control"}),
            # 失败不清空
            render_value=True,
        ),
    )

    re_pwd = forms.CharField(
        label="确认密码",
        min_length=6,
        max_length=16,
        error_messages={
            "min_length": "最小长度为6",
            "max_length": "超过最大长度",
            "required": "输入不能为空",
        },
        widget=forms.widgets.PasswordInput(
            attrs=({"class":" form-control"}),
            render_value=True,
        ),
    )

    # 钩子函数,调用hasattr反射函数
    def clean_name(self):
        name = self.cleaned_data.get("name")
        ret = models.UserRegister.objects.filter(name=name)
        if ret:
            raise ValidationError("用户已存在")
        return name

    # 钩子函数, 获取两次密码,并让它相比较
    def clean(self):
        pwd = self.cleaned_data.get("pwd")
        re_pwd = self.cleaned_data.get("re_pwd")
        print(self.cleaned_data)
        if pwd != re_pwd:
            # 如果不添加add_error那么 print(form.error) <ul class="errorlist"><li>__all__<ul class="errorlist nonfield"><li>二次密码不一致</li></ul></li></ul>
            self.add_error("pwd", ValidationError("两次密码不一致"))
            raise ValidationError("二次密码不一致")
        return self.cleaned_data

4、view.py
from django.shortcuts import render, redirect, HttpResponse
from login.html_forms import  RegForm
from login import models
# Create your views here.

def cz_login(request):
    print(request.GET)
    return render(request, "index.html")

def reg(request):
    form_obj = RegForm()
    if request.method == "POST":
        form_obj = RegForm(request.POST)   # 实例化将数据输入
        if form_obj.is_valid():
            form_register_list = form_obj.cleaned_data
            form_register_list.pop("re_pwd")
            models.UserRegister.objects.create(**form_register_list)
            return HttpResponse("注册成功")
        print(form_obj.errors)

    return render(request, "reg.html", {"form_obj": form_obj})

最终效果
python_day22_Django-6 (form)

2.3、使用form提交的大致完整注册界面

目录文件
python_day22_Django-6 (form)

1、settings.py
# 静态文件定义
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),
]

# auth扩展模块,如果手动定义需要增加这个
AUTH_USER_MODEL = 'app01.UserInfo'

2、formd.py   定义forms 生成html页面
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django import forms
from app01 import models
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError

class RgeForm(forms.Form):
    username = forms.CharField(
        label="用户名",
        max_length=16,
        error_messages={
            "required": "帐号不能为空",
            "max_length": "最大长度16",
        },
        widget=forms.widgets.Input(
            attrs={
                "class": "form-control",
            }
        )
    )

    password = forms.CharField(
        label="密码",
        min_length=6,
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "最少6位",
        },
        widget=forms.widgets.PasswordInput(
            attrs={
                "class":"form-control",
            },
            render_value=True,   # 密码如果输入错误,不清空
        )
    )

    re_password = forms.CharField(
        label="确认密码",
        min_length=6,
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "最少6位",
        },
        widget=forms.widgets.PasswordInput(
            attrs={
                "class":"form-control",
            },
            render_value=True,
        )
    )

    phone = forms.CharField(
        label="手机号码",
        min_length=11,
        max_length=11,
        validators=[RegexValidator(r'^[1][1-9]+$',"格式错误")],
        error_messages={
            "required": "不能为空",
            # "invalid": "格式错误",
            "min_length": "最少11位",
            "max_length": "最大11位",
        },
        widget=forms.widgets.TextInput(
            attrs={
                "class":"form-control",
            }
        )
    )

    email = forms.CharField(
        label="邮箱",
        min_length=11,
        max_length=11,
        error_messages={
          "required": "不能为空",
        },
        widget=forms.widgets.TextInput(
            attrs={
                "class":"form-control",
            }
        )
    )

    # 判断密码是否一致, 如果不一致增加错误提示
    def clean(self):
        password = self.cleaned_data.get("password")
        re_password = self.cleaned_data.get("re_password")
        if password != re_password:
            self.add_error("password","二次密码不一致")
            raise ValidationError("二次密码不一致")
        return self.cleaned_data

    # 判断用户是否存在
    def clean_username(self):
        username = self.cleaned_data.get("username")
        ret = models.UserInfo.objects.filter(username=username)
        if ret:
            self.add_error("username","用户已存在")
            raise ValidationError("用户已存在")
        return username

3、html页面     reg2.html
<head>
    <meta charset="UTF-8">
    <title>reg</title>
    <link rel="stylesheet" href="/static/bootstrap/bootstrap-3.3.1.min.css">
    <style>
        .form-top {
            margin-top: 50px;
        }
    </style>
</head>
<body>

<div class="container">
    <div class="row form-top">
        <div class="col-md-6 col-md-offset-3">
            <form action="/regs2/" method="post" novalidate>
                {% csrf_token %}
                <div class="form-group">
                    <label for={{ form_obj.username.id_for_label }}>{{ form_obj.username.label }}</label>
                    {{ form_obj.username }}
                    <span class="help-block">{{ form_obj.username.errors.0 }}</span>
                </div>

                <div class="form-group">
                    <label for={{ form_obj.password.id_for_label }}>{{ form_obj.password.label }}</label>
                    {{ form_obj.password }}
                    <span class="help-block">{{ form_obj.password.errors.0 }}</span>
                </div>

                <div class="form-group">
                    <label for={{ form_obj.re_password.id_for_label }}>{{ form_obj.re_password.label }}</label>
                    {{ form_obj.re_password }}
                    <span class="help-block">{{ form_obj.password.errors.0 }}</span>
                </div>

                <div class="form-group">
                    <label for={{ form_obj.phone.id_for_label }}>{{ form_obj.phone.label }}</label>
                    {{ form_obj.phone }}
                    <span class="help-block">{{ form_obj.phone.errors.0 }}</span>
                </div>

                <div class="form-group">
                    <label for={{ form_obj.email.id_for_label }}>{{ form_obj.email.label }}</label>
                    {{ form_obj.email }}
                    <span class="help-block">{{ form_obj.email.errors.0 }}</span>
                </div>

                <input type="submit" value="提交">
            </form>

        </div>

    </div>
</div>

4、views.py 
from django.shortcuts import render, redirect, HttpResponse
from app01 import formd
from app01 import models
# Create your views here.

def register2(request):
    form_obj = formd.RgeForm()

    if request.method == "POST":
        form_obj = formd.RgeForm(request.POST)   # django自动生成的 html页面
        print(form_obj)  #<tr><th><label for="id_name">用户名:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="name" maxlength="16" required id="id_name" /></td></tr>
        if form_obj.is_valid():     # 如果返回true就继续执行
            form_userinfo_list = form_obj.cleaned_data
            form_userinfo_list.pop("re_password")
            models.UserInfo.objects.create_user(**form_userinfo_list)
            return HttpResponse("用户注册成功")
    return render(request, "reg2.html", {"form_obj": form_obj})

5、models.py 
from django.db import models
from django.contrib.auth.models import AbstractUser

# Create your models here.
class UserInfo(AbstractUser):
    """
    用户扩展表
    """
    phone = models.CharField(max_length=11, null=True)   # 允许为空
    addr = models.CharField(max_length=200, null=True)

    def __str__(self):
        return self.phone

python_day22_Django-6 (form)

MVC 说明
python_day22_Django-6 (form)
MTV 说明
python_day22_Django-6 (form)
python_day22_Django-6 (form)

FAQ

在settings.py中修改  
LANGUAGE_CODE = "zh-hans"   后台会显示为中文 当时间会提前8小时
\# TIME_ZONE = 'UTC'   将UTC修改成上海时间就能解决
TIME_ZONE='Asia/Shanghai'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章