02 Django基础-Web框架-URL路由

316 阅读5分钟

一、Django基础--Web框架

这是我参与更文挑战的第1天,活动详情查看: 更文挑战

MVC和MTV框架

MVC

把Web应用分为模型(M)、视图(V)、控制器(C)三层,他们之间以一种插件式的,松耦合的方式联系在一起。模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接收用户的输入调用模型和视图完成用户的请求。

MVC.png

MTV

Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是值:

  • M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
  • T 代表模板 (Template):负责如何把页面展示给用户(html)。
  • V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。

除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:

MTV.png

一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。

Django下载与安装

1. Dango下载

  • 命令行
  • 在pycharm中下载(和下载第三方一样)

2.创建项目

  • 命令行
    • Django-admin startproject 项目名称
  • pycharm
    • File à new project -> 左侧选择django ->选择目录 ->选择解释器->create按钮

3.目录介绍

image-20200802122257561

  • Settings.py:

    • BASE_DIR:项目的根目录

    • DEBUG=true: 当前是调试模式

      ​ 如果DEBUG=False ALLOWED_HOSTS=[“*”] 表示所的用户可以访问

    • TEMPLATES=[ “DIRS”:当前文件的地址] :模板

    • 'DIRS': [os.path.join(BASE_DIR, 'templates')]****:指定当前目录的文件夹。

      Templates文件夹是存放html文件的

4.运行Django项目

  • 命令行
    • python manage.py runserver #默认启动127.0.0.1:8000
    • python manage.py runserver 80 #更改默认端口127.0.0.1:80
    • python manage.py runserver 0.0.0.0:80 #更改Ip和端口
  • pycharm
    • ​ 不能用右键点击,直接选择项目,点绿三角

5.Django简单示例

  1. URL控制器
from App import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r"^login/$", views.login, name="login") # 对应到views视图,name是一个别名
]
  1. 在templates模板里写html
<div class="frame">
    <form action="" method="post" >
        {% csrf_token %}
        <h1>欢迎来到我的博客</h1>
        <input type="text" name="user">请输入用户名
        <br>
        <input type="password" name="password">请输入密码
        <br>
        <input type="submit" value="提交">
    </form>
</div>
  1. 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")
  1. 直接访问本地http://127.0.0.1:8000/login/
1.创建项目
2.创建app
3.url.py
4.templates
5.views.py

6. get,post请求

  1. get请求获取数据
Get请求通常没有请求体,会放到url中
  1. post请求获取数据
POST获取数数会进行安全检验(跨站请求),为了避免有三种方法

1. 在form中添加 {% csrf_token %}
    <form action="" method="post" >
        {% csrf_token %}
    </form>
2. 在form中添加novalidate属性(表示不进行格式验证)
	<form action="" method="post" novalidate>
    
    </form>
3. 在settings.py中注释中间键
	MIDDLEWARE = [ #中间键
    # 'django.middleware.csrf.CsrfViewMiddleware',  注释掉了可以提交POST请求
	]

登录页面-静态文件的引入

主是要在settings.py中设置STATIC_URL,STATICFILES_DIRS

配置settings.py:

#重要的是settings.py文件的设置(表示找到static文件)
STATIC_URL = '/static/' #静态文件的别名(static是可以修改的)指的是引入文件
# <img src="/static/images/1.jpg"> 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 ]

实例操作

  1. 在项目文件夹下建立一个文件夹存放静态文件,比如叫cctv
  2. 在cctv文件夹下再建立一个css文件夹
  3. 在css文件夹下建立一个das.css文件

在settings.py文件下写入

STATIC_URL = '/static/' # 别名,一般都起static
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'cctv'),
]
  	{% load static %}
	{#这样写了不用管STATIC_URL = '/static/' 叫什么名称了  会自己识别#}
    <link rel="stylesheet" href="{% static 'pulies/bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <link rel="stylesheet" href="{% static 'css/das.css' %}">

STATIC_URL = '/xxx/' 都可以自动识别
{% get_static_prefix %}  这个是就识别当前的 STATIC_URL = '/xxx/ 名字  返回它的名字/xxx/
所有以可以这样写:<link rel="stylesheet" href="{% get_static_prefix %}css/das.css">

app的创建和注册

创建app:

  1. 命令行:
    • python manage.py startapp startapp(名称)
  2. 通过 run manage.py task
    • tools -> run manage.py task -> 出现窗口 输入命令即可 startapp startapp(名称)

此时新建了一个应用文件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视图,参数,别名), 
}
  • 正则表达式:一个正则表达式字符串
  • views视图:一个可调用对象,通常为一个视图函数
  • 参数:可选的要传递给视图函数的默认参数(字典形式)
  • 别名:一个可选的name参数

正则表达式

r'^articles/2003/'

r:原生字符串
^:以什么开头
$:以什么结尾
\d:数字  {}:几个数字范围   \w:字母  [0-9][a-z] :09的数字和a到z的字符
. 匹配换行符之外的标志
+一个或多个
?0个或1个
*0个或多个
                

注意事项

  1. urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
  2. 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
  3. 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
  4. 每个正则表达式前面的'r' 是可选的但是建议加上。
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^blog/$', views.blog),
    # blogs/2012/12/
    url(r'^blogs/[0-9]{4}/\d{2}/$', views.blogs),  #如果不写$的时候,我们访问blog/2002就会被blog给截胡了,因为是从上向下查找的
    url(r'^blogs/[0-9]{4}/$', views.blogs), # blogs/2012/
]
# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
APPEND_SLASH=True      #就是设置这个为False了django就不会默认加‘/’这个了
DEBUG = FalseTrue表示的是测试环境,上线的是时候要改成这样

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<year>[0-9]{4})/(?P<month>\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<num>[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路由分发

  1. 在app下重新创建一个urls.py
from django.conf.urls import url
from app01 import views

urlpatterns = [
    url(r'^blog/$', views.blog),
    url(r'^blogs/([0-9]{4})/$', views.blogs,{"k1":"v1"}), # blogs/2012/
]
  1. 改原本项目下的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

反向解析: 模板 生成的地址

<a href="{% url 'bloogs' %}">测试url的命名和反向解析</a>     --> blogs - bloogs 获取的就是blogs  
其实就是访问了别名为bloogs对应的url

py

from django.shortcuts import reverse  #有两种导入的方法
from django.urls import reverse

print(reverse("bloogs"))  #/blogs/

动态路由

  1. 分组:
    url(r'^blogs/([0-9]{4})/(\d{2})$', views.blogs, name="bloogs"),
反向解析:模板

<a href="{% url 'bloogs' '2002' '02' %}">测试url的命名和反向解析</a>
#要给上参数,还要参数对应,不然就会出错.其实就是访问了别名为bloogs对应的url
py

print(reverse("bloogs",args=(2002,99)))  # /blogs/2002/99
  1. 命名分组
    url(r'^blogs/(?P<year>[0-9]{4})/(?P<method>\d{2})$', views.blogs, name="bloogs"),
反向解析:模板

{#<a href="{% url 'bloogs' '2002' '02' %}">测试url的命名和反向解析</a>#}  #这个要对应参数
<a href="{% url 'bloogs' method='99' year='2000' %}">测试url的命名和反向解析</a> #这个不用对应参数
其实就是访问了别名为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/