Django(URL、Views、Template)

1. Django初步使用

1.1 MVC和MTV框架

1.1.1 MVC

  • M:模型,负责业务对象和数据库的映射(ORM)
  • V:视图,负责与用户的交互(页面)
  • C:控制器,负责与用户的交互(页面)

Django(URL、Views、Template)

1.1.2 MTV

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

 此外还需一个URL分发器,将一个个URL请求分发给不同的View处理。

Django(URL、Views、Template)

1.2. Django的安装和使用

直接通过pip3 install去下载对应版本的Django即可。

1.2.1 创建django project

先新建一个Django_projects文件夹,进入这个文件夹后,创建第一个项目。

django-admin startproject mysite   # 创建了一个名为"mysite"的Django 项目

django project的目录结构:

mysite
|--- manage.py        # Django项目里的工具,可以通过它调用django shell和数据库,启动关闭项目与项目交互等
|--- mysite              
|--- __init__.py |--- settings.py # 包含了项目的默认设置 |--- urls.py # 负责把URL模式映射到应用程序 |--- wsgi.py

注意:

  • 创建Django项目不能用中文
  • 要将django-admin.exe的路径配置到环境变量中
    • 这个文件的位置一般在python解释器目录的Scripts目录下

启动Django:

python manage.py runserver 127.0.0.1:8080  # 此时已经可以启动django项目了,只不过什么逻辑也没有

1.2.2 创建应用

通过manage.py可以创建应用

python manage.py startapp app01   
# 通过执行manage.py文件来创建应用,
# 应该在这个manage.py的文件所在目录下执行这句话,因为其他目录里面没有这个文件


python manage.py startapp app02 # 每个应用都有自己的目录,每个应用的目录下都有自己的views.py视图函数和models.py数据库操作相关的文件

1.2.3 修改settings配置

将URL中的路径和本地文件系统上的路径做对应关系映射:

STATIC_URL = /static/               # 这里表示的是URL中的路径
STATICFILES_DIRS=( 
   os.path.join(BASE_DIR,"statics"),  # 这里表示的是本地文件系统的路径
)

将csrf中间件选项暂时注释:

# ‘django.middleware.csrf.CsrfViewMiddleware‘,   #这里先注释掉

1.2.4 启动项目

python manage.py runserver 127.0.0.1:8080  # 本机可以不写ip地址了 默认是本机的8000端口

2. URL路由系统

2.1 基本使用格式

 django2.0之后是使用了path,但是也向下兼容使用url,导入url即可。

from django.conf.urls import url
urlpatterns = [
     url(正则表达式, views视图函数,参数,别名),
]
# 正则表达式:一个正则表达式字符串
# views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
# 参数:可选的要传递给视图函数的默认参数(字典形式)
# 别名:一个可选的name参数

2.2 URL分组

2.2.1 无名分组

所谓无名分组,其实就是给视图函数传递位置参数

将要传递的参数在放入小括号()中,然后在对应的视图函数中按顺序接收对应的参数即可。

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [# 无名分组 (给应用视图函数传递位置参数)
    url(rbooks/(\d{4})/$, views.year),  # 完全匹配
    url(r^books/(\d{4})/(\d{2})/$, views.year_mouth),
    url(r^books/(\d{4})/(\d{2})/(\d{2})/$, views.year_mouth_day),
]
  • urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续
  • 若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)
  • 不需要添加一个前导的反斜杠(也就是写在正则最前面的那个/),因为每个URL 都有
    • 例如,应该是^books而不是 ^/books
  • 每个正则表达式前面的 ‘r‘ 是可选的但是建议加上
  • ^books&  以什么结尾,以什么开头,严格限制路径
  • # 是否开启URL访问地址后面没有/跳转至带有/的路径的配置项,默认是开启的
    APPEND_SLASH=True

2.2.2 有名分组

所谓有名分组,就是捕获URL中的值并以关键字参数形式传递给视图函数。

分组命名正则表达式组的语法是(?P<name>pattern),其中name是组的名称,pattern是要匹配的模式。

