day03 ajax删除操作、form组件

回顾

发送请求的途径:

  1. 直接在地址栏输入地址  get
  2. form表单提交  method=''  post/get
  3. a标签  get
  4. ajax

ajax

使用js的技术与服务器进行异步交互。

特点:

  1. 异步
  2. 局部刷新
  3. 传输的数据量小

使用

// 导入jquery.js

上传文件

html上传

前提条件:必须确保有csrftoken的cookie

  1. 使用{% csrf_token %}的标签
  2. 给视图函数加上ensure_csrf_cookie的装饰器

ajax通过django的csrf的校验:

  1. 给data中添加csrfmiddlewaretoken
  2. 给headers中添加x-csrftoken的请求头

推荐的方式:导入文件 + 使用{% csrf_token %}

csrf中间件的流程:

  1. process_request

    从cookie中获取了csrftoken的值将该值放入request.META中

  2. process_view

    1. 如果是 直接接受该请求,不做csrf的校验

    2. 不是 则进行csrf的校验

    3. csrf_token = request.META.get('CSRF_COOKIE')  # cookie中csrftoken的值

    4. request_csrf_token = ""

    5. 请求方式是post,尝试从request.POST中获取csrfmiddlewaretoken的值

      request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
    6. 如果request_csrf_token = "",再尝试从请求头中获取X-CSRFTOKEN的值

      request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')
    7. 比较csrf_token和request_csrf_token,成功则通过,不成功则拒绝

    8. 判断视图是否使用了csrf_exempt的装饰器,使用了就不再进行csrf的校验

    9. 判断请求方式是否是get head potions trace:

小案例 ajax发送请求进行删除操作

删除 {
                if (willDelete) {
                    $.ajax({
                        url: $(this).attr('url'),
                        type: 'get',
                        success: (data) => {
                            if (data.status === 200) {
                                $(this).parent().parent().remove()
                                swal("数据已成功删除", {
                                    icon: "success",
                            } else {
                                swal("删除失败!", {
                                    icon: "error",
                } else {
                    swal("已取消",{
                        icon: "info",
    })" _ue_custom_node_="true">
def delete(request, name, pk):
    print(name, pk)
    # 找到要删除的对象 进行删除
    cls = getattr(models, name.title())
    if not cls:
        return HttpResponse('检测表名')
    ret = cls.objects.filter(pk=pk)
    if ret:
        ret.delete()
    else:
        return HttpResponse('要删除的数据不存在')
    # 返回重定向
    # return redirect(name)  # redirect里可以直接写上url的name
    # return HttpResponse('ok')
    # return HttpResponse(reverse(name))  # 返回重定向的地址,让ajax通过前端去刷新页面
    return JsonResponse({'status': 200})

form组件

定义:

from django import forms
class RegForm(forms.Form):
    user = forms.CharField(label='用户名')
    pwd = forms.CharField(label='密码')

使用:

def reg2(request):
    form_obj = RegForm()  # 空的form
    if request.method == 'POST':
        # 对提交的数据做校验
        form_obj = RegForm(request.POST)  # 包含用户提交的数据的form
        if form_obj.is_valid():  # 对数据进行校验
            # 校验成功
            return HttpResponse('注册成功')
    return render(request, 'reg2.html', locals())

模板

// 一次性生成所有的标签{% csrf_token %}
    {{ form_obj.as_p }}注册// 单独的生成input框
{# novalidate 不在前端做校验#}{% csrf_token %}{{ form_obj.user.label }}{{ form_obj.user }}        {{ form_obj.user.errors.0 }}
    {{ form_obj.pwd.label }}{{ form_obj.pwd }}        {{ form_obj.user.errors.0 }}
    {#    {{ form_obj.errors }}#}注册
MultipleChoiceField{{ form_obj.as_p }}  # 一次性生成所有的input框
{{ form_obj.user }}  # 该字段的input框
{{ form_obj.user.label }}  # 该字段提示的信息
{{ form_obj.user.id_for_label }}  # 该字段的input框的id
{{ form_obj.user.errors}}  # 该字段的所有错误
{{ form_obj.user.errors.0}}  # 该字段的第一个错误
{{ form_obj.errors }}  # 所有字段的错误

常用字段

CharField  # 文本输入框
ChoiceField  # 单选 默认是select
MultipleChoiceField  # 多选 默认是select

常用参数

initial = "hina"  # 默认值
choices  # 用户选择的数据
error_messages  # 自定义错误信息
widget  # 插件  修改input框的类型
required=True  # 是否必填
disabled=True  # 是否禁填
validators  # 校验器

校验器

  1. 定义函数

    from django.core.exceptions import ValidationError
    def check_name(value):
        # 不符合校验规则
        if 'hina' in value:
            raise ValidationError('hina的名字不合适')
        # 符合校验不做任务操作
  2. 使用内置的校验器

    from django.core.validators import RegexValidator
    phone = forms.CharField(validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式不正确')])

钩子函数

  1. 局部钩子

    # 一定要写在类中
    def clean_user(self):  # 局部钩子
    # 不符合校验规则 抛出异常
    value = self.cleaned_data.get('user')
    if 'hina' in value:
    raise ValidationError('hina的名字不合适')
    # 符合校验规则 返回该字段的值
    return value
  2. 全局钩子

    def clean(self):  # 全局钩子
        pwd = self.cleaned_data.get('pwd')
        repwd = self.cleaned_data.get('repwd')
        if pwd != repwd:
            # 不符合校验规则 抛出异常
            # 将错误信息加入到某个字段中
            self.add_error('repwd', '两次密码不一致!!!')
            raise ValidationError('两次密码不一致')
            # 符合校验规则 返回该字段的值
            return self.cleaned_data

is_valid()的流程:

  1. 执行一个full_clean方法

    1. 定义了一个错误字典和 cleaned_data={}  # 存已经经过校验的数据的字典

    2. 执行self._clean_fields()

      循环所有字段

      对一个字典进行内置校验、校验器校验、局部钩子校验

      校验不通过,将该字段以及对应的错误信息加入该字典

      所有校验通过,self.cleaned_data有该字段和该字段的值

    3. 执行全局钩子