Django请求周期流程图(必会)

# 扩展知识点
    """
    缓存数据库
        提前已经将你想要的数据准备好了 你来直接拿就可以
        提高效率和响应时间

    当你在修改你的数据的时候 你会发现数据并不是立刻修改完成的
    而是需要经过一段时间才会修改
        博客园

    了解即可
    """

路由层

from django.conf.urls import url
urlpatterns = [
     url(正则表达式, views视图函数,参数,别名),
]

示例:

from django.conf.urls import url
urlpatterns = [
     url("", views.index,{"name":"lqz"}),    # 这样在视图层index函数就能接收到传的{"name":"lqz"}
]


# 视图层
def index(request,name):
    print(name)
    return HttpResponse("ok")

路由匹配

注意事项

1、惰性匹配

url(r'test',views.test),
url(r'testadd',views.testadd)
"""
url方法第一个参数是正则表达式
    只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
    直接执行对应的视图函数
"""

示例:

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),
    url(r'testadd', views.testadd),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

def test(request):

    return HttpResponse("test")

def testadd(request):

    return HttpResponse("testadd")

浏览器访问时,输入的包含test就可访问

2、自动加斜杠

url(r'test/', views.test),
url(r'testadd/', views.testadd),

"""
你在输入url的时候会默认加斜杠
    django内部帮你做到重定向
        一次匹配不行
        url后面加斜杠再来一次
"""

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),
    url(r'testadd/', views.testadd),
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

def test(request):

    return HttpResponse("test")

def testadd(request):

    return HttpResponse("testadd")

浏览器输入:http://127.0.0.1:8000/testadd访问时

你也可以在settings.py配置文件中取消django自动加斜杠/的机制

在settings.py中添加下面代码即可:

# 取消自动加斜杠
APPEND_SLASH = False    # True是开启

补充1:

url(r'test/', views.test),
url(r'testadd/', views.testadd),

浏览器输入http://127.0.0.1:8000/dfsjfdjksjtest/也能访问test,因为正则可以匹配

解决:加^匹配开头…

url(r'^test/', views.test),
url(r'^testadd/', views.testadd),

补充2、基于补充1

在浏览器输入http://127.0.0.1:8000/test/fafdsdfsfds还是能访问test

解决:加上$匹配结尾

url(r'^test/$', views.test),
url(r'^testadd/$', views.testadd),

配置网站首页

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'^$',views.home),       # 推荐写法
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return HttpResponse("home")

浏览器访问:http://127.0.0.1:8000/

无名分组

"""
分组:就是给某一段正则表达式用小括号扩起来
"""

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'^$',views.home),
    # 分组
    url(r'^test/(\d+)', views.test),
]

此时浏览器访问

我们接收一下这个参数看看是什么

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return HttpResponse("home")

def test(request,xxx):
    print(xxx)
    return HttpResponse("test")

此时浏览器访问:http://127.0.0.1:8000/test/123

在后端查看打印信息:

因此我们发现:

# 无名分组
    url(r'^test/(\d+)', views.test),    # 无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数

# 视图函数
def test(request,xx):
    print(xx)
    return HttpResponse('test')

有名分组

"""
可以给正则表达式起一个别名
"""

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'^$',views.home),
    # 无名分组
    url(r'^test/(\d+)', views.test),
    # 有名分组
    url(r'^testadd/(?P<year>\d+)', views.testadd),   # 给\d+这个表达式起了个别名year,这个year会传给视图函数testadd
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return HttpResponse("home")

def test(request,xxx):
    print(xxx)
    return HttpResponse("test")

def testadd(request):

    return HttpResponse("testadd")

浏览器访问一下,看一下报错信息(testadd视图函数缺少一个关键字参数year)

我们给testadd视图函数加上year关键字参数year

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 首页
def home(request):
    return HttpResponse("home")

def test(request,xxx):
    print(xxx)
    return HttpResponse("test")

def testadd(request,year):
    print(year)
    return HttpResponse("testadd")

浏览器访问并在后端查看这个year关键字参数打印

因此我们发现:

url(r'^testadd/(?P<year>\d+)',views.testadd)    # 有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数

def testadd(request,year):
    print(year)
    return HttpResponse('testadd')

无名、有名分组是否可以混合使用

"""
两者不能混用
但是同一个分组可以使用N多次
"""

# 单个的分组可以使用多次
url(r'^index/(\d+)/(\d+)/(\d+)/',views.index),
url(r'^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/',views.index),

反向解析

# 通过一些方法得到一个结果 该结果可以直接访问对应的url触发视图函数

# 先给路由与视图函数起一个别名
    url(r'^func_kkk/',views.func,name='ooo')
# 反向解析
    # 后端反向解析
      from django.shortcuts import render,HttpResponse,redirect,reverse
      reverse('ooo')
  # 前端反向解析
      <a href="{% url 'ooo' %}">111</a>

