路径参数

  • 参数

    • 路径参数

      • 位置参数

        • 按照书写顺序进行匹配
      • 关键字参数

        • 按照参数名称匹配,和顺序就无关了
    • 参数个数必须和视图函数中参数个数一致(除默认的request以外)

    实践:3个参数的请求响应

    添加url:

url('gettime/(\\d+)/(\\d+)/(\\d+)', views.get_time),

添加views:

def get_time(request, hour, minute, second):
    return HttpResponse('Time %s:%s:%s' % (hour, minute, second))

我们在后面添加了三个参数12/12/12成功返回响应:

但当我们改变参数位置时,响应数据也会发生改变

def get_time(request, hour, minute, second):
    return HttpResponse('Time %s:%s:%s' % (minute, hour, second))


这是因为这种参数叫做位置参数,按照输入顺序12/1/12的顺序进行参数传递

想要不改变位置,我们可以采用关键字参数

添加新的url:

url('getdate/(?P<year>\\d+)/(?P<month>\\d+)/(?P<day>\\d+)', views.get_date),

我们这里采用?P<参数名称>设置参数名称

views:

def get_date(request, year, day, month):
    return HttpResponse('date %s-%s-%s' % (day, year, month))

按照参数名称匹配,和顺序无关

url反向解析

  •  在根urls中

             path('views/', include(('ViewsLearn.urls',app_name),namespace='view')),

  •  在子urls中

 url('hello/(\d+)',views.hello,name='sayhello'),

  • 在模板中使用

  <a href="{% url 'view:sayhello' 
year=2017 %}">Hello
  year 的位置如果不指定名称按顺序算,指定名称按=算

  • 在视图中使用

              HttpResponseRedirect(reverse('view:sayhello',kwargs={}))
        kwargs是字典

  • 反向解析

    • 根据根路由中注册的namespace和在子路由中注册name,这两个参数来动态获取我们的路径
    • 在模板中使用  {% url 'namespace:name'  %}
    • 如果带有位置参数  {% url 'namespace:name'  value1 value2 [valuen...] %}
    • 如果带有关键字参数  {% url 'namespace:name' key1=value1 key2=value2 [keyn=valuen....] %}

    使用反向解析优点

          如果在视图,模板中使用硬编码连接,在url配置发生改变时,需要变更的代码会非常多,这样导致我们的代码结构不是很容易维护,使用反向解析可以提高我们代码的扩展性和可维护性。使用了反向解析后,我们可以动态获取路径。

实践:反向解析

在根urls中的two:

path('two/', include(('two.urls','two') namespace='second')),
# namespace 是命名空间,给two.urls指定一个命名空间名称second

在子路由中:

   url('learn/', views.learn, name='learn'),

可以看到,我们给two/learn/添加了一个名字learn

VIEWS函数:

def learn(request):
    return HttpResponse('LOVE LEARN')

想要访问learn我们可以直接访问

反向解析转跳网页

我们也可以在之前的grade_list.html中添加地址,进行转跳
以下是硬编码地址,和反向解析方法:

<hr>
<a href="/two/learn/">硬编码连接</a>
{# 绝对定位 #}
<hr>
<a href="{% url 'second:learn' %}">反向解析</a>
{# 反向解析出地址 #}

我们可以看到结果,两者本质上没有区别,只是反向解析动态生成路径。

好处:变更应用路径时,反向解析自动变更地址
例如,将根路由中的two改为more 

这时反向解析成功改变路径,而硬编码访问失败

带参反向解析转跳网页

为两个url添加name:

url('gettime/(\\d+)/(\\d+)/(\\d+)', views.get_time, name='get_time'),
url('getdate/(?P<year>\\d+)/(?P<month>\\d+)/(?P<day>\\d+)', views.get_date,name='get_date'),

在grade_list中添加:

<hr>
<a href="{% url 'second:get_time' 12 1 12 %}">时间带参数转跳</a>
{# 位置参数 #}
<hr>
<a href="{% url 'second:get_date' year=2018 month=11 day=12 %}"></a>
{# 关键字参数 #}

参数直接加载url后方,而且反向解析在模板中是{% url 'namespace:name' 参数 %}

作业注意

  1. 建立模型时候的外键
  s_grade = models.ForeignKey(Grade, on_delete=models.CASCADE)

2.挖坑,填坑
{{}}在html挖坑
views中context=locals()填坑
3.获取每个班级学生名字的url,views
4.反向解析语法
5.怎么对应班级的学生进行解析?

视图

视图的本质就是一个函数

视图参数:

1.一个HttpRequest的实例
2.通过正则表达式获取过来的参数

位置:

通常在应用下的views.py中定义

错误视图:

  1. 404视图 (页面没找到)
  2. 400视图 (客户操作错误)
  3. 500视图(服务器内部错误)

    自定义错误视图

    在工程的templates文件夹下创建对应的错误文件
    获取请求路径{{ request_path }}
    在文件中定义自己的错误样式
    注意需要在关闭Debug的情况下才可以
    没有关闭Debug的情况下会在界面中直接显示log

    实践:错误页面定制

  • 在模板中重写对应错误状态码页面
  • 关闭Debug
  • 实现原则

    • 就近原则,自己没有定义404界面,用的就是Django默认的404界面

双R

  • Request

    • 内置属性

      • method
      • path
      • GET

        • 类字典结构
        • 一个key允许对应多个值
        • get
        • getlist
      • POST
      • META

        • 各种客户端元信息
        • REMOTE_ADDR 远端访问IP
  • Response

HttpRequest

服务器在接收到Http请求后,会根据报文创建HttpRequest对象
视图中的第一个参数就是HttpRequest对象
Django框架会进行自己的包装,之后传递给视图
属性: 

  • path  请求的完整路径
  • method  请求的方法,常用GET,POST 
  • encoding  编码方式,常用utf-8
  • GET  类似字典的参数,包含了get的所有参数
  • POST  类似字典的参数,包含了post所有参数
  • FILES  类似字典的参数,包含了上传的文件
  • COOKIES  字典,包含了所有COOKIE
  • session  类似字典,表示会话 

方法: is_ajax()  判断是否是ajax(),通常用在移动端和JS中

实践:研究request参数

GET

def get_request(request):
    print(request.path)
    print(request.method)
    print(request.GET)
    print(request.POST)
    return HttpResponse('REQUEST SUCCESS')

打印属性

/two/getrequest/   # 请求路径
GET
<QueryDict: {}>        # 类字典结构
<QueryDict: {}>

字典结构:由key:value组成,key是由哈希表存储,保证不重复,而且查询速度快
而在Django中类字典结构中key允许重复

网页中?代表一种条件。一个接口。后面是种数据,这个数据要传输到这个网页中。网页根据问号后面的条件中的数据来调取相应的网页。
&,这个英文单词是and的意思,一个条件,同时还要符合另一个条件,这个符号是连接两个条件的符号。

我们可以看到类字典的结构还是核字典的结构一样,只不过把值放在了一起
现在我们要获取  GET里面的参数

 hobby = request.GET.get('hobby')
 print(hobby)


得到的是类字典结构中最后一个值

    hobbies = request.GET.getlist('hobby')
    print(hobbies)

我们可以用getlist获取所有的值

POST

建立一个网页student.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>student</title>
</head>
<body>
<form action=""method = 'POST'>
<span>username:</span><input type="text" name="username" placeholder="please input username">
    <button>submit</button>
</form>
</body>
</html>

解释:
标签被用来组合文档中的行内元素。
定义用户可输入文本的单行输入字段。placeholder是提示

标签用于为用户输入创建 HTML 表单。
表单能够包含 input 元素,比如文本字段、复选框、单选框、提交按钮等等。
表单还可以包含 menustextareafieldsetlegendlabel 元素
表单用于向服务器传输数据。
action是用来规定当提交表单时向何处发送表单数据。

起路由:url('createstudent', views.create_student),
views函数:

def create_student(request):
    return render(request, 'student.html')

页面是这样的:


这时候我们提交数据,会发现报错


报错是403客户端出错,但是实际上,这是DJango自带的放跨站攻击的工具,目前没有学习,所以我们将这个BUG先屏蔽掉

我们将这行注释掉即可

接着我们点击sibmit目的是为了提交数据
所以将action中填写地址

<form action="{% url 'second:do_create_student' %}"

接着我们创建url,用来处理submit上来的数据

url('docreatestudent', views.do_create_student, name='do_create_student'),

views:
我们将传递上来的POST请求,进行打印,并且把提交上来的数据响应回去

def do_create_student(request):
    print(request.method)
    username = request.POST.get('username')
    return HttpResponse(username)

报错重点

但到了这个时候我们点击submit的时候,竟然惊奇的发现返回的docreatestudent页面竟然还是createstudent的路由地址:

而且经过测试,最终路由并没有调用我们创建的do_create_student函数,仍然调用的是create_student
很显然,这是因为点击submit的时候,路由匹配时发生了错误
为了证明这个观点,我们将路由改为:

接着我们重新访问:

成功返回结果:

从而证明了在路由匹配时docreatestudent竟然匹配到了createstudent

原因是这样的:
路由匹配是按照从上到下的顺序匹配的,我们第一次访问createstudent时候没有问题,当我们接着访问docreatestudent时候,由于从上到下,发现createstudent完全包含在了docreatestudent中,所以只匹配上了他

解决方案,我们在url前添加^   用来限定开头匹配:

    url('^createstudent/', views.create_student),
    url('^docreatestudent/', views.do_create_student, name='do_create_student'),

同理之前的$是限制匹配结尾

这样就完美解决问题

最后修改:2024 年 03 月 13 日
如果觉得我的文章对你有用,请随意赞赏