06-Django表单

d:/python/demo3

目标

  • form表单
  • get/post
  • Request对象
  • 利用HTML表单开发注册功能
  • Django表单改造注册功能
  • 数据绑定与校验(了解)
  • 数据验证错误信息(了解)
  • 实战任务

表单

表单有如下特征:

  • 1、通过各种<input>、<select>等标签进行数据与参数的对应,用来作为数据载体,传递数据。
  • 2、在<form>标签中的action属性定义url请求的地址。
  • 3、在<form>标签中的method属性定义Http method。

get/post

get/post及区别略

Request对象

每个view函数的第一个参数是一个HttpRequest对象。
request对象的属性
request.scheme
代表请求的方案,http或者https
request.path
请求的路径,比如请求127.0.0.1/org/list,那这个值就是/org/list
request.method
表示请求使用的http方法,GET或者POST请求
request.encoding
表示提交数据的编码方式
request.GET
获取GET请求
request.POST
获取post的请求,比如前端提交的用户密码,可以通过request.POST.get()来获取
另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中
request.COOKIES
包含所有的cookie
request.META
一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:

CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
CONTENT_TYPE —— 请求的正文的MIME 类型。
HTTP_ACCEPT —— 响应可接收的Content-Type。
HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
HTTP_HOST —— 客服端发送的HTTP Host 头部。
HTTP_REFERER —— Referring 页面。
HTTP_USER_AGENT —— 客户端的user-agent 字符串。
QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
REMOTE_ADDR —— 客户端的IP 地址。
REMOTE_HOST —— 客户端的主机名。
REMOTE_USER —— 服务器认证后的用户。
REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。
SERVER_NAME —— 服务器的主机名。
SERVER_PORT —— 服务器的端口(是一个字符串)

request.user
一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。
如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们
把request传给前端的时候,前端可以通过 {% if request.user.is_authenticated %}判断用户时候登录
request.session
一个既可读又可写的类似于字典的对象,表示当前的会话

利用form表单开发注册功能

接下来我们使用HTML表单,模拟一个用户注册功能,并演示如何使用HTML表单以及request对象:

  1. 用户的信息包括:用户名、密码、昵称、邮件地址、自我介绍。
  2. 访问/register注册页面,填写用户信息,点击[注册]按钮使用post方式提交表单。
  3. 提交后,后端校验数据有效性,用户名/密码/昵称为必填项,邮件地址中必须包含'@'。如果不满足有效性,则给出提示。
  4. 通过有效性验证后,页面跳转到新的欢迎页,并回显用户数据。
    1)d:/python/demo3下新建Django工程
    (略)

2)命令行输入以下命令,新建一个formapp,此应用用于测试form

 python manage.py startapp formapp

3)setting.xml里注册formapp

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'formapp',
]

4)主urls加入以下语句

path('forms',include("formapp.urls")),

5)formapp下新建urls.py 交输入以下内容

from django.urls import path
from . import views
urlpatterns = [
    path('', views.goregister, name='goregister'),
    path('register', views.register),
]

6)views.py

def register(request):
    errors = []
    user = {}
    if request.method == 'POST':
        if not request.POST.get('nickname', ''):
            errors.append('请输入昵称.')
        if not request.POST.get('username', ''):
            errors.append('请输入用户名.')
        if not request.POST.get('password', ''):
            errors.append('请输入密码.')
        if request.POST.get('email') and '@' not in request.POST['email']:
            errors.append('请输入有效的邮件地址.')
        if not errors:
            user = {
                'nickname': request.POST['nickname'],
                'username': request.POST['username'],
                'password': request.POST['password'],
                'email': request.POST.get('email', ''),
                'self_intro': request.POST.get('self_intro', ''),
            }
            save_user(user)
            # 使用post提交的表单,Django要求必须使用csrf标签,渲染模板时,请使用render方法
            return render(request, 'success.html', user)
    return render(request, 'register.html', {
        'errors': errors,
        'nickname': request.POST.get('nickname', ''),
        'username': request.POST.get('username', ''),
        'password': request.POST.get('password', ''),
        'email': request.POST.get('email', ''),
        'self_intro': request.POST.get('self_intro', ''),
    })
def save_user(user):
    # 省略保存用户实现过程
    pass

