Django(二):请求与响应

一、路由说明

1、路由定义的位置

Django的主要路由信息定义在工程同名目录下的urls.py文件中,该文件是Django解析路由的入口。每个子应用为了保持相对独立,可以在各个子应用中定义属于自己的urls.py来保存该应用的路由。然后用主路由文件包含各应用的子路由数据。除了上述方式外,也可将工程的全部路由信息都定义在主路由文件中,子应用不再设置urls.py

import book_test
urlpatterns = [
path('admin/', admin.site.urls),
    # 将子应用的路由添加到总工程中
    # url(r'book_test/',include('book_test.urls'))
    # 将应用中的路由全部注册的	  		  url(r'book_test/sayhello',book_test.views.sayhello)
]

2、路由的执行顺序

Django在接收到一个请求时,从主路由文件中的urlpatterns列表中以由上至下的顺序查找对应路由规则,如果发现规则为include包含,则再进入被包含的urls中的urlpatterns列表由上至下进行查询。值得关注的 由上至下 的顺序,有可能会使上面的路由屏蔽掉下面的路由,带来非预期结果。

urlpatterns = [
    url(r'^say', views.say),
    url(r'^sayhello', views.sayhello),
]

即使访问sayhello/路径,预期应该进入sayhello视图执行,但实际优先查找到了say路由规则也与sayhello/路径匹配,实际进入了say视图执行。
注意:
需要注意路由的执行顺序,以免路由被屏蔽

  1. 路由命名与reverse反解析
    3.1 路由命名
  1. 在使用include函数定义路由时,可以使用namespace参数定义路由的命名空间,这个就像flask蓝图中定义蓝图的第一个参数作用差不多
# flask蓝图
orderblue = Blueprint('order',__name__)
# 命名空间
url(r'book_test/',include('book_test.urls',namespace='books'))

命名空间的作用:避免不同应用中的路由使用了相同的名字发生冲突,使用命名空间区别开。

  1. 在定义普通路由时,可以使用name参数指明路由的名字
url(r'^book_index/', views.book_index,name='index'),
url(r'^sayhello',views.sayhello,name='sayhello'),
url(r'^say',views.say,name='say')

3.2 reverse反解析
使用reverse函数,可以根据路由名称,返回具体的路径, 这个就像flask中的url_for()函数
对于未指明namespace的,reverse(路由name)
对于指明namespace的,reverse(命名空间namespace:路由name)

二、请求与响应

1、请求Request

对于请求我们做的就是获取参数,还记得,请求可以如何传递参数。

  • 提取URL的特定部分,如/weather/beijing/2018,可以在服务器端的路由中用正则表达式截取
  • 查询字符串(query string),形如key1=value1&key2=value2
  • 请求体(body)中发送的数据,比如表单数据、json、xml
  • 在http报文的头(header)中

1.1 URL路径参数

对于url路径参数,我们可以使用正则表达式截取,Django会将提取的参数直接传递到视图的传入参数中。这里提一下,不知还是记得Flask中url路径参数的获取,对于flask我们采用的是转换器进行url匹配
flask

# 请求路径 http://127.0.0.1:5000/89  获取不同新闻的id
@app.route('/<int:news_id>')
def demo(news_id):
print(news_id)
return 'ok'

Django

  • 未命名参数按传递顺序传递,使用正则小括号分组提取
# url(r'^weather/([a-z]+)/(\d{4})/$', views.weather)
url(r'^(\d{4})/([1-9]|1[0-2])',views.mouth)

# 必须按顺序传递参数
def mouth(request,year,mouth):
    print('year:%s'%year)
    print('mouth:%s'%mouth)
    return HttpResponse('年份:%s, 月份: %s' %(year,mouth))

  • 命名参数按名字传参
url(r'^(?P<city>[a-z]+)/(?P<year>\d{4})/$', views.city),

def city(request,city,year):
    print('year:%s' % year)
    print('city:%s' % city)
    return HttpResponse('年份:%s, 城市: %s' %(year,city))

2、HttpRequest对象

属性:

属性 说明
scheme 表示请求方案(http或https 通常)的字符串
body 原始HTTP请求主体作为字节字符串。这对于以不同于传统HTML表单的
方式处理数据非常有用:二进制映像,XML有效负载等
method 表示请求中使用的HTTP方法的字符串。这保证是大写的
path 表示所请求页面的完整路径的字符串 例: “/music/bands/the_beatles/”
GET 类似字典的对象,包含所有给定的HTTP GET参数
POST 一个包含所有POST请求的参数,以及包含表单数据的字典。 如果需要访
问请求中的原始或非表单数据,可以使用HttpRequest.body属
META 包含所有HTTP头部信息的字典。 可用的头部信息取决于客户端和服务器
COOKIES 包含所有Cookie信息的字典。 键和值都为字符串。可以类似字典类型
的方式,在cookie中读写数据,但是注意cookie是不安全的,因此,不要写敏感重要的信息
FILES 一个类似于字典的对象,包含所有的上传文件
encoding 一个字符串,表示提交的数据的编码方式
  • GET属性
def say(request):
    print(request.method)  # 请求的方式
    print(request.scheme) # 请求的方案
    print(request.path) # 请求的路径
    print('-'*50)
    print(request.GET.get('a'))  # 获取请求url 后面带的参数,获取最后一个  /jfj?a=1&b=2&a=3
    print(request.GET.get('b'))  
    print(request.GET.getlist('a'))  # 获取列表
    return HttpResponse('say 页面')

请求url:http://127.0.0.1:8001/book_test/say?a=csx&b=jfjfj&a=12 请求方式get

请求url:http://127.0.0.1:8001/book_test/say?a=csx&b=jfjfj&a=12 请求方式post

  • POST 属性:表单数据的获取
def say(request):
    print(request.method)  # 请求的方式
    print(request.scheme)  # 请求的方案
    print(request.path)  # 请求的路径

    print('-' * 50)
    # 前端发送的表单类型的请求体数据,可以通过request.POST属性获取,返回QueryDict对象
    print(request.POST.get('name'))
    print(request.POST.get('age'))
    print(request.POST.getlist('name'))

    return HttpResponse('say 页面')

运行结果:

  • 非表单数据的获取
def say(request):
    print("-"*100)
    string = request.body
    print(string)
    print(type(string))
    req_data = json.loads(string)
    print(type(req_data))
    print(req_data['a'])
    print(req_data['b'])
    print("-"*100)
    return  HttpResponse('OK')

说明:

  • 对于json数据转换成字典使用 json.loads(参数),对于传入的参数,根据python解释器的不同,传入的参数类型不同。在python3.5 一下传入的参数必须是字符串,因为从request.body 获取的bytes类型,所以我们在转换之前要进行解码。在python3.5之后传入的参数可以是字节或者是字符串,不用解码。

3、HttpResponse对象

与HttpRequest由Django自动创建的对象相比,HttpResponse对象是您的责任。您编写的每个视图都负责实例化,填充和返回 HttpResponse。该HttpResponse课程住在django.http模块中
可以使用django.http.HttpResponse来构造响应对象。

HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)

也可通过HttpResponse对象属性来设置响应体、响应体数据类型、状态码:

  • content:表示返回的内容。
  • status_code:返回的HTTP响应状态码。
  • content_type:指定返回数据的的MIME类型
    响应头可以直接将HttpResponse对象当做字典进行响应头键值对的设置:
response = HttpResponse()
response['NameAuthor'] = 'csx'

实例:

url(r'^demo1$',views.demo1),
    url(r'^demo$',views.demo)
# 直接返回响应
def demo(request):
    return HttpResponse('响应数据',status=400)

# 响应设计
def demo1(request):
    response = HttpResponse()
    response.content = '{"name":"ddd","age":18}'
    response.status_code = 200
    response['Content-Type'] = 'application/json'
    return response

在这里插入图片描述
在这里插入图片描述

HttpResponse子类

