Django 请求与响应

请求与响应

一、请求与响应流程

1. 发起请求
		用户在前端页面发起请求(三种请求方式:a标签、form表单、location.href-在地址栏中输入URL)

2. 接收请求
		请求从前端页面发送给了服务器(Django程序),请求最终达到了视图函数。而在发请求的过程中,往往会传递一些参数给服务器(从前端传参数给后端) Mr_lee 18
		(1) 命名路径/正则路径/正则命名路径
			a. 前端URL: http://127.0.0.1:8000/hello/Mr_lee/18/
			b. 后端path: path('hello/<name>/<age>/',views.hello),
			c. 视图函数: def hello(request,name,age): print(name,age)
			
		(2) request方式
			a. 前端URL: http://127.0.0.1:8000/hello/?name=Mr_lee&age=18
			b. 后端path: path('hello/',views.hello),
			c. 视图函数: def hello(request): 
							name = request.GET.get('name')
							age = request.GET.get('age') 

3. 处理请求
		一般是获取到前端的参数后,对数据库进行增删改查等操作 - 业务逻辑

4. 返回响应
		在视图函数处理完请求后,然后返回响应给前端页面

# 发起请求->接收请求->处理请求->返回响应

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6TUBrjaS-1644897469122)(Django05_请求与响应.assets/image-20210222211636269.png)]

二、HttpRequest对象

1. 当用户向服务器发起一个请求,django会自动创建一个HttpRequest对象,并将请求的参数包装在该对象的GET或POST属性中,然后将该对象作为实参传递给视图函数的形参request.

2. HTTP请求:
	HTTP:超文本传输协议,前端页面(浏览器) 和 后端程序(服务器)之间通信的一种规范
	从前端页面发起的一个请求就称之为HTTP请求

3. Django的执行过程:
	(1)创建对象 - HttpRequest对象
			req = HttpRequest()
			req.GET['name'] = 'Mr_lee' # 给字典加了一个键值对
			req.GET['age'] = 18 # 又加了一个键值对
			
	(2)调用hello函数,并传递实参给形参
    		hello(req)   -> def hello(request): request.GET.get('name')
    		
  • HttpRequest对象常用的属性
1. GET 和 POST  - 类似于字典 包含着GET请求和POST请求时传递的参数
		def hello(request):
			request.GET.get('xx') 或
			request.POST.get('xx')
2. method 属性 - 表示请求的方法
   		 def hello(request):
   		 	if request.method == 'GET':
   				reuest.GET.get('xx')
   			elif request.method == 'POST':
            	request.POST.get('xx')
3. COOKIES - 后续讲解       	

三、HttpResponse对象

1、Response对象简介
1. HttpResponse对象是指响应对象,它是由程序员`自己创建`的,每一个视图函数都必须返回一个HttpResponse对象

2. request对象和response对象起到了客户端浏览器和服务器之间的`信息传递`的作用。request对象用于接收前端浏览器提交的数据,而response对象的功能则是将服务器的数据发送给前端。
2、创建响应对象
1. 方式一: 不使用模板文件,直接返回
	def hello(request):
		return HttpResponse('')
		
2. 方式二:调用模板		
	def login(request):
		return render(request,'login.html')  # render的本质还是HttpResponse

四、View的跳转

1、跳转的情景
- 基本的跳转: 从一个view跳转到一个template
		def index(request):
			return render(request,'index.html')
		
	说明:用户在浏览器地址栏中输入相应的URL,回车时,就是一个空白页面跳转到index.html	
    

- 更为复杂的跳转:从一个view跳转到另一个view,然后再跳转到template
		def index1(request):
			return render(request,'index.html')
			
		def index2(request):
        	return redirect('/xxx/index1/')
     
        说明:用户输入index2的URL,调用index2的视图函数,该视图函数并没有直接渲染页面,而是重定向到index1中
        # 什么情况下: 用户打开注册页面,注册完成后,自动跳转到登录页面	
2、跳转方式
1. 转发: 基本的跳转,浏览器中的URL不变
		转发是一个请求内的跳转,用于view到template之间的跳转  render()
		