urlpatterns = [
    url(r^articles/(?P<year>[0-9]{4})/$, views.year),
# 某年的,(?P<year>[0-9]{4})这是命名参数,那么函数year(request,year),形参名称必须是year这个名字
# 如果这个正则后面没有写$符号,即便是输入了月份路径,也会被它拦截下拉,因为它的正则也能匹配上
url(r^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$, views.month), url(r^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$, views.details), ]
  • 也可以对应views函数的默认值参数,也就是说视图函数中可以指定参数的默认值
  • 捕获的参数永远都是字符串

2.3 URL分发

因为一个项目中可能有多个应用,所以我们需要对URL做分发。

要将新创建的应用添加到setttings配置文件中的INSTALLED_APPS中

使用include即可完成对URL的分发:(include需要手动导入)

from django.conf.urls import url,include
urlpatterns = [
     # 输入不同的url找到不同的app 分发给不同的应用的urls.py
    url(r^app01/, include(app01.urls)), 
     # 这时app01中的urls只需要处理app01后面的那部分url了
    url(r^app02/, include(app02.urls)),

]

2.4 URL别名

通过给URL定义一个别名来防止URL路径更改后URL失效。

使用别名:

# 给url匹配模式起名为 home,别名不需要改,路径就可以随便改了,别的地方要使用这个路径,则用这个别名即可
url(r^home, views.home, name=home),  
url(r^index/(\d*), views.index, name=index), 

在模板中的引用:

{% url home %}  #模板渲染的时候,被django解析成了这个名字对应的那个url,这个过程叫做反向解析 

3. Views视图函数

http请求中产生的核心对象:(所在位置:django.http)

  • http请求:HttpRequest对象
  • http响应:HttpResponse对象

3.1 HttpRequest对象

1) path

  • 请求页面的全路径,不包括域名,也不包括参数

2) method

  • 请求中使用的HTTP方法的字符串表示,全大写表示
if request.method=="GET":
    do_something()
elif request.method=="POST":
    do_something_else()

3) GET

  • 包含所有HTTP GET参数的类字典对象

4) POST

  • 包含所有HTTP POST参数的类字典对象
  • 服务器收到空的POST请求的情况有可能发生,也就是说,表单form通过HTTP POST方法提交请求,但是表单中可能没有数据
    • 因此不能使用if req.POST来判断是否使用了HTTP POST 方法;应该使用 if req.method=="POST"

5) session

  • 唯一可读写的属性,代表当前会话的字典对象
  • 自己有激活Django中的session支持时该属性才可用

6) COOKIES

  • 包含所有cookies的标准Python字典对象
  • keys和values都是字符串

7) FILES

  • 包含所有上传文件的类字典对象
  • FILES中的每一个Key都是<input type="file" name="" />标签中 name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:
    • filename: 上传文件名,用字符串表示
    • content_type: 上传文件的Content Type
    • content: 上传文件的原始内容

8) user

  • 是一个django.contrib.auth.models.User对象,代表当前登陆的用户
  • 如果访问用户当前没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例
  • 可以通过user的is_authenticated()方法来辨别用户是否登陆:if req.user.is_authenticated()
  • 只有激活Django中的AuthenticationMiddleware时该属性才可用

方法:

  • get_full_path()
    • 得到包含参数的path
  • request.POST.getlist("")

3.2 HttpResponse对象

HttpResponse对象由我们自己创建,且每个view请求处理方法必须返回一个HttpResponse对象。

HttpResponse类在django.http.HttpResponse,需要手动导入。

