三板斧的使用
JsonReponse序列化类的使用
form表单上传文件
request对象的方法补充
CBV的书写(视图文件中可以写类、函数)
CBV源码剖析
HttpResponse: 字符串
render:渲染html页面
redirect:重定向的
"""在视图文件中写视图函数的时候不能没有返回值了,默认返回的是None,页面上就会报错"""
def render(request, template_name, context=None, content_type=None, status=None, using=None):
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
序列化
json格式的数据
{"a":1}
json有什么用:
跨语言传输
序列化:json.dumps
反序列化:json.loads
from django.http import JsonResponse
def index(request):
# user_dict = {'username':'kevin你好'}
user_dict = [1, 2, 3, 4]
# res=json.dumps(user_dict,ensure_ascii=False)
# return HttpResponse(res)
# 通过看源码学技术
# return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})
return JsonResponse(user_dict,safe=False)
# return render(request,'index.html')
form知识回顾
form表单想要上传文件类型的数据
method参数必须改为post
enctype参数必须指定成form-data类型
路由
form 表单上传 下载文件 url('^ab_file/',views.ab_file),前端
def ab_file(request):
if request.method == 'POST':
# 只能获取到普通的文本数据,无法获取到文件数据
print(request.POST)
return render(request, 'file.html')
通过这种方式,我们只能获取到我们输入的文本数据,而拿不到我们想要的文件数据
def ab_file(request):
if request.method == 'POST':
# 获取文件数据
print(request.FILES) # ]}>
# 提取文件数据 - 文件对象
file_obj = request.FILES.get('file')
# 提取文件名字 file_obj.name
with open(file_obj.name, 'wb') as f:
# 逐行读取文件数据
# 官方推荐 加上 chunks 方法 等价于 一行行获取
for line in file_obj.chunks():
f.write(line)
return render(request, 'file.html')
]}>
request.method
:该方法返回客户端用于发起请求的HTTP方法。例如,可以是'GET'、'POST'、'PUT'、'DELETE'等。您可以使用该方法来确定请求的类型,并相应地执行特定操作request.POST
:该属性是一个类似字典的对象,包含了请求中通过POST方法发送的所有参数。这些参数通常是通过HTML表单发送的。您可以使用参数的名字作为键来访问单个参数,例如request.POST['username']
。request.GET
:类似于request.POST
,该属性包含了请求中通过GET方法发送的所有参数。这些参数通常会附加在URL之后,以问号分隔。您可以使用参数的名字作为键来访问单个参数,例如request.GET['page']
。request.FILES
:该属性是一个类似字典的对象,包含了请求中通过文件上传组件发送的所有文件。当表单中包含文件上传字段时,通过request.FILES
可以访问上传的文件。您可以使用文件的名字作为键来访问单个文件,例如request.FILES['file']
。只能获取到路由地址,无法获取到参数
request.path
:该属性表示请求URL中的路径部分。它包含在域名之后,在任何查询参数之前。例如,如果请求的URL是"http://example.com/foo/bar/",那么request.path
将为"/foo/bar/"。只能获取到路由地址,无法获取到参数
request.path
相比,request.path_info
更加原始和未经解析。它保留了URL路径中的任何编码、特殊字符或斜杠等信息。request.path_info
的值将是 "/foo/bar/"。request.path
来获取丢弃域名后的路径,而使用 request.path_info
来获取原始的、未解析的路径。这在某些情况下非常有用,例如当您需要对URL进行一些自定义操作或路由处理时。即能获取到路由地址又能获取到完整的路由地址后面的参数
request.get_full_path()
:该方法返回请求URL的完整路径,包括路径部分和任何查询参数。当您需要将完整URL作为字符串使用时,这个方法非常有用。例如,如果请求的URL是"http://example.com/foo/bar/?page=2",request.get_full_path()
将返回"/foo/bar/?page=2"def index(request):
return HttpResponse('index')
路由
CBV 路由 - 根据请求方式的不同选择不同的入口动作
url('^login/', views.MyLogin.as_view())
视图
from django.views import View
class MyLogin(View):
def get(self, request, *args, **kwargs):
return HttpResponse("get")
def post(self, request, *args, **kwargs):
return HttpResponse("post")
FBV和CBV各有各的特点,都有应用
FBV(Function-Based Views)与 CBV(Class-Based Views)是 Django 框架中用于处理视图(Views)的两种不同的编程方式。
from django.http import HttpResponse
from django.views import View
class MyView(View):
def get(self, request):
# 处理 GET 请求
return HttpResponse('Hello, GET Request!')
def post(self, request):
# 处理 POST 请求
return HttpResponse('Hello, POST Request!')
url(r'^login/', views.MyLogin.as_view()),
方法/函数名 加 括号 执行优先级最高
可能的原因
查看源码
@classonlymethod
def as_view(cls, **initkwargs):
"""
Main entry point for a request-response process.
"""
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key))
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
# take name and docstring from class
update_wrapper(view, cls, updated=())
# and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view
view 这是一个闭包函数
在启动Django项目时,就会立刻执行as_view方法
url(r'^login/', views.view()),
方法类似FBV方法
总结:CBV和FBV在路由匹配上本质上是一样的,都是路由 对应 函数内存地址
def view(request, *args, **kwargs):
# 参数 cls 就是我们自己写的类
self = cls(**initkwargs)
# 等价于 self = MyLogin(**initkwargs) ---- 产生一个我们自己写的类的对象
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
# 给我们的对象赋值属性
self.request = request
self.args = args
self.kwargs = kwargs
'''
在看python源码的时候,一定要时刻注意面向对象属性方法查找顺序
先从对象自己找
再去产生对象的类里面找
之后再去父类找
总结:在看源码时,如果遇到 self.x 操作时,一定要时刻注意当前这个self到底是谁
'''
return self.dispatch(request, *args, **kwargs)
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
# CBV 的 精髓 !!!
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
# 获取当前请求的小写格式 然后比对当前请求方式是否合法
# 以 get 请求为例
if request.method.lower() in self.http_method_names:
'''
反射:通过字符串来操作对象的属性或方法
'''
# self 是我们自己写的类产生的对象
# handler = getattr(自己写的类产生的对象,'get',当找不到get属性或方法时就会用到第三个参数)
# 因为我们在自己的类里面重写了 get 方法 ,所以这里的 handler 就变成了我们自己写的 get方法
# handler = 我们自己写的类里面的get方法
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
# 自动调用 get 方法
return handler(request, *args, **kwargs)
url(r'^login/', views.MyLogin.as_view()),