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'
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章