Django基础-Web框架-URL路由
一、Django基础–Web框架
MVC和MTV框架
MVC
把Web应用分为模型(M)、视图(V)、控制器(C)三层,他们之间以一种插件式的,松耦合的方式联系在一起。模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接收用户的输入调用模型和视图完成用户的请求。
MTV
Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是值:
除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:
一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。
Django下载与安装
2.创建项目
3.目录介绍
4.运行Django项目
5.Django简单示例
URL控制器
from App import views
urlpatterns = [
url(r’^admin/’, admin.site.urls),
url(r"^login/$", views.login, name=“login”) # 对应到views视图,name是一个别名
]
在templates模板里写html
views视图
def login(request):
if request.method == “POST”:
user = request.POST.get(“user”)
password = request.POST.get(“password”)
user_obj = models.User.objects.filter(username=user, password=password)
if user_obj:
return render(request, “index.html”)
return render(request, “login.html”)
直接访问本地http://127.0.0.1:8000/login/
1.创建项目
2.创建app
3.url.py
4.templates
5.views.py
get,post请求
get请求获取数据
Get请求通常没有请求体,会放到url中
post请求获取数据
POST获取数数会进行安全检验(跨站请求),为了避免有三种方法
在form中添加 {% csrf_token %}
{% csrf_token %}在form中添加novalidate属性(表示不进行格式验证)
在settings.py中注释中间键
MIDDLEWARE = [ #中间键
]
登录页面-静态文件的引入
主是要在settings.py中设置STATIC_URL,STATICFILES_DIRS
配置settings.py:
#重要的是settings.py文件的设置(表示找到static文件)
STATIC_URL = '/static/' #静态文件的别名(static是可以修改的)指的是引入文件
# STATIC_URL里面的static是和引入文件对应的!!!!如果这里是xx那src="/xx/images/1.jpg
STATICFILES_DIRS=[
os.path.join(BASE_DIR,'static'),# 指的是创建的文件夹static,可以有1个或多个(和下面创建的相对应的)
os.path.join(BASE_DIR,'static1')
]
步骤: 1.先在bootcss.com网站找到对应的框架,2.把里面需要的内容copy过来 3.下载对应的css文件。4.创建static文件夹 5.在settings.py里面编写对应文件夹的位置 STATICFILES_DIRS=[ os.path.join(BASE_DIR,‘static’) 6.写html ]
实例操作
在settings.py文件下写入
STATIC_URL = '/static/' # 别名,一般都起static
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'cctv'),
]
{% load static %}
{#这样写了不用管STATIC_URL = '/static/' 叫什么名称了 会自己识别#}
STATIC_URL = '/xxx/' 都可以自动识别
{% get_static_prefix %} 这个是就识别当前的 STATIC_URL = '/xxx/ 名字 返回它的名字/xxx/
所有以可以这样写:
app的创建和注册
创建app:
此时新建了一个应用文件startapp,它的里面也创建了一些py文件和包:
migrations : 用于在之后定义引用迁移功能。
admin.py :管理站点模型的声明文件,默认为空。
apps.py :应用信息定义文件。在其中生成了类Appconfig,类用于定义应用名等Meta数据。app
models.py : 添加模型层数据类的文件。ORM
test.py :测试代码文件。
views.py :定义URL响应函数。 函数
注册:
在settings.py文件里面注册:
INSTALLED_APPS = [
。。。。
'app01', # 直接写app的名称
'app01.apps.App01Config' # 推荐写法
]
二、Django基础–URL路由
路由
from django.conf.urls import url
urlpatterns = { #Django2.0了这里这是path,也可以在settings.py里面查看版本信息
url(正则表达式,views视图,参数,别名),
}
正则表达式
r'^articles/2003/'
r:原生字符串
^:以什么开头
$:以什么结尾
\d:数字 {}:几个数字范围 \w:字母 [0-9][a-z] :0到9的数字和a到z的字符
. 匹配换行符之外的标志
+一个或多个
?0个或1个
*0个或多个
注意事项
urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
每个正则表达式前面的’r’ 是可选的但是建议加上。
urlpatterns = [
url(r’^admin/’, admin.site.urls),
url(r’^blog/KaTeX parse error: Expected 'EOF', got '#' at position 22: …ws.blog), #̲ blogs/2012/12/…’, views.blogs), #如果不写 的 时 候 , 我 们 访 问 b l o g / 2002 就 会 被 b l o g 给 截 胡 了 , 因 为 是 从 上 向 下 查 找 的 u r l ( r ′ b l o g s / [ 0 − 9 ] 4 / 的时候,我们访问blog/2002就会被blog给截胡了,因为是从上向下查找的 url(r'^blogs/[0-9]{4}/ 的时候,我们访问blog/2002就会被blog给截胡了,因为是从上向下查找的url(r′blogs/[0−9]4/’, views.blogs), # blogs/2012/
]
APPEND_SLASH=True #就是设置这个为False了django就不会默认加‘/’这个了
DEBUG = False 为True表示的是测试环境,上线的是时候要改成这样
ALLOWED_HOSTS = ["*"]
分组
url地址上捕获的参数会按照 位置传参 方式传递给视图函数
位置传参:()
url(r'^blogs/([0-9]{4})/(\d{2})/$', views.blogs),
url(r'^blogs/([0-9]{4})/$', views.blogs), # blogs/2012/
# views.py
def blogs(request,x,y): #一个括号,表示一个参数(位置传参),接送匹配到的数据
print(x,type(x))
print(y,type(y))
return HttpResponse("blogs")
命名分组
url地址上捕获的参数会按照 关键字传参 方式传递给视图函数
关键字传参:(?P<名称>) (?P<名称>)
url(r'^blogs/(?P[0-9]{4})/(?P\d{2})/$', views.blogs),
def blogs(request,year,month): # 这里的名称一定要和关键字对应
print(year,type(year))
print(month,type(month))
return HttpResponse("blogs")
def blogs(request,*args,**kwargs): #元组,和字典,这样也可以
print(args)
print(kwargs)
分组和命名分组,不能混合用。捕获的参数永远都是字符串
视图函数中指定默认值
# urls.py中
urlpatterns = [
url(r'^blog/$', views.page), #没有捕获取到东西的话,将会使用默认值 num=1
url(r'^blog/page(?P[0-9]+)/$', views.page),
]
# views.py中,可以为num指定默认值
def page(request, num="1"):
pass;)
在上面的例子中,两个URL模式指向相同的view - views.page - 但是第一个模式并没有从URL中捕获任何东西。
如果第一个模式匹配上了,page()函数将使用其默认参数num=“1”,如果第二个模式匹配,page()将使用正则表达式捕获到的num值。
传递额外的参数给视图函数
url(r'^blogs/([0-9]{4})/$', views.blogs,{"k1":"v1"}), # blogs/2012/
def blogs(request,*args,**kwargs):
print(args) #('2012',)
print(kwargs) #{'k1': 'v1'}
return HttpResponse("blogs")
include路由分发
在app下重新创建一个urls.py
from django.conf.urls import url
from app01 import views
urlpatterns = [
url(r’^blog/ ′ , v i e w s . b l o g ) , u r l ( r ′ b l o g s / ( [ 0 − 9 ] 4 ) / ', views.blog), url(r'^blogs/([0-9]{4})/ ′,views.blog),url(r′blogs/([0−9]4)/’, views.blogs,{“k1”:“v1”}), # blogs/2012/
]
改原本项目下的urls.py里面的内容加上include
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r’^admin/’, admin.site.urls),
# url(r’^app01/’, include(“app01.urls”)),# http://127.0.0.1:8000/app01/blogs/2002/
url(r’^’, include(“app01.urls”)),# http://127.0.0.1:8000/blog/ 如果为空的话
]
里面参数可以为空(其实就是把原来urls.py里面的参数封装到app下,让在用include()调用app下的urls.py)的内容
url的命名和反向解析
其实就是和函数中的as一样 设置一个别名
静态路由
命名:name=""
url(r'^blogs/$', views.blogs, name="bloogs"), # 设置一个别名 bloogs
反向解析: 模板 生成的地址
测试url的命名和反向解析 --> blogs - bloogs 获取的就是blogs
其实就是访问了别名为bloogs对应的url
py
from django.shortcuts import reverse #有两种导入的方法
from django.urls import reverse
print(reverse("bloogs")) #/blogs/
动态路由
分组:
url(r'^blogs/([0-9]{4})/(\d{2})$', views.blogs, name="bloogs"),
反向解析:模板
测试url的命名和反向解析
#要给上参数,还要参数对应,不然就会出错.其实就是访问了别名为bloogs对应的url
py
print(reverse(“bloogs”,args=(2002,99))) # /blogs/2002/99
命名分组
url(r'^blogs/(?P[0-9]{4})/(?P\d{2})$', views.blogs, name="bloogs"),
反向解析:模板
{#测试url的命名和反向解析#} #这个要对应参数
测试url的命名和反向解析 #这个不用对应参数
其实就是访问了别名为bloogs对应的url
py
print(reverse(“bloogs”,args=(2002,99))) # /blogs/2002/99
print(reverse(“bloogs”,kwargs={“year”:“2009”,“method”:99})) # /blogs/2009/9
命名空间 namespace
app01 urls.py:
urlpatterns = [
url(r'^home/$', views.home, name='home')
]
app02 urls.py:
urlpatterns = [
url(r'^home/$', views.home, name='home')
]
#app01和app02我们写了一样的别名
#我们用app01调用html的时候{% url 'home' %},app02的home会覆盖了app01里面的home
为了避免以上操作:我们就要加namespace
# 在项目的urls.py下
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include("app01.urls", namespace="app01")),
url(r'^app02/', include("app02.urls", namespace="app02")),
]
光加了命名空间,也不行。我们在用反向解析和py的时候,也要在对应的地方区分并添加
反向解析:
模块
{% url 'app01:home' %}
{% url 'app02:home' %}
py
print(reverse("app01:home")) # /app01/home/
print(reverse("app02:home")) # /app02/home/