web 服务器
web服务器也叫”http web 服务器“,专门用于提供网页浏览器的一类软件。 常见的web 服务器软件:nginx,uwsgi,gunicorn,apache,tomcat,iis 等 wsgi:Python 基于 CGI 标准实现的 HTTP 通讯技术 asgi:async+wsgi,支持异步的 wsgi软件
路由
路由是把客户端请求的url地址和用户请求的应用程序[这里意指django里面的视图]进行一对一绑定映射的一种关系.
视图
视图函数FBV
function baseview 视图函数必须编写扎起子应用的 views.py 文件中
from django.http.response import HttpResponse
def 函数视图名称(request):
# 代码
return HttpResponse("返回内容")
视图函数的名称,同一模块下不能重复,命名规则同变量命名规则
视图类
class baseview
请求
限制 HTTP 请求
web项目运行在http协议下,默认肯定也支持用户通过不同的http请求发送数据来。 常见的 HTTP 请求
POST: 添加/上传
GET : 获取/下载
PUT/PATCH : 修改,其中PUT表示修改整体数据,而PATCH表示修改部分数据
DELETE:删除,废弃
Django 支持让客户端只能通过指定的 HTTP 请求来访问到项目用的视图
home/views.py,代码:
# 让用户发送POST才能访问的页面
from django.views.decorators.http import require_http_methods
@require_http_methods(["POST"])
def login(request):
return HttpResponse("登录成功!")
路由绑定
demo/urls.py,代码:
from django.contrib import admin
from django.urls import path
from home.views import index,index2
urlpatterns = [
path('admin/', admin.site.urls),
path("index", index),
path("login", login),
]
浏览器中由于默认用 get 方法访问,而我们设置的只支持 post 方法所以会报错。 正常情况下,我们用户发送POST一般肯定通过使用html网页中的表单/js里面提供http请求的ajax才可以做到发送POST或GET或PUT/PATCH,而现在我们没有表单,因此我们可以安装一个postman的软件,这个软件类似浏览器但是功能比浏览器要强大,专门提供给开发人员免费使用的。
采用 postman 方式进行访问,但由于一种安全访问机制,我们需要将 demo/settings.py 文件进行设置
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', # ctrl+/
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
设置路由绑定视图
为了有效管理路由设置,我们可以将路由放回到子应用目录下
- 在子应用 home 下创建路由文件夹,一般命名为
urls.py - 将子应用home 下的视图绑定到该文件下
"""子应用路由"""
from django.urls import path
# 路由使用过程中,django提供了2个函数给我们把url和视图进行绑定映射,
# django.urls.path
# django.urls.re_path
from . import views
urlpatterns = [
path('home', views.index),
path('list', views.book_list),
# path("路由uri地址", 视图代码)
path('login', views.login),
]
# 最终用户访问的视图url地址:
# url = 总路由的公共url地址 + 子应用路由的uri地址
- 在总路由中 demo/urls.py 问津中,通过
include加载路由文件到 Django 项目中 demo/urls.py
"""总路由"""
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
# path("公共url地址", include("子应用目录名.路由模块"))
path("book/", include("home.urls")),
]
当django项目中的路由分成总路由和子应用路由以后, 那么用户访问视图,则访问地址的规则:
http://127.0.0.1:8000/路由前缀+子应用路由的url地址
例如: 总路由中注册子应用路由时, 路由前缀为 "home" 则用户访问时 正确的地址就是:
http://127.0.0.1:8000/homeindex当然,如果路由前缀是 "home/", 而子路由的url地址为 "index"
则用户访问时 正确的地址就是:http://127.0.0.1:8000/home/index
视图接收 HTTP 请求
在http请求和响应过程中, 用户往往会在请求过程中发送请求信息给服务端.
-
查询字符串[Query String] 所谓的查询字符串就是url地址上面?号后面的数据,例如: http://127.0.0.1:8000/index?name=xiaoming&pwd=123456 上面name=xiaoming&pwd=123456就是查询字符串 可以通过 request.GET 来获取,注意: GET不是http请求,也就是说,只要地址上有查询字符串,都可以获取
-
请求体数据
-
请求头报文信息
-
上传文件
获取查询字符串的参数
home/views.py
"""查询字符串[Query String]"""
def index3(request):
# print(request.method)
"""
访问地址:
http://127.0.0.1:8000/home/index3
打印效果:
<QueryDict: {}>
分析: 通过request得到的客户端请求数据,基本都是会保存成QueryDict类字典给视图的,上面是空字典
QueryDict的声明位置: from django.http import QueryDict
QueryDict的父类继承的就是dict字典,所以字典提供的方法或者操作, QueryDict都有
"""
"""
访问地址:
http://127.0.0.1:8000/home/index3?name=xiapming&mobile=13312345678
打印效果:
<QueryDict: {'name': ['xiapming'], 'mobile': ['13312345678']}>
分析:
这次就获取到了name和mobile参数以及参数的值
注意:
因为客户端传递过来的参数有可能多个值的情况,所以查询字符串返回的数据值都是列表格式
"""
"""
访问地址:
http://127.0.0.1:8000/home/index3?name=xiapming&mobile=13312345678&lve=swimming&lve=shopping&lve=game
打印效果:
<QueryDict: {'name': ['xiapming'], 'mobile': ['13312345678'], 'lve': ['swimming', 'shopping', 'game']}>
分析:
因为lve有多个值的存在, 所以值就是列表中有3个成员
"""
"""获取QueryDict对象中的参数值"""
# 获取参数的一个值,或者第一个值
# 因为QueryDict是一个伪字典对象,所以可以通过get或者中括号获取到数据
# print(request.GET.get("name"))
# print(request.GET["name"])
# 获取参数的所有值
print(request.GET.getlist("lve")) # ['swimming', 'shopping', 'game']
print(request.GET['lve']) # game,后面的值覆盖了前面的值
return HttpResponse("ok")
home/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path("index", views.index ),
path("index2", views.index2 ),
path("index3", views.index3 ),
]
获取请求体数据
def index4(request):
"""获取请求体数据,返回数据结果是QueryDict"""
print(request.POST)
"""
打印效果:
<QueryDict: {'name': ['root'], 'password': ['123456']}>
"""
print(request.body) # b'{\n\t"title": "\xe5\x9c\xa3\xe8\xaf\x9e\xe6\xa0\x91",\n "username":"\xe5\x9c\xa3\xe8\xaf\x9e\xe8\x80\x81\xe5\xa4\xb4",\n "age": 1200\n}'
"""
打印效果:
b'{\n\t"title": "\xe5\x9c\xa3\xe8\xaf\x9e\xe6\xa0\x91",\n "username":"\xe5\x9c\xa3\xe8\xaf\x9e\xe8\x80\x81\xe5\xa4\xb4",\n "age": 1200\n}'
"""
import json
ret = json.loads(request.body)
print(ret) # {'title': '圣诞树', 'username': '圣诞老头', 'age': 1200}
return HttpResponse("ok")
home/urls.py代码:
from django.urls import path
from . import views
urlpatterns = [
path("index", views.index ),
path("index2", views.index2 ),
path("index3", views.index3 ),
path("index4", views.index4 ),
]
获取请求头数据
def index4(request):
"""获取请求头信息"""
print( request.META.get("CONTENT_TYPE") ) # application/json
"""获取自定义请求头"""
print( request.META.get("HTTP_COMPANY")) # oldboyedu
return HttpResponse("ok")
获取上传文件
print(request.FILES) # <MultiValueDict: {'avatar': [<InMemoryUploadedFile: 老男孩教育-数据库-存储迁移.jpg (image/jpeg)>]}>
print(request.FILES.get("avatar")) # 老男孩教育-数据库-存储迁移.jpg
print(type( request.FILES.get("avatar")) ) # <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>
响应
视图相应数据
-
响应内容
直接返回数据给客户端包括
HTML 内容(一般用于前后端不分离项目)和json 内容(前后端分离的 API 接口开发) -
响应页面
通过返回页面跳转的信息给浏览器,让浏览器自己进行页面跳转
返回 HTML 数据
ef index5(request):
"""响应对象"""
"""
return HttpResponse(content="正文内容",content_type="内容格式",status="http响应状态码")
content_type 内容格式,默认是 text/html
status 响应状态码,默认是 200
"""
"""返回html内容"""
return HttpResponse("<h1>hello world</h1>")
返回 JSON 数据
from django.http.response import JsonResponse
import json
def index5(request):
"""响应对象"""
"""返回json数据"""
# data = {
# "id":1,
# "username":"张晓明",
# "money": 22.50,
# "sex":True,
# "lve":["swimming","walk","game"]
# }
# goods_list = [
# {"id":1,"num":10,"name":"产品1"},
# {"id":2,"num":10,"name":"产品2"},
# {"id":3,"num":10,"name":"产品3"},
# {"id":4,"num":10,"name":"产品4"},
# ]
# # 方式1,如果返回非字典数据,务必设置 sale=False 才行.
# # return HttpResponse(json.dumps(data), content_type="application/json")
# # 方式2,如果返回非字典数据,务必设置 sale=False 才行.
# return JsonResponse(goods_list,safe=False)
返回图片信息
def index5(request):
"""响应对象"""
"""通过响应对象不仅可以返回HTML网页信息,还可以返回纯文本,或者图片,甚至完成文件下载的功能[这个过程只需要设置content_type即可]"""
# content = open("release.png","rb").read()
# return HttpResponse(content,content_type="image/jpeg")
提供下载支持
def index5(request):
"""响应对象"""
"""还可以是其他格式数据,用于提供下载"""
# with open("./basic-2.2.1.zip","rb") as f:
# content = f.read()
# return HttpResponse(content,content_type="application/x-zip-compressed")
自定义响应头
def index5(request):
"""响应对象"""
"""返回数据的过程中设置响应头"""
response = HttpResponse("ok")
# 自定义响应头[值和属性都不能是多字节]
response["company"] = "oldboyedu"
return response
页面跳转
# 跳转到站外
def index5(request):
"""响应对象"""
from django.shortcuts import redirect
# 方式1
# return HttpResponseRedirect("http://www.baidu.com")
# 方式2
# return redirect("http://www.baidu.com")
# 跳转到站内
def center(request):
# 方式1
# return redirect("/student/login")
# 方式2
print( reverse("stu:user_login") ) # 路由反转,自动根据编写的视图方式名反解析成url地址
return redirect( reverse("stu:user_login") )
def login(request):
return HttpResponse("登录页面")
在站内跳转时,如果使用reverse进行路由反转解析,则必须在总路由和子路由文件中,对路由的前缀和子路由进行别名绑定.方法如下:
# 总路由
from django.contrib import admin
from django.urls import path
from django.urls import include
urlpatterns = [
path('admin/', admin.site.urls),
# path('home/', include('home.urls',namespace="应用别名") ),
path('student/', include('demo.student.urls',namespace="stu") ),
]
# 子路由文件,例如:student/urls.py
from django.urls import path
from . import views
app_name = "student" # 当前子应用的包名
urlpatterns = [
# path("index", views.index ),
# path("index2", views.index2 ),
# path("index3", views.index3 ),
path("center", views.center ),
path("login", views.login, name="user_login" ),
]