当用户请求一个页面时,Django 把请求的数据包装成一个 HttpRequest 对象,然后 Django 加载对应的view 函数,把这个 HttpRequest 对象作为第一个参数传给 view 函数。任何 view 函数都应该返回一个 HttpResponse 对象。
[图片上传失败...(image-1141ba-1556782871431)]
HttpRequest 对象表示来自客户端的一个单独的 HTTP 请求。HttpRequest 对象是 Django 自动创建的,且会传递给视图函数作为第一个参数。
HttpRequest常用的属性:
method -- 返回一个字符串,表示请求使用的HTTP方法
if request.method == "POST":
...
elif request.method == "GET":
...
GET、POST -- 一个类似于字典的对象,包含GET、POST的所有参数
def formRequest(request):
if request.method == 'GET':
a = request.GET.get('uname') # 通过GET的get方法得到uname对应的值
b = request.GET['upwd'] # 通过字典形式获取
return HttpResponse("表单传参" + a + b)
else:
a = request.POST.get('uname')
b = request.POST.get('upwd')
return HttpResponse("表单传参" + a + b)
COOKIES -- 包含所有cookies的标准Python字典对象。Keys和values都是字符串。
Request 和 Response 对象起到了服务器与客户机之间的信息传递作用。Request 对象用于接收客户端浏览器提交的数据,而 Response 对象的功能则是将服务器端的数据发送到客户端浏览器。
对于 HttpRequest 对象来说,是由 Django 自动创建, 但是,HttpResponse 对象就必须我们自己创建。每个 View 方法必须返回一个 HttpResponse 对象。
from django.http import HttpResponse
def index(request):
return HttpResponse('HelloWorld') #构造对象调用init方法
loader.get_template
from django.http import HttpRespse, loader
def index(request):
template = loader.get_template('index.html')
return HttpResponse(template.render(request=request))
使用render()函数
from django.http import HttpResponse,render
def index(request):
return render(request, "index.html") # 建议使用更简易的这种写法
一个View接到请求,处理完业务逻辑后,最后都需要给出响应。而响应内容的生成一般不由View负责,Template是专业的响应内容生成者,则此时需要View和Template之间做衔接、跳转。
from django.http import HttpResponse,render
def index(request):
return render(request, "index.html") # 跳转到模板中,并将模板内容显示在客户端
def regist_logic(request):
try:
name = request.POST.get("userName")
password = request.POST.get("userPwd")
user = User.objects.create(name=name, password=password)
#return HttpResponseRedirect("/redirect/login/") # 从一个页面,重定向到另一个页面
return redirect("/redirect/login/") # 从一个页面,重定向到另一个页面
except:
return HttpResponse("注册失败")
跳转方式:
转发:基本的跳转,浏览器中的URL不变
转发发生在一个请求内的跳转,用于View到Template间的跳转, render(request, "test.html")
即为在一个请求内由View转发跳转到Template
重定向:从view跳转到view,浏览器中的URL发生改变
重定向发生在不同请求之间,用于View之间的跳转 redirect("另外的View的请求路径:/a/b/c/")
Cookie实际上是一种数据存储技术,由服务器生成,并保存在客户端(浏览器)的一种技术。
HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。
比如你登录邮箱,我们经常会在此时设置30天内记住我,或者自动登录选项。
存储cookie是由Response对象来完成,当通过Response对象设置好cookie后,再响应到客户端,cookie会随之存入到客户端。
有服务器生成,通过Responsee对象 传递给服务器并保存起来
不使用模板
def index(request):
res = HttpResponse("测试cookie")
res.set_cookie("uname","Mr_lee")
return res;
使用模板
def index2(request):
res = render(request,'cookie_demo/index.html')
res.set_cookie("age",18)
return res;
设置过期时长:默认是浏览器关闭后失效
res.set_cookie("age",18,max_age=100)
请求服务器时,当再次访问项目时,request会携带本项目的所有cookie到达服务器,通过request对象可以读取cookie中的数据。
def index(request):
#返回所有cookie
print(request.COOKIES) #{'uname': 'Mr_lee', 'age': 18}
print(type(request.COOKIES)) #dict
request.COOKIES['age']
request.COOKIES.get("age")
[图片上传失败...(image-dac94a-1556782871431)]
#存中文cookie值
uname = "米斯特利".encode('utf-8').decode('latin-1')
#取中文cookie值
str = request.COOKIES.get("name").encode('latin-1').decode('utf-8')
print(str)
测试实例:记住我
Cookie是将少量信息存储于客户端(本地浏览器)的,而Session技术是一种将会话状态保存在服务器端的技术。
Session一般是指浏览器这个页面打开到关闭的这段时间 ,Session用作多个请求之间,共享数据。
常见情景:登录请求之后,之后的请求中都可以显示用户名。
INSTALLED_APPS = [
...
'django.contrib.sessions',
...
]
MIDDLEWARE = [
...
'django.contrib.sessions.middleware.SessionMiddleware',
...
]
python manage.py migrate
Session默认存活两周,可以修改为一个会话周期,在settings.py中:
SESSION_EXPIRE_AT_BROWSER_CLOSE=True
#注意,django默认的session存储位置为数据库的django_session表,需要通过python manage.py migrate生成
def xxx(req):
req.session['username']="Mr_lee"
req.session['login']=1
...
def xxx(req):
print(req.session['username'])
print(req.session.get('login')
...
注意session没有中文问题,没有长度限制,相比存在客户端的cookie更安全
req.session.flush() # 清除数据,置空cookie中的sessionid,清除数据表中的记录
req.session.clear() #清除数据
del req.session['username'] #清除一个key的数据
浏览器第一次请求session对象时,服务器会创建一个session并且生成一个sessionId,存储在数据库中,并将sessionid返回给浏览器,这个sessionId会被保存在浏览器的会话cookie中
在浏览器不关闭的情况下,之后的每次请求请求头都会携带这个sessionId到服务器。服务器接收到请求后就得到该请求的sessionID,服务器找到该id对应的session返还给请求者使用。
测试实例:强制登录
http请求的状态码 200=成功 404=资源未找到 500=服务器错误 400=bad request...
可以为常见的错误定制错误页面
关闭调试模式,设置allow_host
在templates下新建:404.html 500.html 400.html,在出现对应错误时,会自动跳转错误页面
Django手动配置事务的方式主要有二种:
第一种是将每个请求都包裹在一个事务中。
'ATOMIC_REQUESTS': True
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'jangodb',
'USER':'root',
'PASSWORD':'123456',
'HOST':'localhost',
'PORT':3306,
'ATOMIC_REQUESTS':True
}
}
# 运行View前已经开启事务
def test(request):
Person(name="tx_name22", age=18).save()
Person(name="tx_name33", age=18).save()
a=10/0 #出现异常,事务自动回滚
return HttpResponse("abc")
注意:
如下情况,事务依然提交
基于View的事务控制,不能处理异常,否则事务行为被破坏
如果在view中try了异常,django就认为整个View没有异常,则事务正常提交
def test(request):
try:
Person(name="tx_name22", age=18).save()
Person(name="tx_name33", age=18).save()
a=10/0
except Exception:
print("error")
raise
return render(request,"error1.html")
return render(request,"success.html")
0`def testt(request):
try:
with transaction.atomic():#开始一个事务 环境,with结束时,如果没有异常,事务提交;否则回滚
Person(name="tx_name22", age=18).save()
Person(name="tx_name33", age=18).save()
a=10/0
return render(request,"success.html")
except:
print("error") #此时的异常已经回滚
return render(request,"error.html") #还可以为错误提供专用的视图页面
在实际的Django项目中,经常需要获取某条URL,为生成的内容配置URL链接。
比如提交表单时,跳转到某个url,点击a标签链接到某个url,此时在表单和a标签中一定不能硬编码URL 。
注册
path('loginlogic/',views.login_logic),
path('regist/', views.regist_view),
一旦URLconf中的的路由配置发生修改,则需要在所有使用到该url的地方去作修改。显然这种做法是比较stupid。
此时我们需要一种安全、可靠、自适应的机制,当修改URLconf中的代码后,无需在项目源码中大范围搜索、替换失效的硬编码URL。
为了解决这个问题,Django提供了一种解决方案,只需在URL中提供一个name参数,并赋值一个你自定义的、好记的、直观的字符串。
通过这个name参数,可以反向解析URL、反向URL匹配、反向URL查询或者简单的URL反查。
urlpatterns = [
path('index/',views.index,name='index'),
]
在需要解析URL的地方,对于不同层级,Django提供了不同的工具用于URL反查:
在模板语言中:使用url
模板标签。(也就是写前端网页时)
反向解析
在Python代码中:使用reverse()
函数。(也就是写视图函数等情况时)
def index(request):
url = reverse('index') # 可用作重定向的url等
print(url)
return render(request, 'index.html')
# redirect("index") -- path('index/',views.index,name='index'),
URL名称name使用的字符串可以包含任何你喜欢的字符,但是过度的放纵有可能带来重名的冲突,比如两个不同的app,在各自的urlconf中为某一条url取了相同的name,这就会带来麻烦。为了解决这个问题,又引出了下面的命名空间。
URL命名空间可以保证反查到唯一的URL,即使不同的app使用相同的URL名称。
实现命名空间的做法很简单,在urlconf文件中添加app_name = 'xxx'
即可。
#-- urls.py -- #
app_name='reverse_app' # 定义app_name
urlpatterns = [
path('index/',views.index,name='index'),
]
使用时在name前加app_name:url_name即可:
def index(request):
url = reverse('reverse_app:index') # 使用方式 app_name:url_name
print(url)
return render(request, 'index.html')
反向解析
作业:
技术点熟悉,练习
登录 注册
注册后自动跳转登录页面
登录后记住我 一周 -- cookie
强制登录 -- session