2. 重定向:从view跳转到view,浏览器中的URL会发生改变
		重定向发生的不同请求之间,用于view与view之间的跳转  redirect(to=要跳转到的页面的URL)

五、Cookie

1、Cookie简介
1. Cookie实际上是一种数据存储技术,由服务器生成(执行),并保存在浏览器中的一种技术。

2. 由于HTTP协议是一种无状态的协议,客户端浏览器和服务器端数据交换完毕后,再次交换数据需要建议新的连接。 

比如:登录邮箱,我们点击了“7天自动登录”或“记住我” 
2、Cookie的应用场景
- 保存登录信息-用户名和密码- 保存用户的搜索记录
3、Cookie的使用过程
3.1 存储Cookie
存储Cookie需要由Response对象来完成,当通过Response对象设置好Cookie后,再响应到客户端,Cookie就会随之存储到浏览器中。
  • 不使用模板

    def index(request):    resp = HttpResponse('存储cookie')    resp.set_cookie('username','Mr_lee')    resp.set_cookie('password','123456')	return resp
    
  • 使用模板

    def index(request):    resp = render(request,'index.html')    resp.set_cookie('username','Mr_lee')    resp.set_cookie('password','123456')	return resp
    
3.2 读取Cookie
# 读取cookie需要由request对象完成# 当向服务器发起一个请求时,request对象会携带浏览器中的所有的cookie到达到服务器def read(request):    # print(request.COOKIES)    username = request.COOKIES.get('username')    password = request.COOKIES.get('password')    print(username,password)    return HttpResponse('读取cookie')
3.3 Cookie的生命周期
默认的生命周期:	一次会话,浏览器打开到关闭,关闭浏览器后,cookie会失效修改生命周期:	resp.set_cookie('username','Mr_lee',max_age=值(秒))	    (1) max_age=0 删除cookie    (2) max_age=-1 相当于不设置 会话cookie    (3) max_age=100 存活100秒 100秒后失效
3.4 Cookie的中文问题
# cookie不能直接存储中文# 存储:username = '吕小布'.encode('utf-8').decode('latin-1')resp.set_cookie('username',username,max_age=3600*24*7)# 读取:username = request.COOKIES.get('username')username = username.encode('latin-1').decode('utf-8')print(username)
4、案例:记住我
登录页面, 记住我(7天自动登录)选项,当用户勾选了“记住我”,点击登录,将用户名和密码保存在cookie中,下次用户就不需要再进行登录操作了
# 在登录逻辑中,登录成功的情况下,并且勾选了记住我def login_logic(request):    username = request.POST.get('username')    password = request.POST.get('password')    rem = request.POST.get('remember')    result = User.objects.filter(username=username,password=password)    if result:        resp = redirect('/account/home/')        if rem:            # 存储cookie            resp.set_cookie('username',username,max_age=3600*24*7)            resp.set_cookie('password',password,max_age=3600*24*7)        return resp    return HttpResponse('登录失败')# 下次输入登录页面的URL,执行login视图函数,在login函数中,需要检查并验证cookie# 如果cookie验证成功,直接跳转到主页面,否则 依然渲染登录页面def login(request):    username = request.COOKIES.get("username")    password = request.COOKIES.get("password")    # 一定要和数据库进行比对 (不能只判断username和password是否存在)    result = User.objects.filter(username=username,password=password)    if result:        return redirect('/account/home/')    return render(request,'alogin.html')

六、Session

1、Session简介
1. Cookie将少量数据存储在客户端浏览器本地,而Session是一种将会议状态存储在服务器端的技术(数据库中)。2. Session(翻译:会话)一般指的是浏览器页面从打开到关闭的这段时间。Session的存储技术一般用于多个请求之间,共享数据状态。3. 常用情景:	登录成功后,记录下登录状态(Session),周期为一个会话周期,然后就可以去访问‘我的订单、我的余额’等页面
2、Session的使用
2.1 启用session
1. INSTALLED_APPS中需要有sessions	INSTALLED_APPS = [...,  'django.contrib.sessions', ...]	2. MIDDLEWARE = [..,  'django.contrib.sessions.middleware.SessionMiddleware',...]3. 需要执行迁移的指令  python manage.py migrate 生成django_session表 - 存储session数据
2.2 Session生命周期
- 默认生命同期:	 默认的生命周期为2周	 - 修改:(一般session都会修改为一次会话)	 在settings.py文件中添加如下:	 SESSION_EXPIRE_AT_BROWSER_CLOSE=True
2.3 Session的存储
def save(request):    request.session['username']='Tom'    request.session['password']='123456'    return HttpResponse("存储session")
2.4 Session的读取
def read(request):    username = request.session.get('username')    password = request.session.get('password')    print(username,password)    return HttpResponse("读取session")