HttpResponse对象上扩展的常用方法:

  • 页面渲染:
    • render()     
    • render_to_response()
  • 页面跳转:
    • redirect("路径")
  • 直接返回:
    • HttpResponse("xxoo")
  • locals()函数可以直接将函数中所有的变量传给模板
    • return render(req,"my backend.html",locals()

render和redirect的区别:

  • render的页面需要模板语言渲染,且url并没有变化,还是保持不变
  • redirect是直接跳转,url会改变

4. Template模板系统

模板渲染的两种特殊符号:

  • 变量相关的用  {{ }}
  • 逻辑相关的用  {% %} 

4.1 变量的使用

4.1.1 语法格式

使用双大括号来引用变量:

{{ var_name }}

Views函数中的代码:

def current_time(req):
    now=datetime.datetime.now()
    return render(req, current_datetime.html, {current_date:now}) 
    # 在模板中,就可以使用{{current_date}}来引用这里的变量

4.1.2 深度变量的查找

利用点号来查找深度变量

点号可以访问列表索引,也可以通过字典的键来访问对应的值,同样也可以访问对象的属性以及方法

{{ items.2 }}      # 通过列表的索引来获取对应的值
{{ person.name }}  # 通过字典的key来获取对应的值
{{ date.month }}   # 通过点号来访问对象的属性
{{ var.upper }}    # 通过访问对应的方法来调用它

4.1.3 变量的过滤器(filter)

1)语法格式

  • {{ obj|filter:param }}

2)常用的过滤器

# default:如果值是False,就替换成设置的默认值,否则就是用本来的值
{{ value|default:值是False}}
# length:返回值的长度,作用于字符串和列表 {{ name_list|length }}
# slice:切片,支持python中可用的所有数据类型 {{ name_list|slice:1:3 }} {{ s|slice:1::2 }} # add:给变量加上相应的值 {{ value|add:3 }} # capfirst:首字母大写 {{ value|capfirst }} # upper:字符转换成大写 {{ value|upper }} # cut:从字符串中移除指定的字符 {{ value|cut: }} # date:格式化日期字符串 {{ value|date:Y-m-d }}    # join:设定连接符将可迭代对象的元素连接在一起,与字符串的join方法相同 {{ name_list|join:_}} {{ tu|join:+}} # safe:告知Django这段代码为安全的,不必进行转义 {{ value|safe}}

4.2 标签(tag)的使用

4.2.1 使用标签的格式

  • {% tags %}

4.2.2 常用的标签

{% if %}

  • {% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
  • {% if %} 标签不允许同一标签里同时出现and和or
  • {% if %} 可以和过滤功能进行配合
{% if num >= 100 and 8 %}
    {% if num > 200 %}
        <p>num大于200</p>
    {% else %}
        <p>num大于100小于200</p>
    {% endif %}
{% elif num < 100%}
    <p>num小于100</p>
{% else %}
    <p>num等于100</p>
{% endif %}

{% for %}

<ul>
{% for obj in list %}
    <li>{{ obj.name }}</li>
{% endfor %}
</ul>

# 在标签里可以用reversed来反序循环列表
{% for obj in list reversed %}
    ...
{% endfor %}
  • forloop.first  第一次循环
  • forloop.last  最后一次循环
  • 示例:
    {% for foo in name_list %}
        {% if forloop.first %}
            {{ foo }}
        {% else %}
            <p>只有第一次循环打印</p>
        {% endif %}
    {% endfor %}

{% csrf_token %}

  • 用于生成csrf_token的标签,用于防止跨站攻击验证
  • 这里其实会生成一个隐藏的input标签,提交时和其他表达标签一并提交给后台
  • 使用时在form标签里面加上{% csrf_token %}即可
    <form action="{% url "xxoo" %}" >
              <input type="text">
              <input type="submit"value="提交">
              {% csrf_token %}
    </form>

{% url %}

{% with %}

  • 用更简单的变量名替代复杂的变量名
  • 只在with段内有效
    {% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}

{% load %}

  • 加载标签库

4.3 自定义filter和simple_tag

1)在app中创建templatetags模块(必须创建,且名字不能改)

2)创建 .py文件,如my_tags.py

from django import template
from django.utils.safestring import mark_safe

register = template.Library()   #register的名字是固定的,不可改变

@register.filter
def filter_multi(v1,v2):
    return  v1 * v2

@register.simple_tag
def simple_tag_multi(v1,v2):
    return  v1 * v2

@register.simple_tag
def my_input(id,arg):
    result = "<input type=‘text‘ id=‘%s‘ class=‘%s‘ />" %(id,arg,)
    return mark_safe(result)

3)在settings中的INSTALLED_APPS配置当前app

  • 要配置当前app,否则Django无法找到自定义的simple_tag
  • 如果找不到,重启一下Django试试

