django笔记(1)

django处理请求流程

image.png

django简单说明

1.安装

  • pip install django

2.创建项目

image.png

  • 目录结构

├── demo #项⽬⽬录

│ ├── __init__.py #包标志

│ ├── settings.py #项⽬配置⽂件

│ ├── urls.py #路由映射表

│ └── wsgi.py #wsgi接⼝

└── manage.py #项⽬管理命令
  • manage.py:是Django⽤于管理本项⽬的命令⾏⼯具,之后进⾏站点运⾏,数据库⾃动⽣成等都是通过本⽂件完成。
  • python manage.py startapp app 创建自己的应用
  • 把app加入settings.py中的INSTALLED_APPS中
  • python manage.py runserver启动服务
  • 访问127.0.0.1:8000

3.settings文件

# 项目根目录
BASE_DIR = Path(__file__).resolve().parent.parent

# 调试模式
DEBUG = True


# 允许访问的主机
ALLOWED_HOSTS = ['*']

# 安装的app,自己创建的app也应该加入
INSTALLED_APPS

# 模板配置
TEMPLATES

# 数据库配置,支持sqlite、mysql、oracle、pg
DATABASE=

#语⾔编码
LANGUAGE_CODE = 'zh-hans' 

#时区
TIME_ZONE = 'Asia/Shanghai' 

简单视图

  • app应用下的views.py代表视图,接受用户请求,经过处理逻辑后返回客户端文本、html、重定向等
from django.http import HttpResponse


def index(request):
    return HttpResponse("index view")

简单路由

  • 定义视图后,还需要把请求路径匹配到视图,在app应用目录下创建urls.py文件
from django.urls import path
from .views import index

urlpatterns = [
    path('index/', index, name="index"),
]
  • urlpatterns是固定名称,不应该改动
  • path函数第一个参数是路径名,第二个是视图函数,name参数可以完成名称到路径的映射。
  • 即使添加urls.py中的配置,依然不能访问,需要把app下的urls.py导入到项目目录下urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('app.urls'))
]

image.png

简单的模板

  • 目标:返回一个页面
  • 在templates下面创建index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h2>this is index page</h2>
</body>
</html>
  • 修改views.py文件
from django.shortcuts import render


def index(request):
    return render(request, "index.html")
  • request参数是必要的,由框架把请求封装成request对象然后传参

简单模型

  • 在models.py文件中定义模型类,一个模型类相当于一张表
class User(models.Model):
    uname = models.CharField(max_length=20)
    password = models.CharField(max_length=32)
  • 执行python manage.py migrate

  • 执行python manage.py makemigrations

  • 执行python manage.py migrate

  • 说明:第一次执行python manage.py migrate,生成django框架需要的表,python manage.py makemigrations生成数据库迁移文件,记录生成自定义表的信息,后续修改,都会生成迁移文件,第二次python manage.py migrate,就是真正生成自定义的数据库

  • 创建2条数据

image.png

  • 创建视图
def users(request):
    users = User.objects.all()
    return render(request, "users.html", context={"users", users})
  • 添加路由
path('users/', users, name="users")
  • 访问127.0.0.1:8000/api/users

image.png

路由

path函数参数

  • 路径名称
  • 视图函数
  • kwargs可选参数
  • 名称:通过该名称反向查询路径名称

1.路径名称

  • 除了具体的路径名称,还可以写正则表达式严格要求请求路径
re_path('re/(\d{11})', re_view, name="re")
  • 假设上面路径匹配手机号
def re_view(request, phone):
    return HttpResponse(phone)
  • 视图中添加处理函数

image.png

  • 总结:
    • urls.py中路径匹配是从上往下匹配

    • 一个视图可以有多个请求路径

    • 路径前面不要加/

    • 如果路径匹配不上会报404错误,把settings.py中DEBUG=False,会调用默认错误视图处理

动态url

path("hello/<name>/",views.hello)

path("show/<name>/<int:age>",views.show)
  • 当使用<>包起来变量,那么视图函数必须使用一样的变量名