不包含分组的反向解析

前端反向解析示例:

无论urls.py里面的匹配正则参数怎么改,通过别名ooo。html的a标签都能访问到func

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'^func', views.func,name="ooo")   # 先给路由与视图函数关系起一个别名
]

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.
# 反向解析
def func(request):

    return HttpResponse("func")

home.html

html文件通过模板语法{% url “urls.py中设置的别名” %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<a href="{% url "ooo" %}">111</a>
<a href="{% url "ooo" %}">222</a>
<a href="{% url "ooo" %}">333</a>
<a href="{% url "ooo" %}">444</a>
<a href="{% url "ooo" %}">555</a>
<a href="{% url "ooo" %}">666</a>
<a href="{% url "ooo" %}">777</a>
</body>
</html>

后端反向解析示例(views.py需要导入reverse)

from django.shortcuts import render,HttpResponse,redirect,reverse

# Create your views here.

# 首页
def home(request):
    # urls.py中的正则匹配怎么改这边都能通过别名接收到,注意要导入reverse模块
    print(reverse("ooo"))     # reverse("urls.py中设置的反向解析的名字")
    return render(request,"home.html")

无名、有名分组的反向解析

无名分组反向解析

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'^$', views.home),
    # 无名分组反向解析
    url(r'^index/(\d+)/', views.index,name="ooo"),
]

views.py

from django.shortcuts import render,HttpResponse,redirect,reverse

# Create your views here.
# index
def index(request,args):
    print(args)
    return HttpResponse("index")

def home(request):
    print(reverse("ooo",args=(1,)))   # 后端写法,这个打印的是url路径,如果想跳转得url = reverse("ooo",args=(1,))然后return redirect(url)
    return render(request,"home.html")

home.html:前端书写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--无名分组反向解析前端写法-->
<a href="{% url "ooo" 123 %}">123</a>
</body>
</html>

补充:

# 关于url模板语法中123,是依据路由层分组匹配规则而写的
# 无名分组反向解析
    url(r'^index/(\d+)/', views.index,name="ooo"),
"""
这个数字写代码的时候应该放什么
    数字一般情况下放的是数据的主键值  数据的编辑和删除
"""

# 可以将url中的123换成模板语法的变量(不过变量不需要{{}},直接写就好了)
# 例如:
{%for user_obj in user_queryset%}
    <a href="{% url 'ooo' user_obj.id %}">编辑</a>
{%endfor%}

有名分组反向解析

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'^$', views.home),    # 有名分组反向解析
    url(r'^func/(?P<year>\d+)/', views.func,name="xxx"),
]

views.py

from django.shortcuts import render,HttpResponse,redirect,reverse

# Create your views here.
# 有名分组
def func(request,year):
    print(year)
    return HttpResponse("func")

def home(request):
    # 有名分组反向解析后端写法1,和无名分组一样,提供一个满足匹配规则的数字
    print(reverse("xxx",args=(1,)))     #推荐写法
    # 有名分组反向解析后端写法2:
    # print(reverse("xxx",kwargs={"year":123}))     #正规写法
    return render(request,"home.html")

home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--前端有名分组反向解析-->
<!--正规写法-->
{#<a href="{% url "xxx" year=123 %}">123</a>#}
<!--推荐写法,因为这个写法和无名分组一样,好记-->
<a href="{% url "xxx" 123 %}">123</a>

</body>
</html>

路由分发

"""
django的每一个应用都可以有自己的templates文件夹 urls.py static文件夹
正是基于上述的特点 django能够非常好的做到分组开发(每个人只写自己的app)
作为组长 只需要将手下书写的app全部拷贝到一个新的django项目中 然后在配置文件里面注册所有的app再利用路由分发的特点将所有的app整合起来

当一个django项目中的url特别多的时候 总路由urls.py代码非常冗余不好维护
这个时候也可以利用路由分发来减轻总路由的压力

利用路由分发之后 总路由不再干路由与视图函数的直接对应关系
而是做一个分发处理
    识别当前url是属于哪个应用下的 直接分发给对应的应用去处理

"""

环境简述:

项目中有两个应用(app01,app02),现在通过在项目的urls.py中配置路由分发到每个应用的urls.py

ps:

应用中的urls.py文件是开发这个应用的自己写的,默认没有的,需要自己建

第一种实现:

day62\day62\urls.py:总路由

注意事项:

总路由的第一个参数不要加$,因为加了$符就不再往后面匹配了,例如:url(r’^app01/$’,include(app01_urls)),

from django.conf.urls import url,include
from django.contrib import admin
from app01 import urls as app01_urls
from app02 import urls as app02_urls

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 总路由中,路由分发,注意,需要导入一个include方法
    url(r'^app01/',include(app01_urls)),      # 只要url前缀是app01开头,全部交给app01处理
    url(r'^app02/',include(app02_urls)),      # 只要url前缀是app02开头,全部交给app02处理    # 注意事项:总路由里面的url千万不能加$符结尾
]

