Django-- (四) Django请求、表单验证、会话

1、常见的请求方式

默认页面请求都是get请求,常用的请求方式get和post:
1、get:默认是get请求,请求数据以明文形式放在路由上,get的格式是以?开头,键等于值的形式,以&来分割键值对,通常用于向服务器获取资源。
https://www.baidu.com/s?wd=张三&rsv_spt=1
2、post:请求数据隐藏发送,安全系数更高。通常用于向服务器提交资源。

2、请求对象

视图函数中request是传递到视图的请求对象,包含了本次请求所有的信息。

request对象的类型是django.http.HttpRequest,常用属性如表所示:

属性描述
request.GET获取get请求数据的方法
request.POST获取post请求数据的方法
request.FILES获取文件上传请求数据的方法
request.method获取请求的方法
request.META请求的详细参数
request.META.OS请求端系统
request.META.HTTP_USER_AGENT用户请求头,返回请求浏览器版本
request.META.HTTP_HOST请求的主机
request.META.HTTP_REFERER请求的来源

3、表单请求

3.1 get请求

在表单中默认使get请求提交表单

属性说明
action提交的地址,默认是当前路由。
method提交的方法,默认是get
name用来做传参的标识
submit会自动提交当前表单的数据

获取get请求的表单数据

# 获取表单中name的值为username的数据
username = request.GET.get("username")
3.2 post请求

表单使用post请求提交时需要进行CSRF验证,在Django的1.4版本之前,CSRF默认关闭,需要在settings当中手动开启,在1.4之后,默认开启。

在Django的任何post请求,都会在请求之初,给用户下发一下串用来校验身份的编码,并且每次请求不一样。如果不加csrf校验,则会发生错误。

使用Django的csrf校验

视图必须以render函数返回页面,render函数的功能和render_to_response功能类似,但是会返回请求到前端,这样,前端就可以调用csrf_token了,前端必须在form表单当第一行加入csrf_token标签。使用如下

def login(request):
    """登录"""
    if request.method == "POST":
        pass
    return render(request, "login.html", locals())
<form class="user" method="post">
    {% csrf_token %}
    
    <div class="form-group">
        <input type="text" class="form-control" name="username" id="username" placeholder="用户名">
    </div>
    
    <div class="form-group">
        <input type="password" class="form-control" name="password" id="password" placeholder="密码">
    </div>
    
    <button type="submit" class="btn btn-primary btn-user btn-block">
        登陆
    </button>
    <hr>
</form>
3.3 文件上传
3.3.1 settings配置

文件的上传需要设置上传文件的位置,在settings中修改

文件的位置还可以在模型中指定,例如upload_to=“store/img”,在static文件下创建store/img,从而实现文件存储在/static/store/img目录下。开发者也不用考虑文件名重复的问题,框架会自动修改有相同名字的文件。

picture = models.ImageField(null=True, upload_to="store/img")

3.3.2 文件上传

form表单设置

需要设置method=“post” enctype=“multipart/form-data”, 如下

<form method="post" class="form" enctype="multipart/form-data" action="/goods/">
    {% csrf_token %}
    <div class="form-group">
        <label class="">商品名称</label>
        <input class="form-control" type="text" name="name">
    </div>
    <div class="form-group">
        <label class="">商品图片</label>
        <input class="form-control" type="file" name="picture">
    </div>
    <button class="btn btn-primary fa-pull-right" type="submit">提交商品</button>
</form>

后端处理

普通文字:request.POST.get

文件字段:request.FILES.get

def goods(request):
    if request.method == "POST":
        name = request.POST.get("name")
        picture = request.FILES.get("picture")
        goods = Goods()
        goods.name = name
        goods.picture = picture
        goods.save()
    return render(request, "goods.html", locals())
3.3.3 新增

goods.save()
文件会自动保存到MEDIA_ROOT设置的路径中,数据库中的名字默认是文件的名字,若设置了upload_to属性,数据库中存储的数据是upload_to的字段加上文件名。

4、表单类

4.1 表单类介绍

用户表单是Web端的一项基本功能,大而全的Django框架中自然带有现成的基础Form对象。
Form表单的功能:
1、自动生成HTML表单元素
2、检查表单数据的合法性(后端验证)
3、如果验证错误,重新显示表单(数据不会重置)
4、数据类型转换(字符类型的数据转换成相应的Python类型)
Django表单类,带有前后端验证的。
1、前端验证:
Django表单类对象渲染到模板后,会变成HTML附带属性标签,这些是属性一般是HTML5的属性,可以交互。
2、后端验证
通过将request的参数传给Form,得到一个Form对象,调用这个对象的is_valid方法,如果返回True表示参数通过验证,否则不通过验证。

4.2 表单类的使用

创建表单类

# form.py  表单类文件

from django import forms


class RegisterForm(forms.Form):
    username = forms.CharField(
        required=True,  # 是否必须填写
        min_length=2,  # 最小长度
        max_length=10,  # 最大长度
        error_messages={  # 用字典来存储每个验证的错误信息
            "required": "用户名必填",
            "min_length": "用户名至少是2位",
            "max_length": "用户名不能超过10位"
        }
    )
    password = forms.CharField(
        required=True,
        error_messages={
            "required": "密码必填"
        }
    )

视图,处理表单校验的结果及业务逻辑