def foo(request, name):
    pass
  • int:age和上面一样,但是也定义了该变量的类型是int
  • 参数类型
    • str:不定义时默认就是str类型
    • int:匹配0和正整数
    • slug:匹配数字字母、-、_组成的字符串
    • path:匹配非空字符串

path/<path: path>:假设有这么一个路径名称,当请求127:0.0.1:8000/path/etc/a/b/c,会传递etc/a/b/c字符串给视图

re_path(r'^hello/(\w+)/(\d{1,2})/$',views.hello)
re_path(r'^hello/(?P<name>\w+)/(?P<age>\d{1,2})/$',views.hello),
  • ()部分是正则的组,当匹配成功时,会把内容传递给视图函数
  • re_path(r'^hello/(\w+)/(\d{1,2})/$',views.hello)中(\w+)是位置参数,视图函数中任意变量名都可以接受
def foo(request, value1, value2):
    pass
  • re_path(r'^hello/(?P<name>\w+)/(?P<age>\d{1,2})/$',views.hello):视图函数只能是name和age
def foo(request, name, age):
    pass

请求和响应对象

1.HttpRequest对象

  • 服务器接收请求后封装成的对象
  • 试图函数的第一个对象必须是HttpRequest对象
  • HttpRequest可以获取的信息
属性说明
content-type请求的mime类型
GET一个QUeryDict对象,包含get请求方式的所有参数,也就是?后的内容
POST一个QUeryDict对象,包含post方式的所有参数
COOKIES一个标准的python字典,包含所有的cookie
SESSION一个类似字典的对象,表示当前会话,只有django启用会话时才可用
PATH一个字符串,表示请求的完整路径,不包括域名
method一个字符串,表示http常用的方法,GET、POST
FILES一个QueryDict,包含所有的上传文件
META请求头信息
scheme协议
  • META中常用的键值
说明
HTTP_REFERER来源页面
REMOTE_ADDR客户端ip
REMOTE_HOST客户端主机
  • 常用方法
方法名说明
get_host()主机+端口
get_full_path()获取请求路径+查询字符串
is_ajax()ajax请求返回True
build_absolute_uri()完整url

QueryDict

  • QueryDict是Dict的⼦类,和Dict最⼤的不同是,值都是列表。⽤于存储从请求中传递过来的参数,例如对于表单中select、checkbox等多值参数,QueryDict⾮常合适。get、post、files请求都对应⼀个QueryDict

  • HttpRequest中QueryDict是不可变的,只能获取值,不能修改

  • QueryDict键值对都是字符串

  • QueryDict中⼀个键可以对应多个值

  • 示例

{'hobby':['打篮球','玩游戏','k歌'],'name':['tom'],'age':'21'}
  • 实战
urlpatterns = [
    path('req_test/', req_test, name="req_test"),
]
  • 定义视图函数
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo</title>
</head>
<body>
<h2>name {{ name }}</h2>
<h2>hobby {{ hobbies }}</h2>
<h2>host {{ host }}</h2>
<h2>full_path {{ full_path }}</h2>
<h2>absolute_uri {{ absolute_uri }}</h2>
<h2>remote_address {{ remote_address }}</h2>
<h2>REMOTE_HOST {{ REMOTE_HOST }}</h2>
<h2>remote_address {{ scheme }}</h2>
</body>
</html>

image.png

2.HttpResponse对象

  • 每一个试图函数必须返回一个响应对象
属性说明
content字符串
charset字符编码
status_code状态码
content_type指定输出的MIME类型

示例

    1. 不用模板
def hello(req):
    return HttpResponse("hello world")
def goodbye(req):
    res = HttpResponse()
    res.content = b'good bye'
    res.charset = "utf-8"
    res.content_type = 'text/html'
    return res
  • 2.使用模板
def studentlist(req):
    for key in req.GET.lists():
    print(key)
    allstudent = Student.objects.all()
    return render(req,'studentlist.html',context={'data':allstudent})
  • 3.常用方法