Django提供了一系列HttpResponse的子类,可以快速设置状态码

  • HttpResponseRedirect 301
  • HttpResponsePermanentRedirect 302
  • HttpResponseNotModified 304
  • HttpResponseBadRequest 400
  • HttpResponseNotFound 404
  • HttpResponseForbidden 403
  • HttpResponseNotAllowed 405
  • HttpResponseGone 410
  • HttpResponseServerError 500

JsonResponse

若要返回json数据,可以使用JsonResponse来构造响应对象,作用:

  • 帮助我们将数据转换为json字符串
  • 设置响应头Content-Type为 application/json
# 路由
url(r'^view_demo$',views.demo_view)

# 视图函数
def demo_view(request):
    return JsonResponse({'city': 'beijing', 'subject': 'python'})

在这里插入图片描述

重定向

url(r'^book_index/', views.book_index,name='index'),
url(r'^views$',views.view_demo)

def view_demo(request):
    return redirect('index')

4、Cookie

设置cookie

Django的cookie设置和Flask的cookie设置相似

# flask 设置cookie,max_age 过期时间,以秒为单位
@app.route('/login')
def login():
    response = make_response('登录成功')
    response.set_cookie('username', 'csx', max_age=3600)
    response.set_cookie('password', '512279', max_age=3600)
    return response

# 路由
url(r'^login',views.login),

# django
def login(request):
    response = HttpResponse('登录成功')
    response.set_cookie('name','csx',max_age=300)
    response.set_cookie('age',19,max_age=300)
    return response

在这里插入图片描述

获取cookie

# flask
@app.route('/')
def index():
    password = request.cookies.get('password')
    user = flask.request.cookies.get('username')
    return '%s -- %s' % (user, password)
# 路由
url(r'^show',views.show_)

# django 获取cookie
def show_(request):
    name = request.COOKIES.get('name')
    age = request.COOKIES.get('age')
    return HttpResponse('name: %s,age: %s' %(name,age))

在这里插入图片描述

删除cookie

# flask
@app.route('/logout')
def logout():
    response = make_response('success')
    response.delete_cookie('username')
    response.delete_cookie('password')

# 路由
url(r'^show',views.show_)

# django 获取cookie
def logout(request):
    response = HttpResponse('退出登录')
    response.delete_cookie('name')
    response.delete_cookie('age')
    return response

5、Session

session 配置

  • 启用session
    Django项目默认启用Session
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    #默认启用了session
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

session的存储位置

在settings.py文件中,可以设置session数据的存储方式,可以保存在数据库、本地缓存等

  • 默认存储在数据库中:存储在数据库中,如下设置可以写,也可以不写,这是默认存储方式。
SESSION_ENGINE='django.contrib.sessions.backends.db'

如果存储在数据库中,需要在项INSTALLED_APPS中安装Session应用。

  • 本地缓存
    存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快。
SESSION_ENGINE='django.contrib.sessions.backends.cache'
  • 混合存储

优先从本机内存中存取,如果没有则从数据库中存取。

SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
  • 存储在Redis中

在settings.py文件中做如下设置

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

如果redis的ip地址不是本地回环127.0.0.1,而是其他地址,访问Django时,可能出现Redis连接错误,修改redis的配置文件,添加特定ip地址.

Session操作

通过HttpRequest对象的session属性进行会话的读写操作。

  • 以键值对的格式写session。
request.session['键']=
  • 根据键读取值。
request.session.get('键',默认值)
  • 清除所有session,在存储中删除值部分。
request.session.clear()
  • 清除session数据,在存储中删除session的整条数据。
request.session.flush()
  • 删除session中的指定键及值,在存储中只删除某个键及对应的值。
del request.session['键']
  • 设置session的有效期
request.session.set_expiry(value)

①如果value是一个整数,session将在value秒没有活动后过期。
②如果value为0,那么用户session的Cookie将在用户的浏览器关闭时过期。
③如果value为None,那么session有效期将采用系统默认值,默认为两周,可以通过在settings.py中设置SESSION_COOKIE_AGE来设置全局默认值。

猜你喜欢

转载自blog.csdn.net/qq_38803950/article/details/86562354