3)在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

  • 必须在模板的首行导入{% load xxx %},这里是导入my_tags

4)使用simple_tag和filter

{% load xxx %}           #首行 
    
 # num=12
{{ num|filter_multi:2 }}      # filter_multi只能传一个值,前面的num将作为它的第一个参数
                              # 而冒号后的值将作为第二个参数

{% simple_tag_multi 2 5 %}    # 参数不限,但不能放在if for语句中
{% simple_tag_multi num 5 %}

# filter_multi可以用在if等语句后,simple_tag不可以
{% if num|filter_multi:30 > 100 %}
    {{ num|filter_multi:30 }}
{% endif %}

4.4 模板的继承

1)extends

  • 继承母版master.html,只需在其他页面添加一行:
    {% extends master.html %}

2)block

  • 对母版中对应位置的内容进行替换,一般对js,css,html三部分内容定义三个bock
  • 在base模版中设置越多的 {% block %} 标签越好
  • 不能在一个模板中定义多个相同名字的block标签

在母版中定义:

<div class="menu">
    {% block content %}
    {% endblock %}
</div>

在其他页面对母版继承后,再进行对应内容的替换:

{% extends master.html %}  # 继承母版

# 进行对应位置内容的替换
{% block content %}
     base页面首页
{% endblock %}

3)保留母版内容并添加新特性

  • 使用super即可

母版html:

<div class="menu">

    {% block content %}
        <div>这是母版测试页面</div>
    {% endblock %}
</div>

base.html:

{% block content %}
    {{ block.super }}
     base页面首页
{% endblock %}

5. Models(ORM系统)

ORM是 “对象-关系-映射” 的简称。(Object Relational Mapping,简称ORM)

5.1 数据库的配置和使用

1)配置settings文件

django默认使用sqlite的数据库,并默认自带sqlite的数据库驱动

如果要更改数据库为MySQL,需要配置如下:

DATABASES = {
    default: {
        ENGINE: django.db.backends.mysql, 
        NAME: books,  # 数据库名称,必须事先创建好
        USER: root,   # 数据库用户名
        PASSWORD: ‘‘,   # 数据库密码
        HOST: ‘‘,       # 数据库主机,留空默认为localhost
        PORT: 3306,   # 数据库端口
    }
}

2)更改MySQL驱动

django默认的MySQL驱动为MySQLdb,而MySQLdb在py3中有问题,所以还需要更改MySQL驱动为pymysql

# 找到项目名文件下的__init__,在里面写入:

import pymysql
pymysql.install_as_MySQLdb()

3)在models中通过类创建数据库表

在对应app的models文件中创建数据库表

  • 每个类就对应一张表
  • 类的每个实例就对应于表中的一条记录
  • 每个类中的属性就对应每张表中对应的每个字段
from django.db import models
# Create your models here.

class UserInfo(models.Model):               # 这里类就对应于一张表,且必须继承models.Model
    id = models.AutoField(primary_key=True)  
    name = models.CharField(max_length=16)
    age = models.IntegerField()
    current_date = models.DateField()

    """
    上面的几个类的属性通过ORM映射就对应成了:
    create table userinfo(
        id int primary key auto_increment,
        name varchar(16),
        age int,
        current_date date)
    """

4)在数据库中生成表结构

将上面的类生成真生的数据库中的表结构 

python manage.py makemigrations
# Django 会在相应的 app 的migrations文件夹下面生成 一个python脚本文件 

python manage.py migrate
# 生成数据库表

# 此时,对应app下面的migrations目录中出现一个0001_initial.py的文件,这个文件就是执行了上述指令之后产生的脚本文件,这个文件就是一个记录

5.2 更多的字段和参数

5.2.1 字段

CharField
    # 字符串字段, 用于较短的字符串
    # CharField 必须有一个参数 maxlength, 限制该字段所允许的最大字符数.

IntegerField
    # 用于保存一个整数