write(content) 设置内容 == obj.content
set_cookie() 设置cookie
delete_cookie() 删除cookie

3.JsonResponse对象

  • JsonResponse 是HttpResponse的⼦类,⽤于向客户端返回json数据。⼀般⽤于ajax请求。它的content-type缺省值为:application/json

  • class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True,json_dumps_params=None, **kwargs)

data:可以是字典,如果safe设置为False,也可以是json序列化对象
encoder:编码格式,缺省是django.core.serializers.json.DjangoJSONEncoder
safe:缺省是True,如果传递⾮字典给data,则报TypeError
  • 示例
from django.http import JsonResponse
import json as myJson
#返回json数据
def json(req):
    jsonStr = JsonResponse({'name':'zhangsan','age':18})
    jsonStr = myJson.dumps({'name':'zhangsan','age':18})
    return HttpResponse(jsonStr)
 
  • json.dumps给ajax返回数据以后 js代码中需要将json数据使⽤Json.parse() 进⾏解析成js对象 ⽽JsonResponse会⾃动转换为js对象(少了异步Json.parse()的转换)
def courselist(req):
    courses = Course.objects.all() #QuerySet
    data = {'course':list(courses.values())} #查询结果集QuerySet转字典
    return JsonResponse(data) #传字典给JsonResponse
def courselist(req):
    courses = Course.objects.all()
    data = json.dumps(list(courses.values())) #查询结果集QuerySet转
    Json字符串,序列化
    return JsonResponse(data,safe=False) #safe必须设置为False

重定向

  • 不带参数重定向
#urls.py
urlpatterns = [
    path('',views.index),
    re_path(r'^list/$',views.list_user),
    #redirect 重定向路由地址
    url(r'^redirect/$',views.Redirect)
]
#views.py
def index(req):
    return render(req,'index.html')
def list_user():
    return HttpResponse("list user")
def Redirect(req):
    # return redirect('http://localhost:9000/')
    # return redirect('/')
    return redirect("list/")
  • 带参数重定向
#urls.py
urlpatterns = [
    path('repath/<int:num>/', views.repath),
    re_path(r'^parameter/(?P<num1>\d+)/(?P<num2>\d+)/$',views.parameter),
]
#views.py
def repath(req,num):
    return redirect("parameter/3/5")
def index(request):
    return HttpResponse("⾸⻚")
def parameter(req,num1, num2):
    return HttpResponse("num1={},num2={}".format(num1,num2))
  • 反向解析
  • 根据namespace和name查找真是路径,urls.py中app_name指定namespace,path函数中name=指定name
# urls.py中
app_name = 'App' # namespace 命名空间
urlpatterns = [
    path('', views.index, name="index"),
    path('para/<int:num1>/<int:num2>/', "para"),
]
#python代码中写法
def repath(req):
    #res = reverse("App:index")
    # print(res,type(res))
    #return redirect(res)
    # path中参数或re_path中的位置参数,args可以是列表或元组
    # return redirect(reverse("App:para",args=(1,2)))
    # re_path中命名组,带关键字参数
    return redirect(reverse("App:para",kwargs={'num1':1,'num2':3}))

# 模板中的写法:
<h2><a href="/form/">展示表单</a></h2>
<h2><a href="/index/">死链接⽆参的跳转</a></h2>
<h2><a href="/args/1/2/">死链接带参的跳转</a></h2>
<h2><a href="{% url 'App:index' %}">动态⽣成路由地址不带参的跳转</a>
</h2>
<h2><a href="{% url 'App:args1' 1 2 %}">动态⽣成路由地址带参的跳转</a>
</h2>
<h2><a href="{% url 'App:args1' num1=1 num2=2 %}">re_path中命名组,动
态⽣成路由地址带关键字参数的跳转</a></h2>

默认错误视图

  • 需要在settings中把DEBUG=False
  • 在templates目录下创建错误试图
  • 示例

image.png

image.png