FBV与CBV
FBV 基于函数的视图
CBV 基于类的视图
FBV
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index),
]
def index(request, id):
print(id, type(id)) # 222
return HttpResponse('index')
CBV
无论是FBV还是CBV路由层都是路由对应视图函数内存地址
urlpatterns = [
# url(r'^mycls/',views.view)
url(r'^mycls/',views.MyCls.as_view())
]
class MyCls(View):
def get(self,request):
return render(request,'index.html')
def post(self,request):
return HttpResponse('post')
CBV源码解析
urls.py
from django.contrib import admin
from django.urls import path, re_path
from app01 import views
urlpatterns = [
url('^admin/', admin.site.urls),
url('^test', views.MyCls.as_view())
]
views.py
from django.shortcuts import render, HttpResponse
# Create your views here.
class MyCls(View):
def get(self, request):
return render(request, 'test.html')
def post(self, request):
return HttpResponse('post')
test.html
Title
欢迎访问
请求对象
request
当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象。
Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。
请求地址格式
http://127.0.0.1/index
url:协议://IP:port/路径?get请求数据
request
方法
常用方法
request.GET()
一个类似于字典的对象, 包含 HTTP GET 的所有参数
request.POST()
一个类似于字典的对象, 包含 HTTP POST 的所有参数
request.body
一个字符串, 代表请求报文的主体. 在处理非 HTTP形式的报文时非常有用, 例如: 二进制图片, XML, Json等
但是, 如果要处理表单数据的时候, 推荐还是使用
request.POST()
request.get_full_path()
路径加参数,如果输入URL请求是http://127.0.0.1:8000/index/?a=1, 则输出为index/?a=1
request.path()
只输出路径,如果输入URL请求是http://127.0.0.1:8000/index/?a=1, 则输出为index/
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index',views.index)
]
views.py
from django.shortcuts import render,HttpResponse
# Create your views here.
def index(request):
print(request)
print(request.get_full_path()) # /index/?a=1
print(request.path) # /index/
return HttpResponse('ok')
request.method
一个字符串, 表示请求使用的HTTP方法, 例如 "GET", "POST"
request.COOKIES()
一个标准的python字典, 包含所有的cookie. 键和值都是字符串
request.encoding
一个字符串, 表示提交的数据的编码方式 (如果为None, 则表示使用 DEFAULT_CHARSET 的设置, 默认为 'utf-8')
这个属性是可写的, 可以修改它来修改访问表单数据使用的编码
接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding值
如果你知道表单数据的编码不是 DEFAULT_CHARSET, 则使用它
request.META
一个标准的python字典, 包含所有的HTTP 首部. 具体的头部信息取决于客户端和服务器
键值 | 说明 |
---|---|
CONTENT_LENGTH | 请求的正文的长度(是一个字符串) |
CONTENT_TYPE | 请求的正文的MIME类型 |
HTTP_ACCEPT | 响应可接受的Content_Type |
HTTP_ACCEPT_ENCODING | 响应可接收的编码 |
HTTP_ACCEPT_LANGUAGE | 响应可接收的语言 |
HTTP_HOST | 客户端发送HTTP Host头部 |
HTTP_REFERER | Referring 页面 |
HTTP_USER_AGENT | 客户端的user-agent字符串 |
QUERY_STRING | 单个字符串形式的查询字符串(未解析过的形式) |
REMOTE_ADDR | 客户端的IP 地址 |
REMOTE_HOST | 客户端的主机名 |
REMOTE_USER | 服务器认证后的用户 |
REQUEST_METHOD | 一个字符串, 例如'GET' 或 'POST' |
SERVER_NAME | 服务器的主机名 |
SERVER_PORT | 服务器d额端口(是一个字符串) |
从上面的表格可以看到, 除 CONTENT_LENGTH
和 CONTENT_TYPE
之外, 请求中任何 HTTP 首部转换为 META时, 都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_
前缀
所以, 一个叫做 X-Bender
的头部将转换成 META 中的 HTTP_X_BENDER
键
request.FILES
一个类似字典的对象, 包含所有的上传文件信息
FILES中的每个键为 中的name, 值则为对应的数据
注意: FILES 只有在请求的方法为 POST
且提交的 带有
enctype="multipart/form-data"
的情况下才会包含数据, 否则, FILES 将为一个空的类似于字典的对象
request.session()
一个既可读又可写的类似字典的对象, 表示当前的会话. 只有当django启用会话的支持时才可用
request.user
用户认证组件下使用, 一个AUTH_USER_MODEL 类型的对象, 表示当前登录的用户
如果用户当前没有登录, user将设置为
django.contrib.auth.model.AnonymousUser
的一个实例, 可以通过is_authenticated
区分他们
匿名用户
class models.AnonymousUser
django.contrib.auth.model.AnonymousUser
类实现了 django.contrib.auth.model.User接口
字段 | 说明 |
---|---|
id | 永远为None |
get_username() | 永远返回字符串 |
is_staff | 永远为False |
is_superuser | 永远为False |
is_active | 永远为False |
groups | 永远为空 |
user_permissions | 永远为空 |
is_anonymous() | 返回True 而不是False |
is_authenticated() | 返回False而不是True |
set_password() | 引发 NotImplementedError |
check_password() | 引发 NotImplementedError |
save() | 引发 NotImplementedError |
delete() | 引发 NotImplementedError |
from django.utils.deprecation import CallableFalse, CallableTrue
from django.db.models.manager import EmptyManager
class AnonymousUser(object):
id = None
pk = None
username = ''
is_staff = False
is_active = False
is_superuser = False
_groups = EmptyManager(Group)
_user_permissions = EmptyManager(Permission)
def __init__(self):
pass
def __str__(self):
return 'AnonymousUser'
def save(self):
raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")
def delete(self):
raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")
def set_password(self, raw_password):
raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")
def check_password(self, raw_password):
raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")
@property
def groups(self):
return self._groups
@property
def user_permissions(self):
return self._user_permissions
def get_group_permissions(self, obj=None):
return set()
@property
def is_anonymous(self):
return CallableTrue
@property
def is_authenticated(self):
return CallableFalse
def get_username(self):
return self.username
响应对象
response
与由Django自动创建的HttpRequest对象相比,HttpResponse对象是我们的职责范围了。我们写的每个视图都需要实例化,填充和返回一个HttpResponse。
HttpResponse类位于django.http模块中。
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index',views.index)
]
views.py
from django.shortcuts import render,HttpResponse
# Create your views here.
def index(request):
print(request)
print(request.get_full_path()) # /index/?a=1
print(request.path) # /index/
return HttpResponse('ok')
浏览器返回Json格式
希望在浏览器返回一个大字典,我们想到了Httpresponse({'name':'lyysb','password':123344})
在django中,通过JsonResponse这个类来完成
测试1
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'test',views.Test.as_view()),
]
views.py
from django.views import View
from django.shortcuts import HttpResponse, render, redirect
class Test(View):
def get(self, request):
data={'name': 'lyysb', 'password': 123332}
return HttpResponse(data)
def post(self, request):
pass
浏览器输入http://127.0.0.1:8000/test/
只是返回来字典的键值
所以如果要这个字典完整在浏览器上渲染,尝试使用json格式字符串
测试2
修改views.py里的代码
views.py
from django.views import View
from django.shortcuts import HttpResponse
import json
class Test(View):
def get(self, request):
data = {'name': 'lyy傻缺', 'password': 123332}
return HttpResponse(json.dumps(data, ensure_ascii=False))
# ensure_ascii=False参数的作用是使得中文能够在浏览器上渲染
def post(self, request):
pass
浏览器输入http://127.0.0.1:8000/test/
测试3
使用 JsonResponse 返回json字符串
JsonResponse 源码
内部调用的也是Json模块,封装了json.dumps()
如果需要传递参数,通过 json_dumps_params 关键字传参,传参的值以字典的形式传值,因为这样 json_dumps_params的值就打散成key=value的形式为json.dumps()传递
比如说 json.dumps(data, ensure_ascii=False),要使用JsonResponse得到同样的效果
就这么用: JsonResponse(data,json_dumps_params={'ensure_ascii':False})
class JsonResponse(HttpResponse):
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
if safe and not isinstance(data, dict):
raise TypeError(
'In order to allow non-dict objects to be serialized set the '
'safe parameter to False.'
)
if json_dumps_params is None:
json_dumps_params = {}
kwargs.setdefault('content_type', 'application/json')
data = json.dumps(data, cls=encoder, **json_dumps_params)
super(JsonResponse, self).__init__(content=data, **kwargs)
views.py
from django.http import JsonResponse
from django.views import View
class Test(View):
def get(self, request):
data = {'name': 'lyy傻缺', 'password': 123332}
return JsonResponse(data,json_dumps_params={'ensure_ascii':False})
def post(self, request):
pass
urls.py
from django.contrib import admin
from django.urls import path, re_path
from app01 import views
urlpatterns = [
url('^admin/', admin.site.urls),
url('^test', views.MyCls.as_view())
]
文件上传
实现简单的文件上传
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'upload', views.Upload_file.as_view()),
]
views.py
from django.views import View
from django.shortcuts import HttpResponse, render
class Upload_file(View):
def get(self, request):
return render(request, 'test.html')
def post(self, request):
file_obj = request.FILES.get('myfile')
with open(file_obj.name, 'wb') as f:
for line in file_obj.chunks():
f.write(line)
return HttpResponse('ok')
test.html
上传文件