注意:

  • 存储session和读取session都由request对象来完成

  • session没有中文问题

  • session也没有长度限制 (存储在数据库中)

  • session存储在服务器的数据库中相比cookie更安全

2.5 清除session
比如:点击了“退出”,此时需要清除登录状态(session)1. request.session.flush()		清除session所有数据,清除表中的数据及cookie中的sessionid2. request.session.clear()		清除了session_date中的键值对,但session表中的记录还在3. del request.session[key]	 	删除指定的session中的某一个键值
3、Session的实现原理
1. 浏览器第一次请求session对象时,服务器会创建一个session并生成一个sessionid,存储数据库中(session_key),同时会将sessionid返回给浏览器,存储浏览器的cookie中。2. 在浏览器不关闭的情况下(会话周期),之后的每次请求都会携带cookie中的sessionid到达服务器。服务器接收到请求后就可以通过request对象获取到cookie中的sessionid,然后再通过该id从数据库中找到对应的session_data给请求者使用。# 不同的用户,打开的是自己电脑上的浏览器,去存储sesion时,会给每一个用户生成一个sessionid,并将id返回给用户的浏览器的cookie中# 用户下一次再去请求session数据时,请求会携带自己的浏览器中的sessionid到达服务器,服务器根据sessionid找到对应行的数据
4、session和cookie区别
1. Cookie是将数据存储在浏览器本地,Session是存储在服务器的数据库中2. 需要在一小段时间后依然可以保持的数据,使用Cookie来存储,如“记住我”。保证在一段时间,可以自动登录。 `Cookie一般用于多个会话间的状态保持`   需要在多个请求间多次共享数据,保持状态,使用Session。`Session是一个会话间的状态保持`   3. 每个网站在一个浏览器中的cookie数据上限上4K,而session无限制4. Cookie存在浏览器本地,隐私性不好,安全性较低。而session存储在服务器更安全。5. Cookie生命周期默认为一次会话,但一般会修改为一个固定周期,而Session默认为2周,但一般修改为一次会话。
5、案例:强制登录
当当网:	打开当当网,未登录,直接点击“我的订单”,无法进入,此时会强制跳转到登录页面,登录成功后,再点击“我的订单”就可以进入了。	当访问我的订单时,它会检测登录状态,当登录成功后,需要记录登录状态(Session)
def login(request):    username = request.COOKIES.get("username")    password = request.COOKIES.get("password")    # 一定要和数据库进行比对 (不能只判断username和password是否存在)    result = User.objects.filter(username=username,password=password)    if result:		# 自动登录时,也需要存储登录状态            request.session['is_login'] = True        return redirect('/account/home/')    return render(request,'alogin.html')def login_logic(request):    username = request.POST.get('username')    password = request.POST.get('password')    rem = request.POST.get('remember')    result = User.objects.filter(username=username,password=password)    if result:		# 手动登录成功时,记录登录状态        request.session['is_login'] = True        resp = redirect('/account/home/')        if rem:            # 存储cookie            resp.set_cookie('username',username,max_age=3600*24*7)            resp.set_cookie('password',password,max_age=3600*24*7)        return resp    return HttpResponse('登录失败')def home(request):  # 在需要有登录状态的请求中(视图函数中)  # 从session中获取登录状态    is_login = request.session.get('is_login')    if is_login:        return render(request,'home.html')    return redirect('/account/login/')

七、全局错误视图设置