app01\urls.py

from django.conf.urls import urlfrom app01 import views

urlpatterns = [
    url(r'^reg/', views.reg),
]

app02\urls.py

from django.conf.urls import urlfrom app02 import views

urlpatterns = [
    url(r'^reg/', views.reg),
]

app01\views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

def reg(request):
    return HttpResponse("app01:reg")

app02\views.py

from django.shortcuts import render,redirect,HttpResponse

# Create your views here.
def reg(request):
    return HttpResponse("app02:reg")

浏览器访问:http://127.0.0.1:8000/app01/reg/

第二种实现:终极写法,推荐使用

day62\day62\urls.py:总路由

from django.conf.urls import url,include
from django.contrib import admin


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 总路由中,路由分发,注意,需要导入一个include方法
    url(r'^app01/',include("app01.urls")),
    url(r'^app02/',include("app02.urls")),
]

app01\urls.py

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^reg/', views.reg),
]

app02\urls.py

from django.conf.urls import url
from app02 import views

urlpatterns = [
    url(r'^reg/', views.reg),
]

app01\views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

def reg(request):
    return HttpResponse("app01:reg")

app02\views.py

from django.shortcuts import render,redirect,HttpResponse

# Create your views here.
def reg(request):
    return HttpResponse("app02:reg")

路由分发的本质

urls.py

# 路由分发本质    include  可以无限制的嵌套N多层
    url(r'^index/',([],None,None))
# 示例:
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/',([
        url(r'^index_1/',([
                url(r'^index_1_1',views.index),
                url(r'^index_1_2',views.index),
                url(r'^index_1_3',views.index),
                          ],None,None)),
        url(r'^index_2/',views.index),
        url(r'^index_3/',views.index),
                ],None,None)),

]

views.py

from django.shortcuts import render, HttpResponse,redirect

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

浏览器访问

应用独立static和Templates

参考:https://blog.csdn.net/qq_39112101/article/details/89524071

名称空间

# 当多个应用出现了相同的别名 反向解析不会自动识别应用前缀

环境:

接着上面路由分发的环境,有两个应用,考虑到两个应用中urls.py里面起别名冲突的情况,想正常使用反向解析的解决方案(就可以用名称空间)

应用别名冲突情况下:

day62\day62\urls.py:总路由

from django.conf.urls import url,include
from django.contrib import admin


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 总路由中,路由分发,注意,需要导入一个include方法
    url(r'^app01/',include("app01.urls",namespace="app01")),
    url(r'^app02/',include("app02.urls",namespace="app02")),
]

app01\urls.py

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^reg/', views.reg,name="reg"),     # 别名和app02冲突
]

app02\urls.py

from django.conf.urls import url
from app02 import views

urlpatterns = [
    url(r'^reg/', views.reg,name="reg"),
]

app01\views.py

from django.shortcuts import render,HttpResponse,redirect,reverse

# Create your views here.

def reg(request):
    # 此时冲突的情况下后端使用反向解析,使用名称空间解析
    print(reverse("app01:reg"))     # /app01/reg/
    return HttpResponse("app01:reg")

app02\views.py

from django.shortcuts import render,redirect,HttpResponse,reverse

# Create your views here.
def reg(request):
    # 此时反向解析,使用名称空间解析
    print(reverse("app02:reg"))     # /app02/reg/
    return HttpResponse("app02:reg")

此时前端使用反向解析示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

{% url "app01:reg" %}
{% url "app02:reg" %}

</body>
</html>

总结:为什么要用名称空间,就是因为应用别名冲突了,所以,我们如果起别名的时候保证不冲突就不用使用名称空间了

"""
一般情况下 有多个app的时候我们在起别名的时候会加上app的前缀
这样的话就能够确保多个app之间名字不冲突的问题
"""

day62\day62\urls.py:总路由

from django.conf.urls import url,include
from django.contrib import admin


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 总路由中,路由分发,注意,需要导入一个include方法
    url(r'^app01/',include("app01.urls")),
    url(r'^app02/',include("app02.urls")),
]

app01\urls.py

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^reg/', views.reg,name="app01_reg"),
]

app02\urls.py

from django.conf.urls import url
from app02 import views

urlpatterns = [
    url(r'^reg/', views.reg,name="app02_reg"),
]

app01\views.py

from django.shortcuts import render,HttpResponse,redirect,reverse

# Create your views here.

def reg(request):
    # 此时反向解析,使用名称空间解析
    print(reverse("app01_reg"))     # /app01/reg/
    return HttpResponse("app01:reg")