# views.py
def register(request):
    """注册"""
    if request.method == "POST":
        # 获取参数,放入表单校验
        register_form = RegisterForm(request.POST)
        if register_form.is_valid():  # 判断表单是否校验成功
            # 获取表单提交验证后的数据
            username = register_form.data.get("username")
            password = register_form.data.get("password")
            # 查询是否有该用户
            seller = Seller.objects.filter(name=username).first()
            if not seller:
                # 注册用户
                seller = Seller()
                seller.name = name
                seller.password = encrypt_password(password)
                seller.save()
                return redirect("/login/")
    return render(request, "register.html", locals())

前端渲染

注:可以用断点调试的方法查看一个对象的数据,例如查看register_form的所有属性,根据需求在前端渲染需要的数据。

<!--register.html-->

<form class="user" method="post">  <!-- 不写action默认提交到原路由 -->
    {% csrf_token %}
<div class="form-group row">
    <div class="col-sm-12 mb-3 mb-sm-0">
        <input type="text" name="username" class="form-control form-control-user" id="username" placeholder="用户名" value="{{ register_form.data.username }}">
    </div>
    <p class="container-fluid" style="color: red; margin-top: 5px;">
        {{ register_form.errors.username.0 }}  <!-- 调用表单校验后register_form对象的username的错误属性返回前段显示 -->
    </p>
</div>
<div class="form-group">
    <input type="password" name="password" class="form-control form-control-user" id="password" placeholder="密码">
    <p class="container-fluid" style="color: red; margin-top: 5px;">
        {{ register_form.errors.username.0 }}
    </p>
</div>

<button type="submit" class="btn btn-primary btn-user btn-block">
    注册用户
</button>
</form>

5、表单校验

5.1 常用验证器

在验证某个字段的时候,可以传递一个validators参数用来指定验证器,进一步对数据进行过滤。

常用的验证器

验证器描述
MaxValueValidator验证最大值。
MinValueValidator验证最小值
MinLengthValidator验证最小长度
MaxLengthValidator验证最大长度
EmailValidator验证是否是邮箱格式
URLValidator验证是否是URL格式
RegexValidator正则表达式的验证

案例:验证用户名是2-10位字母数字下划线组成的。

# form.py

from django.core.validators import RegexValidator


class RegisterForm(forms.Form):
    username = forms.CharField(
        required=True,
        validators=[
            RegexValidator(
                r"^[a-zA-Z0-9_]{2,10}$",  # 正则表达式
                "用户名只能是2-10位字母数字下划线组成"  # 验证失败提示信息
            )
        ],
        error_messages={
            "required": "用户名必填"
        }
    )
    password = forms.CharField(
        required=True,
        error_messages={
            "required": "密码必填"
        }
    )

视图,和前端渲染同4.2

结果如下:

5.2 自定义验证

Django表单类也提供了对特定字段的自定义验证,在Form类中定义实例方法,如果验证失败,抛出ValidationError异常,否则正常返回值。
案例: 验证用户名是否包含敏感词

class Sensitive_Word():
    """类式自定义"""
    def __call__(self, value):
        datas = ["admin", "nb", "sb"]
        for data in datas:
            if value.find(data) != -1:
                raise ValidationError("用户名不能含有敏感词汇")


def sensitive_word(value):
    """函数式自定义"""
    datas = ["admin", "nb", "sb"]
    for data in datas:
        if value.find(data) != -1:
            raise ValidationError("用户名不能含有敏感词汇")


class RegisterForm(forms.Form):
    username = forms.CharField(
        required=True,
        validators=[
            RegexValidator(
                r"^[a-zA-Z0-9_]{2,10}$",
                "用户名只能是2-10位字母数字下划线组成"
            ),
            # Sensitive_Word(),  # 自定义类校验器的调用
            sensitive_word  # 自定义函数校验器的调用
        ],
        error_messages={
            "required": "用户名必填"
        }
    )
    password = forms.CharField(
        required=True,
        error_messages={
            "required": "密码必填"
        }
    )

视图,和前端渲染同4.2

6、会话

Django的时间默认是使用UTC,与我们本地相差了8个小时。因cookie和session具有时效性,需要设置成我们当前的时区。

Django的response获取的方式有:

response= HttpResponse(“xx”)

response= render(request,”xx.html”)

response= redirect(“/index”)

6.1 cookie

1、创建cookie

response.set_cookie(,,有效期)  # 有效期单位是秒

2、删除cookie

response.delete_cookie()

3、获取cookie

request.cookie.get()

cookie可以用来存储一些不重要的数据,比如用户的账号和昵称等,把这些信息回显到前端,实现用户下一次登录时不用再输入账号。(如“记住我”这样的功能)

6.2 session

Django中默认配置把session数据存储到了数据库中。

session的操作
1、创建session

request.session[] =# 有效期默认是2周,可以修改
request.session.set_expiry(时间)  #单位是秒

2、获取session

request.session.get()

3、删除session

del request.session[]  # 删除一个键值对
request.session.clear()   # 删除所有键值对

服务器获取不到session,验证失败的情况:
1、客户端没有发来sessionid
2、客户端发来sessionid,但是从数据库中找不到
3、客户端发来sessionid,从数据库中找到了,但是过期了

上述三种情况都是导致session的验证失败

案例:创建检测用户的登录状态的装饰器,实现在session验证通过的情况下才能访问相应页面

from functools import wraps

def login_check(fun):
    @wraps(fun)
    def inner(*args, **kwargs):
        if not args[0].session.get("logined"):
            # 未登录
            return redirect("/login")
        else:
            return fun(*args, **kwargs)
    return inner


@login_check
def index(request):
    return render(request, "index.html", locals())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值