# 在项目上线运行时,需要配置错误页面给用户请求与响应:	如果请求发送成功,且服务器成功返回了响应,此时在前端页面中可以得到一个成功的状态码200 HTTP请求的状态码:	200 - 请求成功	301/302 - 重定向	403     - 禁止提交 CSRFToken	404     - 资源未找到Not Found	500     - 服务器错误Internet Server Error
如果发生了404或500等错误,不能让用户看到错误日志	(黄色错误页面)# 解决方案:	(1)在settings.py文件中,将Debug=True改为False		DEBUG = False  # 开发阶段需要设置为True 调试模式  项目上线后,不能让用户看到错误日志 因此需要将调试模式改为False	 	 (2) ALLOWED_HOSTS = ['*']		 ---------------------------------------------------------------------------------# 配置错误页面:	在templates目录下,新建404.html 500.html即可,当出现访问错误时,django会自动根据错误的状态码找到对应的html文件,展示给用户

八、基于View的事务控制

# 事务控制的目的: 保证数据库中数据的完整性 # 事务加在哪些操作中:增删改  

在Django中进行事务控制的两种方式:

  • 方式一:给所有的请求(视图函数)都包裹在一个事务中,在视图函数开始时begin,函数结束时commit
在settings.py文件中的databases中添加:DATABASES = {    'default': {        'ENGINE': 'django.db.backends.mysql',        'NAME': 'modeldb',        'HOST': '127.0.0.1',        'PORT': 3306,        'USER': 'root',        'PASSWORD':'123456',        'ATOMIC_REQUESTS':True    }}# 弊端: 当函数中有try块时,错误会先被try块捕获并处理,此时事务就检测不到错误,无法回滚数据def register_logic(request):    try:        username = request.POST.get('username')        password = request.POST.get('password')        user = User.objects.create(username=username, password=password)        if user:            10 / 0            return redirect('/account/login/')  # 重定向:从一个页面定位到另一个页面    except:        return HttpResponse('注册失败')
  • 方式二:在视图函数中通过上下文管理器with transaction.atomic():来进行事务控制
# 在databases中将   'ATOMIC_REQUESTS':True 去掉 def register_logic(request):    try:        username = request.POST.get('username')        password = request.POST.get('password')        with transaction.atomic():            user = User.objects.create(username=username, password=password)            if user:                10 / 0                return redirect('/account/login/')  # 重定向:从一个页面定位到另一个页面    except:        return HttpResponse('注册失败')    # 第二种方式进行事务控制,更加地灵活,当发生错误时,事务先检测到错误,进行回滚操作,但事务本身不能处理错误,所以错误最终还是会被try块捕获并处理    

九、反向解析

1、简介
在django项目中,经常需要获取某个URL,比如:
# 前端页面中:	(1)<a href='url'> 跳转 </a>	
(2)location.href = 'url'	
(3)<form action='url'> </form>	
# 后端程序中:	 
(1)重定向  redirect('要跳转到的页面的URL')	 上述中的URL路径的写法都称之为`硬编码`,一旦urls.py
文件中的path访问发生了修改 `path('home/',viwes.home)` -> `path('homepage/',viwes.home)` ,
此时所有用到该访问路径的地方都需要修改。显然这种做法是比较stupid	 
2、反向解析
此时我们需要一种安全、可靠的、自适应的机制,当urls.py文件中的path访问路径发生改变时,无需要在项目
的源代码到处去搜索修改失效的硬编码的URL路径。
为了解决上述的问题,django提供了解决方案:	只需要在path访问路径中,添加一个name参数,
并赋一个好记的‘字符串’即可	urlpatterns = [ path('home/',views.home,name='home'),	]
3、如何使用
# 1. 在视图函数中	def login(request):		
						xxx		
						return redirect('home')
 # 这里直接写name参数的值即可 反向解析-django会根据name自动到解析到name对应的url访问路径
 # 2. 在模板文件html中	<form action="{% url 'login_logic' %}" method="post"> xx </form>
4、命名空间
如果多个app中出现了同名的name参数,此时有可能引发混乱。一个项目会出现多个相同的name,django在进行反向解析时,
就不知道解析成哪个app中的url解决:	给每个app的urls.py文件中,
添加 app_name='app的名字'	使用时:  		前端页面:    {% url '空间的名字:name'%}		视图函数:   redirect('空间名:name')
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值