Django 具有 “视图” 的概念,负责处理用户的请求并返回响应
django的MTV模式
M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
T 代表模板 (Template):负责如何把页面展示给用户(html)。 模板渲染功能
V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。
除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:
本节,主要介绍URL控制器和视图view.py
处理URL请求过程
- 举例:浏览器地址栏输入地址 -> http://localhost:8000/blog
- Django从配置文件
settings.py
中,根据ROOT_URLCONF
找到 主路由文件;默认情况下,该文件在项目同名目录下的urls,例如djstart/djstart/urls.py
- Django加载主路由文件中的urlpatterns变量[包含很多路由的数组]
- 从上往下,依次匹配urlpatterns中的path,匹配到第一个合适的,中断后续匹配
- 匹配成功-调用对应的视图函数处理请求,返回响应
- 匹配失败-返回404响应
匹配成功
匹配失败
djstart/djstart/urls.py
from django.urls import path
from app_demo import views
urlpatterns = [
# ...
path('blog/',views.blog_list_view,name='blog_list')
]
djstart/app_demo/views.py
from django.http import HttpResponse
def blog_list_view(request):
html='blogs 列表页'
return HttpResponse(html)
URL控制器
路由配置-path()路径匹配
- 导入 -
from django.urls import path
- 语法 -
path(route,views,name=None)
- route:字符串类型,匹配的请求路径
- views:匹配的请求路径对应的视图处理函数的名称
- name:为地址起别名,在模板中地址反向解析时使用
djstart/djstart/urls.py
from django.urls import path
from app_demo import views
urlpatterns = [
# 匹配 http://localhost:8000/blog/,调用app_demo.views中的blogs_view视图函数进行处理
path('blog/',views.blog_list_view,name='blog_list')
]
路由配置-path路径转换器
- 语法
<转换器类型:自定义形参名>
- 作用:若转换器类型匹配到对应类型的数据,则将数据按照关键字传参的方式传递给视图函数
djstart/djstart/urls.py
from django.urls import path
from app_demo import views
urlpatterns = [
# ...
# 匹配 http://localhost:8000/blog/1 ,调用相应视图函数 blog_detail_view(request,blog_id=1)
path('blog/<int:blog_id>',views.blog_detail_view,name='blog_detail')
]
djstart/app_demo/views.py
from django.http import HttpResponse
def blog_detail_view(request,blog_id):
html=f'blog 详情页,blog_id:{blog_id}'
return HttpResponse(html)
- 内置的路径转换器有:str,int,slug,uuid,path
路由匹配-re_path() 正则表达式匹配
导入 -
from django.urls import re_path
语法
re_path(reg,views,name=None)
正则表达式为命名分组模式
(?P<name>pattern)
,其中name
是组名,pattern
是要匹配的模式。作用:
- 在url的匹配过程中可以使用正则表达式进行精确匹配
- 匹配提取参数后,数据按照关键字传参的方式传递给视图函数
djstart/djstart/urls.py
from django.urls import path, re_path
from app_demo import views
urlpatterns = [
# ...
# 匹配/blog/arch/2022-03 ,调用视图entry_archive_view(request,year=2022,month=03)
re_path(r'^blog/arch/(?P<year>\d{4})-(?P<month>\d{1,2})$',views.entry_archive_view)
]
djstart/app_demo/views.py
def entry_archive_view(request, year,month):
html = f'文章归档,年份:{year},月份:{month}'
return HttpResponse(html)
包含其它的URLconfs - include()
在任何时候,你的 urlpatterns
都可以 “include” 其它URLconf 模块。这实际上将一部分URL 放置于其它URL 下面。
在项目开发中,为了保持app的独立性,往往会在各自app中创建一个独立的URLconf
模块,然后在根URLconf
模块中通过include()
加载。
djstart/djstart/urls.py
from django.urls import path, re_path,include
urlpatterns = [
path('blog/',include('app_demo.urls'))
]
djstart/app_demo/urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
path('', views.blog_list_view, name='blog_list'),
path('<int:blog_id>', views.blog_detail_view, name='blog_detail'),
re_path(r'^arch/(?P<year>\d{4})-(?P<month>\d{1,2})$', views.entry_archive_view, name='entry_archive')
]
每当 Django
遇到 include()
,它会将匹配到该点的URLconf
的任何部分切掉,并将剩余的字符串发送到包含的URLconf
进行进一步处理。
传递额外选项给视图函数
djstart/app_demo/urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
#..
# 匹配 /blog/1 , 调用视图函数 blog_detail_view(request,blog_id=1,lang='EN')
path('<int:blog_id>', views.blog_detail_view, {'lang':'EN'},name='blog_detail')
]
djstart/app_demo/views.py
def blog_detail_view(request, blog_id,**kwargs):
html = f'blog 详情页,blog_id:{blog_id},lang:{kwargs.get("lang")}'
return HttpResponse(html)
视图函数
视图函数是用于接收一个浏览器请求(HttpRequest对象)并通过HttpResponse对象返回响应的函数。此函数可以接收浏览器请求并根据业务逻辑返回相应的响应内容给浏览器
语法
def xxx_view(request[,其他参数...]): return HttpResponse(content=响应体,content_type=响应体数据类型,status=状态码)
为了将代码放置在某处,约定将视图放在名为 views.py
的文件里,这个文件放置在项目或应用目录里。
如:djstart/app_demo/views.py
Django中的请求
请求在Django中,实则为视图函数的第一个参数,即HttpRequest对象
Django接收到http协议的请求后,会根据请求数据报文创建HttpRequest对象,HttpRequest对象通过属性描述了请求的所有相关信息
- path_info: URL字符串
- method:字符串,表示HTTP请求方法,常用值:’GET’,’POST’
- GET:QueryDict查询字典,包含get请求方式的所有数据
- POST:QueryDict查询字典,包含post请求方式的所有数据
- FILES:类似于字典的对象,包含所有的上传文件信息
- COOKIES:Python字典,包含所有的cookie,键和值都为字符串
- session:表示当前会话
- body:字符串,请求体的内容(POST或PUT)
- scheme:请求协议(’http’/‘https’)
- get_full_path():请求的完整路径
- META:请求中的元数据(消息头)
- request.META[‘REMOTE_ADDR’]:客户端IP地址
Django中的响应
构造函数格式
HttpResponse(content=响应体,content_type=响应体数据类型,status=状态码)
content_type:返回的数据的MIME类型,默认为
text/html
。浏览器会根据这个属性,来显示数据。常用的
Content-Type
有:text/html
,application/json
,application/xml
djstart/app_demo/views.py
def get_info_view(request):
info={
"path_info":request.path_info,
"method":request.method,
"GET": request.GET,
"COOKIES": request.COOKIES,
"scheme": request.scheme,
"full_path": request.get_full_path(),
"REMOTE_ADDR": request.META.get('REMOTE_ADDR'),
"host": request.get_host(),
"port": request.get_port(),
"headers": str(request.headers),
"User-Agent":request.headers.get('User-Agent')
}
return HttpResponse(content=json.dumps(info),content_type='application/json')
注意使用HTTPResponse
响应json字符串时,我们需要把返回的数据先dumps成json字符串。如果我们直接使用**JsonResponse
方式会更简单**,实质上JsonResponse
也是继承HttpResponse
。
return JsonResponse(info)
注意:为了对 dict
以外的对象进行序列化,你必须将 safe
参数设置为 False
,如
response = JsonResponse([1, 2, 3], safe=False)
- 将URL映射到视图
djstart/app_demo/urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
# ...
path('get_info',views.get_info_view,name='get_info')
]
文件上传
djstart/app_demo/views.py
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from app_demo.models import Blog
from djstart.settings import BASE_DIR
#视图装饰器,该视图只允许POST请求
@require_http_methods(["POST"])
#视图被**免除了中间件csrf所确保的保护** (测试目的)
@csrf_exempt
def blog_edit_view(request):
""" 创建或更新blog """
# 根据blog_id 获取或创建Blog实例
blog, created = Blog.objects.get_or_create(pk=request.POST.get("blog_id"))
# 获取文件对象f
f = request.FILES.get("logo_img")
# 重命名,避免文件名相同相互覆盖
file_name = str(int(time.time())) + "-" + f.name
# 指定文件存储路径
file_path = os.path.join(BASE_DIR, 'media', file_name)
# 将文件写到本地
with open(file_path, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
# 存储到数据库
blog.name = request.POST.get("name")
blog.tagline = request.POST.get("tagline")
blog.logo = file_name # 数据库存储文件保存路径(不带根目录)
blog.save()
return HttpResponse('编辑blog成功!')
djstart/app_demo/urls.py
from django.urls import path, re_path
from . import views
urlpatterns = [
# 编辑blog
path('edit',views.blog_edit_view,name='blog_edit')
]
通过POSTMAN进行测试
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。