<学习笔记>从零开始自学Python-之-web应用框架Django( 八)Django表单

        HTML 表单是交互式网站的基本组成部分,用户提交信息、搜索内容、与后台数据交互都要用到表单。

1、从请求对象中获取数据

        view视图函数的第一个参数都是 request,这个request就是请求获得的HttpRequest对象。里面包含中有一些关于当前所请求 URL 的信息,如下图

HttpRequest对象的方法和属性
属性/方法 说明 示例
request.path 完整的路径,不含域名,但是包 含前导斜线 “/hello/”
request.get_host() 主机名(即通常所说的“域名”) “127.0.0.1:8000”或www.newweb.com
request.get_full_path() 包含查询字符串(如果有的话) 的路径 “/hello/?print=true”
request.is_secure() 通过 HTTPS 访问时为 True,否 则为 False True 或 False

2、关于请求的其他信息

        request.META 的值是一个 Python 字典,包含请求的所有 HTTP 首部,例如用户的 IP 地址和用户代理(user agent,通常是 Web 浏览器的名称和版本)。

        注意,具体包含哪些首部取决于用户发送了什么首部,以及 Web 服务器返回了什么首部。

这个字典中常见的几个键有:

• HTTP_REFERER:入站前的 URL(可能没有)。(注意,要使用错误的拼写,即 REFERER。)

• HTTP_USER_AGENT:浏览器的用户代理(可能没有)。例如:"Mozilla/5.0 (X11; U; Linux i686; frFR; rv:1.8.1.17) Gecko/20080829 Firefox/2.0.0.17"。

• REMOTE_ADDR:客户端的 IP 地址,例如 "12.345.67.89"。(如果请求经由代理,这个首部的值可能是一 组 IP 地址,以逗号分隔,例如 "12.345.67.89,23.456.78.90"。)

注意,因为 request.META 是个普通的 Python 字典,所以尝试访问不存在的键时,抛出 KeyError 异常。 (HTTP 首部是外部数据,即由用户的浏览器提交,因此不能完全相信,当某个首部为空或不存在时,应该让应用程序优雅失败。)为了处理未定义的键,应该使用 try/except 子句,或者 get() 方法:

# 用try语句
def ua_display_good1(request):
    try:
        useragent = request.META['HTTP_USER_AGENT']
    except KeyError:
        useragent = 'unknown'
        return HttpResponse("Your browser is %s" % useragent)



# 用get方法
def ua_display_good2(request):
    useragent = request.META.get('HTTP_USER_AGENT', 'unknown')
    return HttpResponse("Your browser is %s" % useragent)

也可以编写一个简单的视图,显示 request.META 中的所有信息,以便查阅。

def display_meta(request):
    values = request.META.items()
    values
    html = []
    for k, v in values:
        html.append('<tr><td>%s</td><td>%s</td></tr>' % (k, v))
    return HttpResponse('<table>%s</table>' % '\n'.join(html))

3、用表单实现查询功能

        除了关于请求的基本元数据之外,HttpRequest 对象还有两个属性包含用户提交的信息:request.GET 和 request.POST。这两个属性的值都是类似字典的对象,分别用于获取 GET 和 POST 数据。POST 数据一般由 HTML 表单提交,而 GET 数据既可以来自表单,也可以来自页面 URL 中的查询字符串。

        我们利用request.GET 和 request.POST就可以实现前后端之间的通信,让用户提交的信息传递给服务器,服务器进行响应。

        我们前面的案例中说到可以用url传输信息给后端,但那不是个好办法,现在我们改用表单传输数据,实现查询功能。我们先在之前的 'notice/'  url 对应的 class3.html 增加一个查询表单(纯属偷懒,表单应该放到页面合适的地方去)

<form action="/search/" method="get">
    <h3>根据姓名查找同学</h3>
<input type="text" name="chaxun">
<input type="submit" value="查询">
</form>

这里 method = ‘get’表示请求的方法为  get

<h3>这一行是标题,告诉用户这个表单是干嘛的,应该填什么数据,可要可不要

第一个input 的 name='chaxun' 这是后面我们找数据是要用到的标签名称

第二个input 的 type = 'submit' 表示这是一个提交按钮,value='查询' 表示它在页面上显示为“查询”

看一下页面:

 然后我们来写个视图函数 chaxun1

def chaxun1(request):
    studentName = request.GET['chaxun']
    s = Student.objects.get(name=studentName)
    return HttpResponse('你要查询的{}同学信息如下:姓名:{},年龄{},性别{},成绩{},武力值{}'.format(s.name,s.name,s.age,s.sex,s.score,s.skill))

然后我们在上面的文本框中输入 “黄蓉”,点击查询按钮,得到如下结果:

 4、改进表单

       上面这个表单虽然实现了我们预期的功能,但是还不完善。比如如果用户提交的是个空表单怎么办,如果用户提交的信息数据库里查不到怎么办,我们不能总是报错啊,现在我们来着手改进这个表单:

if request.GET and request.GET['chaxun']:             #确保GET方法获得了值,并且'chaxun'标签(就是那个提交查询内容的输入框)不为空
        studentName = request.GET['chaxun']
        try:                                              #确保要查询的数据存在
            s = Student.objects.get(name=studentName)
            result = '你要查询的{}同学信息如下:姓名:{},年龄{},性别{},成绩{},武力值{}'.format(s.name,s.name,s.age,s.sex,s.score,s.skill)
            context['result']=result
        except:
            context['result']='查无此人'                   #如果查不到,显示“查无此人”并返回同一个页面
        return render(request,'class3.html',context=context,status=200)

    else:                                                 #如果输入为空,曾刷新页面,重新填写
        
        return render(request, 'class3.html')

这样改造后,我们再查询页面,就可以直接看到结果了,输入空值则会返回当前页面继续填写

5、Django的表单类

        用户在填写表单的时候,谁也不知道用户会写些什么,为了数据能够按规范填写,就需要对用户的填写行为进行约束,也就是表单的验证。我们当然可以自己手动去写这些验证方法,不过Django已经贴心地为我们准备好了内置的表单库,django.forms,它能处理从显示 HTML 表单到验证的大多数问题,即开即用。

        我们用一个例子来演示一下这个表单类怎么用。比如上面那个查询功能,我们现在用forms表单类把它集成实现。

        首先新建一个forms.py文件(当然也可以直接写在views.py,不过一般Django风格都是给forms单独一个文件)我们定义一下我们需要的字段。这里的字段其实是显示在前端给用户看的,所以想要让用户输入什么字段,就在这里定义,比如我们这里打算让用户可以通过 姓名、年龄 和 成绩这三个条件来查询:

from django import forms                          #注意这里要从django引入forms库
class chaxunForm(forms.Form):                     #定义一个查询类
    #这里label就是前端显示的输入框的提示文字,max_length是输入的最大长度,
    #required=False是允许这个值为空,因为我们期望的是通过每个条件单独都可以查询

    name = forms.CharField(label="名字",max_length=10,required=False)         

    #这里可以定义输入数值的大小,用max_value  和 min_value 参数来设定上下限
    age = forms.IntegerField(label="年龄",required=False,max_value=100,min_value=10)
    score = forms.IntegerField(label="成绩",required=False)

为了方便演示,我们另外写了个HTML页面文件 chaxun.html,反正用模板继承很方便

{% extends "base.html" %}
{% block title %}武侠三班的小窝{% endblock %}

{% block main %}
<h1>查询页面,在这里可以查找你想了解的同学</h1>

<form action="" method="post">{% csrf_token %}
    <h3>根据条件查找同学</h3>
        {
   
   {form}}
    <input type="submit" value="查询">
</form>


<P>
    {% for result in results %}
<div>{
   
   {result}}</div>
    {% endfor %}
</P>


{% endblock %}

注意这里页面上的输入框不用我们自己手动写了,form类会自动把自定义的字段转成input输入框  然后我们去views.py调用这个类,

from classManage.forms import chaxunForm
........
#其他代码
........
def chaxun4(request):
    context={}
    form=chaxunForm(request.POST) 
    if request.method == 'POST':                #这里要注意确认一下方法为POST
        form = chaxunForm(request.POST)         #实例化一个我们在forms.py里面定义的chaxunForm类
        context['form']=form                    #把form实例赋值给字典的 'form',方便前端调用
        results = []
        if form.is_valid():                     #确保form的数据有效,这个验证工作forms类帮我们做了
            stuName = form.cleaned_data.get('name')      #cleaned_data是经过清洗的数据  
            stuAge = form.cleaned_data.get('age')
            print(stuAge)
            if stuName:
 #名字一般是唯一的,但是为了上下统一用一个函数比较方便,我们统统用filter,而不是get,然后把数据放到一个列表中去遍历
                stus=Student.objects.filter(name=stuName) 
            elif stuAge:
                stus=Student.objects.filter(age=stuAge)
            elif stuScore: 
                stus=Student.objects.filter(score=stuScore)
            else:
                pass
            for s in stus:
                result = '你要查询的{}同学信息如下:姓名:{},年龄{},性别{},成绩{},武力值{}'.format(s.name,s.name,s.age,s.sex,s.score,s.skill)
                results.append(result)
            print('postresult:',results)
            context['results']=results
            return render(request,'class3.html',context=context,status=200)
    else:
        form = chaxunForm()
        context['form']=form              #把form对象整个赋值给字典的 'form'方便前端调用
    
    return render(request,'chaxun.html',context=context,status=200)

我们去访问页面 http://127.0.0.1:8000/cha/ 看看效果

可以看到出现了 名字、年龄、成绩 三个查询框,我们任意填其中一个,实现查询功能

 

 我们测试一下forms的验证效果,我们在年龄框里面输入汉字,发现根本不给输入,然后我们在年龄这里输入数字5,点击查询后发现它提示我数字必须大于10:

当然这里这个提示不太美观,可以自定义来定制验证信息。总之,forms类可以帮我们进行数据审查,比如如果我们定义了一个forms类的email字段,它会自动审查输入是否为一个email格式,这真的大大简化了我们的工作啊。

所以我们一般做登录、注册表单或者信息提交表单的时候,用这个forms类真的很方便。 

猜你喜欢

转载自blog.csdn.net/qq_41597915/article/details/127239321
今日推荐