DecimalField
    # 一个浮点数. 必须 提供两个参数:
    #    max_digits 总位数(不包括小数点和符号)
    #    decimal_places 小数位数
    #        要保存最大值为 999 (小数点后保存2位):
    #            models.DecimalField(..., max_digits=5, decimal_places=2)
    #        要保存最大值一百万(小数点后保存10位): 
    #            models.DecimalField(..., max_digits=17, decimal_places=10) 
    #                max_digits大于等于17就能存储百万以上的数了
    # admin 用一个文本框(<input type="text">)表示该字段保存的数据

AutoField
    # 一个 IntegerField, 添加记录时它会自动增长,通常不需要直接使用这个字段
    # 自定义一个主键:my_id=models.AutoField(primary_key=True)
    # 如果不指定主键,系统会自动添加一个主键字段到 model

BooleanField
    # A true/false field
    # admin 用 checkbox 来表示此类字段

TextField
    # 一个容量很大的文本字段
    # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框)

EmailField
    # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数

DateField
    # 一个日期字段
    # 有下列额外的可选参数:
    #    auto_now    
    #        当对象被保存时(更新或者添加),自动将该字段的值设置为当前时间.
    #        通常用于表示 "last-modified" 时间戳.
    #    auto_now_add    
    #        当对象首次被创建时,自动将该字段的值设置为当前时间.
    #        通常用于表示对象创建时间.
    #    (仅仅在admin中有意义...)

DateTimeField
    # 一个日期时间字段. 类似 DateField 支持同样的附加选项

ImageField
    # 类似 FileField, 不过要校验上传对象是否是一个合法图片
    # 它有两个可选参数:height_field和width_field,如果提供这两个参数,则图片将按提供的高度和宽度规格保存
    
FileField
    # 一个文件上传字段.
    # 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 
    # 这个路径必须包含 strftime #formatting,
    # 该格式将被上载文件的 date/time替换(so that uploaded files don‘t fill up the given directory).
    # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .
    #
    # 在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
    #    1) 在 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件
    #            出于性能考虑,这些文件并不保存到数据库
    #            定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对WEB服务器用户帐号是可写的.
    #    2) 在 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,
    #            以告诉 Django使用 MEDIA_ROOT 的哪个子目录保存上传文件.
    #            数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT).
    #        如果 ImageField 叫作 mug_shot, 就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径

URLField
    # 用于保存 URL. 
    # 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且没有返回404响应).
    # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)

NullBooleanField
    # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 
    # 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
    # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据

XMLField
    # 一个校验值是否为合法XML的 TextField
    # 必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema 的文件系统路径.

FilePathField
    # 可选项目为某个特定目录下的文件名. 
    # 支持三个特殊的参数, 其中第一个是必须提供的.这三个参数可以同时使用.
    #    path    
    #        必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目.
    #        Example: "/home/images".
    #    match    
    #        可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. 
    #        注意这个正则表达式只会应用到 base filename 而不是路径全名. 
    #        Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
    #    recursive
    #        可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
    #
    # match 仅应用于 base filename, 而不是路径全名
    #    FilePathField(path="/home/images", match="foo.*", recursive=True)
    #    会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif

IPAddressField
    # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
    
CommaSeparatedIntegerField
    # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.

5.2.2 参数

null
    # 如果为True,Django 将用NULL 来在数据库中存储空值,默认值是 False.
 
blank
    # 如果为True,该字段允许不填。默认为False。
    # 这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
    # 如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。

default 
    # 字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用
    # 如果字段没有设置可以为空,将来如果后添加一个字段,这个字段就要给一个default值
 
primary_key
    # 如果为True,那么这个字段就是模型的主键。
    # 如果没有指定任何一个字段的primary_key=True,Django会自动添加一个IntegerField字段做为主键
    #     所以除非想覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key=True。
 
unique 
    # 如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
 
choices
    # 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项
    # 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,
    #    而且这个选择框的选项就是choices 中的选项
    
db_index
  # 如果db_index=True 则代表着为此字段设置数据库索引

DatetimeFieldDateFieldTimeField 这个三个时间字段,都可以设置如下属性:
    auto_now_add
    #     配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
    # 
    
    auto_now
    #     配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间

 5.3 添加表记录

 

Django(URL、Views、Template)

上一篇:protected(C# 参考)


下一篇:条款39:明智的使用private继承