app02\views.py

from django.shortcuts import render,redirect,HttpResponse,reverse

# Create your views here.
def reg(request):
    # 此时反向解析,使用名称空间解析
    print(reverse("app02_reg"))     # /app02/reg/
    return HttpResponse("app02:reg")

不冲突情况下前端正常使用反向解析:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

{% url "app01_reg" %}
{% url "app02_reg" %}

</body>
</html>

伪静态

"""
静态网页
    数据是写死的 万年不变

伪静态
    将一个动态网页伪装成静态网页

    为什么要伪装呢?
        https://www.cnblogs.com/Dominic-Ji/p/9234099.html
        伪装的目的在于增大本网站的seo查询力度
        并且增加搜索引擎收藏本网上的概率

    搜索引擎本质上就是一个巨大的爬虫程序

    总结:
        无论你怎么优化 怎么处理
        始终还是干不过RMB玩家
"""

Django怎么实现伪静态:

例如在app01中如下配置:

from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^reg.html', views.reg),
]

app01\views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

def reg(request):
    return HttpResponse("app01:reg")

在浏览器访问

虚拟环境

"""
在正常开发中 我们会给每一个项目配备一个该项目独有的解释器环境
该环境内只有该项目用到的模块 用不到一概不装

linux:缺什么才装什么

虚拟环境
    你每创建一个虚拟环境就类似于重新下载了一个纯净的python解释器
    但是虚拟环境不要创建太多,是需要消耗硬盘空间的

扩展:
    每一个项目都需要用到很多模块 并且每个模块版本可能还不一样
    那我该如何安装呢? 一个个看一个个装???

    开发当中我们会给每一个项目配备一个requirements.txt文件
    里面书写了该项目所有的模块即版本
    你只需要直接输入一条命令即可一键安装所有模块即版本
    ps:requirements.txt使用
    # pip3 install -r requirements.txt   #安装requirements.txt依赖
    # 生成requirements.txt文件  (在项目根目录下执行)
    # pip3 freeze > requirements.txt
    # 使用
    # pip install -r requirements.txt

"""

创建虚拟环境步骤:

1、pycharm-file-New Project

2、创建完成(标志venv文件夹)

Django1.x和2.x版本区别

"""
1.django1.X路由层使用的是url方法
    而在django2.X和3.X版本中路由层使用的是path方法
    url()第一个参数支持正则
    path()第一个参数是不支持正则的 写什么就匹配什么


    如果你习惯使用path那么也给你提供了另外一个方法re_path就和url一样,django2.x和django3.x中还是支持url的不过不推荐使用(也不合理)
        from django.urls import path, re_path        # django2.x和3.x正确使用方法
        from django.conf.urls import url             # url能够使用,但不推荐(容易让人版本混淆)

        re_path(r'^index/',index),
        url(r'^login/',login)
  2.X和3.X里面的re_path就等价于1.X里面的url


2.虽然path不支持正则 但是它的内部支持五种转换器
    path('index/<int:id>/',index)
    # 将第二个路由里面的内容先转成整型然后以关键字的形式传递给后面的视图函数

    def index(request,id):      
    print(id,type(id))
    return HttpResponse('index')



    str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
    int,匹配正整数,包含0。
    slug,匹配字母、数字以及横杠、下划线组成的字符串。
    uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
    path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)

3.除了有默认的五个转换器之外 还支持自定义转换器(了解)
# ================自定义转换器==================================
    # app01.path_converts中
    class MonthConverter:
        regex='\d{2}' # 属性名必须为regex

        def to_python(self, value):
            return int(value)

        def to_url(self, value):
            return value # 匹配的regex是两个数字,返回的结果也必须是两个数字


    # urls.py中注册转换器
    from django.urls import path,register_converter
    from app01.path_converts import MonthConverter
    from app01 import views

    register_converter(MonthConverter,'mon')

    urlpatterns = [
    path('articles/<int:year>/<mon:month>/<slug:other>/',     views.article_detail, name='aaa'),

]


4.模型层里面1.X外键默认都是级联更新删除的
  models.ForeignKey(to='Publish')
但是到了2.X和3.X中需要你自己手动配置参数 
models.ForeignKey(to='Publish',on_delete=models.CASCADE)
  on_delete其他选项
  CASCADE:删除作者信息一并删除作者名下的所有书的信息;
  PROTECT:删除作者的信息时,采取保护机制,抛出错误:即不删除Books的内容;
  SET_NULL:只有当null=True才将关联的内容置空;
  SET_DEFAULT:设置为默认值;
  SET( ):括号里可以是函数,设置为自己定义的东西;
  DO_NOTHING:啥也不干
"""
文档更新时间: 2022-03-01 21:52   作者:李延召