7)页面
formapp/templates目录下新建register.html success.html
register.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Neuedu Django ch03</title>
</head>
<body>
    {% if errors %}
        <ul>
            {% for error in errors %}
            <li>{{ error }}</li>
            {% endfor %}
        </ul>
    {% endif %}

    <!-- action属性不填写时,等同于将表单提交到当前页面的请求地址 -->
    <form action="/forms/register" method="post">
        {# csrf标签是Django提供的防止伪装提交请求的功能。POST方法提交的表格,必须有此标签。 #}
        {% csrf_token %}
        <p>昵称: <input type="text" name="nickname" value="{{ nickname }}" ></p>
        <p>用户名: <input type="text" name="username" value="{{ username }}" ></p>
        <p>密码: <input type="text" name="password" value="{{ password }}" ></p>
        <p>邮件地址: <input type="text" name="email" value="{{ email }}" ></p>
        <p>自我介绍: <textarea name="self_intro" rows="10" cols="50">{{ self_intro }}</textarea></p>
        <input type="submit" value="注册">
    </form>

</body>
</html>

success.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Neuedu Django ch03</title>
</head>
<body>
<h1>恭喜注册成功!您的用户信息如下:</h1>
<p>昵    称: {{ nickname }}</p>
<p>用 户 名: {{ username }}</p>
<p>邮件地址: {{ email }}</p>
<p>自我介绍: {{ self_intro }}</p>
</body>
</html>

8)运行效果


image.png
image.png

Django表单改造注册功能(中英文两套)

d:/python/demo3
上述功能,如果页面需要提交的字段比较多,后台views会特别麻烦。用Django表单组件可以简化这部分工作

Django带有一个form库,称为django.forms,这个库可以处理包括HTML表单显示以及验证的很多内容。接下来我们来深入了解一下form库,学习如何使用Django表单,最后试着使用它来重写我们的用户注册功能。
1)我们在settings目录创建一个python文件,form.py,继承自django.forms.Form,在RegisterForm中定义一些属性,与模型写法类似

from django import forms


class RegisterForm(forms.Form):
    nickname = forms.CharField(max_length=20)
    username = forms.CharField()
    password = forms.CharField()
    email = forms.EmailField(required=False)
    self_intro = forms.CharField(required=False, widget=forms.Textarea)

class RegisterFormChinese(forms.Form):
    nickname = forms.CharField(max_length=20, label='昵称')
    username = forms.CharField(label='用户名')
    password = forms.CharField(label='密码')
    email = forms.EmailField(required=False, label='邮件地址')
    self_intro = forms.CharField(required=False, widget=forms.Textarea, label='自我介绍')

2)改造views.py关键代码

from demo3.form import RegisterForm, RegisterFormChinese
def register(request):
    # get请求访问页面时,返回空表单,post请求提交数据时进行表单验证和页面跳转
    if request.method == 'POST':
        form = RegisterForm(request.POST)
        if form.is_valid():
            return render(request, 'success.html', {'form': form})
    else:
        form = RegisterForm()
    return render(request, 'register.html', {'form': form})


def register_chinese(request):
    if request.method == 'POST':
        form = RegisterFormChinese(request.POST)
        if form.is_valid():
            # 将用户提交的表单回显,并设置不可编辑
            # form.fields 返回一个OrderedDict
            # 我们遍历这个存储着表单字段的字典,并通过widget.attrs设定他们的html属性
            for f in form.fields.values():
                f.widget.attrs['disabled'] = 'disabled'
            return render(request, 'success.html', {'form': form})
    else:
        form = RegisterFormChinese()
    return render(request, 'register_chinese.html', {'form': form})

3)改造register.html

<form action="/forms/register/" method="post">
    {% csrf_token %}
    <table>{{ form }}</table>
    <input type="submit" value="Submit" />
</form>

4)register_chinese.html

<form action="/forms/register_chinese/" method="post">
    {% csrf_token %}
    <table>{{ form }}</table>
    <input type="submit" value="提交" />
</form>

4)改造success.html

<body>
<h1>注册成功</h1>
<table>{{ form }}</table>
</body>

5)formapp.urls.py

from django.urls import path
from . import views
urlpatterns = [
    path('', views.goregister, name='goregister'),
    path('register/', views.register),
    path('register_chinese/', views.register_chinese),
]

6)启动服务

python manage.py runserver

7)浏览器输入地址测试

http://127.0.0.1:8000/forms/register/
http://127.0.0.1:8000/forms/register_chinese/

数据绑定与校验证(了解)

form.is_bound()属性查看表单对象是否已经绑定
form.is_valid()是否所有字段验证通过,返回True/False

数据验证错误信息(了解)

f.errors()提供了一个字段与错误消息相映射的字典表。

代码解释

我们将页面展示与页面提交的地址都设置为formapp/register
在视图中通过request对象的method方法判断页面请求的get/post方法,进行不同的操作。
当页面提交get请求时(直接访问url地址),初始化一个空的表单对象,并返回给页面。
当页面提交post请求时(通过页面html提交表单时),验证表单并跳转到成功页面。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容