二、Python复习教程(重点)- 前端框架

笔记 同时被 3 个专栏收录
24 篇文章 3 订阅
22 篇文章 0 订阅
3 篇文章 0 订阅

目录导航:

文章目录

三、Web前端

1.1 Web前端开发介绍

1. Web网站介绍

  • 网络系统软件开发包括两种结构: C/S是客户机(client)/服务器(server) B/S是浏览器(browser)/服务器。
  • B/S最大的优点就是可以在任何地方进行操作而不用安装任何专门的软件
  • B/S架构软件的优势与劣势: 维护和升级方式简单。 成本降低,选择更多。 应用服务器运行数据负荷较重。
  • 目前比较流行的WEB技术:Python、PHP、JavaEE、Ruby与ASP.NET
  • 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。
  • HTTP是一个客户端和服务器端请求和应答的标准(TCP)。客户端是终端用户,服务器端是网站。通过使用Web浏览器、网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求。

2. 动态网站开发所需的Web构件

  • 客户端浏览器
  • Web前端
  • Web服务器
  • 服务器端编程语言
  • 数据库管理系统

3. Web的工作原理

Web的工作原理

1.2 HTML基础语法 (缺)

1.3 HTML常用标签介绍

1.3.1 文本标签:

  • <hn>...</hn> 其中n为1–6的值。 标题标签(加粗、独立行)
  • <i>...</i> 斜体
  • <em>...</em> 强调斜体
  • <b>...</b> 加粗
  • <strong>...</strong> 强调加粗
  • <cite></cite> 作品的标题(引用)
  • <sub>...</sub>下标 <sup>...</sup>上标
  • <del>...</del> 删除线

1.3.2 格式化标签:

  • <br/> 换行
  • <p>...</p> 换段
  • <hr /> 水平分割线
  • 列表:
    • <ul>...</ul> 无序列表
    • <ol>...</ol> 有序列表 其中type类型值:A a I i 1 start属性表示起始值
    • <li>...</li> 列表项
    • <dl>...</dl> 自定义列表
    • <dt>...</dt> 自定义列表头
    • <dd>...</dd> 自定义列表内容
  • <div>...</div> 常用于组合块级元素,以便通过 CSS 来对这些元素进行格式化
  • <span>...</span> 常用于包含的文本,您可以使用 CSS 对它定义样式,或者使用 JavaScript 对它进行操作。

1.3.3 图片标签img*

<img /> 在网页中插入一张图片
    属性:
        src: 图片名及url地址
        alt: 图片加载失败时的提示信息
        title:文字提示属性
        width:图片宽度
        height:图片高度
        border:边框线粗细

1.3.4 HTML中的超级链接*

<a href=" ">...</a> 超级链接标签
    属性:
        href: 必须,指的是链接跳转地址
        target: 表示链接的打开方式:
            _blank  新窗口
            _parent 父窗口
            _self   本窗口(默认)
            _top    顶级窗口
            framename 窗口名
        title:文字提示属性(详情)
锚点链接:
    定义一个锚点:<a id="a1"></a> 以前使用的是 <a name="a1"></a>
    使用锚点:    <a href="#a1">跳到a1处</a>

1.3.5 表格标签

<table>...</table>  表格标签: 属性:border width cellspacing cellpadding
<caption>...</caption> 表格标题
<tr>...</tr>  行标签
<th>...</th>  列头标签
<td>...</td>  列标签: 跨行属性rowspan  跨列属性:colspan   

<thead>...</thead>  表头
<tbody>...</tbody>  表体
<tfoot>...</tfoot>  表尾

1.3.6 form表单标签 (其中1~5重点,其他了解)

(1) <form>...</form> 表单标签

form标签常用属性:
    *action属性:提交的目标地址(URL)
    *method属性:提交方式:get(默认)和post
        get方式是URL地址栏可见,长度受限制(IE2k 火狐8k),相对不安全.
        post方式是URL地址不可见,长度不受限制,相对安全.
    enctype:提交类型
    target: 在何处打开目标 URL。
    name:属性为表单起个名字.在HTML5中使用 id 代替。

(2) <input> 表单项标签input定义输入字段,用户可在其中输入数据。在 HTML 5 中,type 属性有很多新的值。

    具体在下面有详解:
    如:<input type="text" name="username">
    *type属性:表示表单项的类型:值如下:
            text:单行文本框
            password:密码输入框
            checkbox:多选框 注意要提供value值
            radio:单选框   注意要提供value值
            file:文件上传选择框
            button:普通按钮 
            submit:提交按钮
            image:图片提交按钮
            reset:重置按钮, 还原到开始(第一次打开时)的效果
            hidden:主表单隐藏域,要是和表单一块提交的信息,但是不需要用户修改

            email 用于应该包含 e-mail 地址的输入域
            url 用于应该包含 URL 地址的输入域
            number 用于应该包含数值的输入域。
                max    规定允许的最大值
                min    规定允许的最小值
                step 规定合法的数字间隔(如果 step="3",则合法的数是 -3,0,3,6 等)
                value 规定默认值
            range 用于应该包含一定范围内数字值的输入域,显示为滑动条
                max    规定允许的最大值
                min    规定允许的最小值
                step 规定合法的数字间隔(如果 step="3",则合法的数是 -3,0,3,6 等)
                value 规定默认值
            日期选择器 Date pickers    
                date - 选取日、月、年
                month - 选取月、年
                week - 选取周和年
                time - 选取时间(小时和分钟)
                datetime - 选取时间、日、月、年(UTC 时间)
                datetime-local - 选取时间、日、月、年(本地时间)
            search    用于搜索域,比如站点搜索或 Google 搜索
            color 颜色选择

        *name属性: 表单项名,用于存储内容值的
        *value属性: 输入的值(默认指定值)
        *placeholder: 预期值的简短的提示信息
        size属性: 输入框的宽度值
        maxlength属性: 输入框的输入内容的最大长度
        readonly属性: 对输入框只读属性
        *disabled属性: 禁用属性
        *checked属性: 对选择框指定默认选项
        accesskey属性: 指定快捷键(不常用) (IE:alt+键  火狐:alt+shift+键)
        tabindex属性: 通过数字指定tab键的切换顺序(不常用)

        src和alt是为图片按钮设置的

        注意:reset重置按钮是将表单数据恢复到第一次打开时的状态,并不是清空
            image图片按钮,默认具有提交表单功能。

(3) <select>...</select> 标签创建下拉列表。

    name属性:定义名称,用于存储下拉值的
    size:定义菜单中可见项目的数目,html5不支持
    disabled 当该属性为 true 时,会禁用该菜单。 
    multiple 多选
    <option>... </option>  下拉选择项标签,用于嵌入到<select>标签中使用的;
        *value属性:下拉项的值
        *selected属性:默认下拉指定项.

(4) <textarea>...</textarea> 多行的文本输入区域

    name :定义名称,用于存储文本区域中的值。
    cols :规定文本区内可见的列数。
    rows :规定文本区内可见的行数。
    disabled: 是否禁用
    readonly: 只读
    ...
    默认值是在两个标签之间

(5) <button>...</button> 标签定义按钮。

您可以在 button 元素中放置内容,比如文档或图像。这是该元素与由 input 元素创建的按钮的不同之处。

(6) <fieldset> --fieldset 元素可将表单内的相关元素分组。

    disabled属性:定义 fieldset 是否可见。
    form属性: 定义该 fieldset 所属的一个或多个表单。

(7) <legend></legend> – 标签为 <fieldset><figure> 以及 <details> 元素定义标题。

<form>
  <fieldset>
    <legend>个人信息:</legend>
    姓名:<input type="text" /><br/>
    年龄:<input type="text" /><br/>
  </fieldset>
  <br/><br/>
  <fieldset>
    <legend>健康信息:</legend>
    身高:<input type="text" /><br/>
    体重:<input type="text" /><br/>
  </fieldset>
</form>

(8) <optgroup> html5标签–<optgroup> 标签定义选项组。此元素允许您组合选项

城市:
<select name="city">
    <optgroup label="河北省">
          <option>石家庄</option>
          <option>保定</option>
          <option>廊坊</option>
    </optgroup>
    <optgroup label="河南省">
          <option>郑州</option>
          <option>安阳</option>
          <option>周口</option>
    </optgroup>
</select>

(9) <datalist> html5标签–<datalist>标签定义可选数据的列表。与 input 元素配合使用,就可以制作出输入值的下拉列表。

<form action="demo_form.php" method="get">
    搜索:
    <input type="search" list="namelist" name="keywords"/>
    <datalist id="namelist">
        <option value="zhangsan">
        <option value="zhangsanfeng">
        <option value="zhangwuji">
        <option value="lisi">
        <option value="lixiaolong">
    </datalist>
</form>

1.3.7 <iframe></iframe> 行内框架

属性:src:规定在 iframe 中显示的文档的 URL
      name:规定 iframe 的名称
      height:规定 iframe 的高度。
      width:定义 iframe 的宽度。
      frameborder:规定是否显示框架周围的边框。

例如:<iframe src="1.html" name="myframe" width="700" height="500"></iframe>

1.3.8 多媒体标签(了解)

<audio src="./images/beidahuang.mp3" controls="controls">
    你的浏览器不支持播放
</audio>
<br/>
<audio controls="controls">
    <source src="./images/beidahuang.mp3" type="audio/mpeg" />
    你的浏览器不支持播放
</audio>

<br/><br/>
<video controls="controls" width="400" height="400">
    <source src="./images/fun.mp4" type="video/mp4" />
    <source src="movie.webm" type="video/webm">
    你的浏览器不支持视频播放
</video>

<video  controls loop poster="tiao.jpg">
    <source src="movie.webm" type="video/webm">
    <source src="movie.ogg" type="video/ogg">
    <source src="movie.mp4" type="video/mp4">
    您的破浏览器该扔了,不支持视频标签
</video>

<br/><br/>

<embed src="./images/haowan.swf" width="300" height="300" />

1.4 CSS层叠样式表介绍

1.4.1 什么是CSS?

  • CSS 指层叠样式表 (Cascading Style Sheets)
  • 样式定义如何显示控制 HTML 元素,从而实现美化HTML网页。
  • 样式通常存储在样式表中,目的也是为了解决内容与表现分离的问题
  • 外部样式表(CSS文件)可以极大提高工作效率
  • 多个样式定义可层叠为一,后者可以覆盖前者样式

1.4.2 CSS的语法:

格式: 选择器{属性:值;属性:值;属性:值;....}

选择器

  • 案例如下:其中选择器也叫选择符
p{
    color:red;
    text-align:center;
}

1.4.3 CSS中的注释:

格式: /* ... */

1.4.4 在HTML中如何使用css样式(HTML中引入CSS的方式):

(1) 内联方式(行内样式)
  • 就是在HTML的标签中使用style属性来设置css样式
  • 格式: <html标签 style="属性:值;属性:值;....">被修饰的内容</html标签>
<p style="color:blue;font-family:隶书">在HTML中如何使用css样式</p>
<!-- 特点:仅作用于本标签。-->
(2) 内部方式(内嵌样式)
  • 就是在head标签中使用<style type="text/css"></style>标签来设置css样式
<style type="text/css">
    ....css样式代码
</style>
<!-- 特点:作用于当前整个页面 -->
(3) 外部导入方式(外部链入)
  • 3.1(推荐)就是在head标签中使用标签导入一个css文件,在作用于本页面,实现css样式设置
<link href="文件名.css" type="text/css" rel="stylesheet"/>
  • 3.2 还可以使用import在style标签中导入css文件。
<style type="text/css">
    @import "style.css";
</style>
  • 特点:作用于整个网站
  • 优先级:当样式冲突时,就是采用就近原则,是值css属性离被修饰的内容最近的为主。
  • 若没有样式冲突则采用叠加效果。

1.5 CSS的常用选择符

1.5.1 css2的选择符(重要)

(1). html选择符(标签选择器)

就是把html标签作为选择符使用
如 p{....}  网页中所有p标签采用此样式
h2{....}  网页中所有h2标签采用此样式

(2). class类选择符 (使用点.将自定义名(类名)来定义的选择符)

定义:  .类名{样式....}    匿名类
其他选择符名.类名{样式....}
使用:<html标签 class="类名">...</html标签>        
.mc{color:blue;} /* 凡是class属性值为mc的都采用此样式 */
p.ps{color:green;}  /*只有p标签中class属性值为ps的才采用此样式*/
注意:类选择符可以在网页中重复使用

(3). Id选择符:

定义: #id名{样式.....}
使用:<html标签 id="id名">...</html标签>
注意:id选择符只在网页中使用一次.
  • 选择符的优先级:从大到小 [ID选择符]->[class选择符]->[html选择符]->[html属性]

(4). 关联选择符(包含选择符)

  • 格式:

    选择符1 选择符2 选择符3 ...{样式....}
    
    table a{....} /*table标签里的a标签才采用此样式*/
    h1 p{color:red} /*只有h1标签中的p标签才采用此样式*/
    

(5). 组合选择符(选择符组)

  • 格式:

    选择符1,选择符2,选择符3 ...{样式....}
    
    h3,h4,h5{color:green;} /*h3、h4和h5都采用此样式*/
    

(6). 伪类选(伪元素)择符:

  • 格式:

    标签名:伪类名{样式....}
    
    a:link {color: #FF0000; text-decoration: none}             /* 未访问的链接 */
    a:visited {color: #00FF00; text-decoration: none}          /* 已访问的链接 */
    a:hover {color: #FF00FF; text-decoration: underline}     /* 鼠标在链接上 */
    a:active {color: #0000FF; text-decoration: underline}     /* 激活链接 */
    

1.5.2 CSS3中的选择器(熟悉)

(1). 关系选择器:

div>p 选择所有作为div元素的子元素p
div+p 选择紧贴在div元素之后p元素
div~p 选择div元素后面的所有兄弟元素p

(2). 属性选择器:

[attribute]选择具有attribute属性的元素。
[attribute=value]选择具有attribute属性且属性值等于value的元素。
[attribute~=value]选择具有attribute属性且属性值为一用空格分隔的字词列表,其中一个等于value的元素。 
[attribute|=value]选择具有att属性且属性值为以val开头并用连接符"-"分隔的字符串的E元素。
[attibute^=value]匹配具有attribute属性、且值以valule开头的E元素
[attribute$=value]匹配具有attribute属性、且值以value结尾的E元素
[attribute*=value]匹配具有attribute属性、且值中含有value的E元素

(3). 结构性伪类选择器:

::first-letter设置对象内的第一个字符的样式。 
::first-line设置对象内的第一行的样式。 
:before设置在对象前(依据对象树的逻辑结构)发生的内容。
:after设置在对象后(依据对象树的逻辑结构)发生的内容。
:lang(language)匹配使用特殊语言的E元素。 
:element1~element2:
:first-of-type匹配同类型中的第一个同级兄弟元素
:last-of-type匹配同类型中的最后一个同级兄弟元素
:only-of-type匹配同类型中的唯一的一个同级兄弟元素
:only-child匹配父元素仅有的一个子元素
:nth-child(n)匹配父元素的第n个子元素
:nth-last-child(n)匹配同类型中的倒数第n个同级兄弟元素
:last-child()匹配父元素的最后一个子元素
:root匹配元素在文档的根元素。在HTML中,根元素永远是HTML 
:empty匹配没有任何子元素(包括text节点)的元素

(4). *状态伪类选择器

:link 设置超链接a在未被访问前的样式。
:visited 设置超链接a在其链接地址已被访问过时的样式
:active     设置元素在被用户激活(在鼠标点击与释放之间发生的事件)时的样式
*:hover    设置元素在其鼠标悬停时的样式
*:focus    设置元素在其获取焦点时的样式
:target    匹配相关URL指向的E元素
:enabled   匹配用户界面上处于可用状态的元素
:disabled   匹配用户界面上处于禁用状态的元素
:checked   匹配用户界面上处于选中状态的元素
:not(selector)匹配不含有selector选择符的元素
::selection  设置对象被选择时的样式

(5). 其他伪类选择器

E:not(s) : {attribute}
匹配所有不匹配简单选择符s的元素E
p:not(.bg) {background-color:#00FF00;}

1.6 CSS常用属性

1.6.1 color颜色属性:

a. HSL颜色:  通过对色调(H)、饱和度(S)、亮度(L)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色.
    background-color: hsl(240,100%,50%);color:white;
b. HSLA颜色: 色调(H)、饱和度(S)、亮度(L)、透明度(A)background-color: hsla(0,100%,50%,0.2);
*c. RGB颜色:(R)、绿(G)、蓝(B)三个颜色通道的变化
    background-color: rgba(200,100,0);
d. RGBA颜色:(R)、绿(G)、蓝(B)、透明度(A)
    background-color: rgba(0,0,0,0.5);
*e. 图片透明度的设置  img.opacity{ opacity:0.25;}
       兼容IE8 filter:alpha(opacity=100);

1.6.2 字体属性:font

font:
*font-size:         字体大小:20px,60%基于父对象的百分比取值
*font-family:    字体:宋体,Arial
 font-style:    normal正常;italic斜体; oblique倾斜的字体 
*font-weight:    字体加粗 :bold
 font-variant:    small-caps 小型的大写字母字体
 font-stretch:    [了解]文字的拉伸是相对于浏览器显示的字体的正常宽度(大部分浏览器不支持)。

1.6.3 文本属性:

 text-indent:    首行缩进:text-indent:30px;
 text-overflow:    文本的溢出是否使用省略标记(...)。clip|ellipsis(显示省略标记)
*text-align:     文本的位置:left center right
 text-transform:对象中的文本的大小写:capitalize(首字母)|uppercase大写|lowercase小写
*text-decoration: 字体画线:none无、underline下画线,line-through贯穿线
 text-decoration-line:[了解]文本装饰线条的位置(浏览器不兼容)

*text-shadow: 文本的文字是否有阴影及模糊效果
 vertical-align: 文本的垂直对齐方式
 direction:文字流方向。ltr | rtl

 white-space:nowrap; /* 强制在同一行内显示所有文本*/

*letter-spacing: 文字或字母的间距
 word-spacing:单词间距
*line-height:行高
*color: 字体颜色

1.6.4 背景属性:background

*background-color: 背景颜色
*background-image: 背景图片
*background-repeat:是否重复,如何重复?(平铺)
*background-position:定位
 background-attachment: 是否固定背景,
                scroll:默认值。背景图像是随对象内容滚动
                fixed:背景图像固定                
css3的属性:                
*background-size: 背景大小,如 background-size:100px 140px;
多层背景:
 background:url(test1.jpg) no-repeat scroll 10px 20px,url(test2.jpg) no-repeat scroll 50px 60px,url(test3.jpg) no-repeat scroll 90px 100px;
 background-origin:content-box,content-box,content-box;
 background-clip:padding-box,padding-box,padding-box;
 background-size:50px 60px,50px 60px,50px 60px;

1.6.5 *边框(盒模型):

盒子模型:

盒子模型

border:宽度 样式 颜色;
border-color;
border-style; 边框样式:solid实现,dotted点状线,dashed虚线
border-width:
border-left-color;
border-left-style;
border-left-width:
...
CSS3的样式
border-radius:圆角处理
box-shadow:    设置或检索对象阴影

1.6.6 *内补白(内补丁)

padding:        检索或设置对象四边的内部边距,如padding:10px; padding:5px 10px;
padding-top:    检索或设置对象顶边的内部边距
padding-right:    检索或设置对象右边的内部边距
padding-bottom:检索或设置对象下边的内部边距
padding-left:    检索或设置对象左边的内部边距

1.6.7 *外补白(外补丁)

margin:        检索或设置对象四边的外延边距,如 margin:10px;  margin:5px auto;
margin-top:    检索或设置对象顶边的外延边距
margin-right:    检索或设置对象右边的外延边距
margin-bottom: 检索或设置对象下边的外延边距
margin-left:    检索或设置对象左边的外延边距

1.6.8 Position定位

*position:    定位方式:absolute(绝对定位)fixed(固定)(relative定位参考,可对内部相对absolute定位)
*z-index:    层叠顺序,值越大越在上方。
*top:        检索或设置对象与其最近一个定位的父对象顶部相关的位置
 right:        检索或设置对象与其最近一个定位的父对象右边相关的位置
 bottom:        检索或设置对象与其最近一个定位的父对象下边相关的位置
*left:        检索或设置对象与其最近一个定位的父对象左边相关的位置

1.6.9. Layout布局

*display:    是否及如何显示:none隐藏,block块状显示...
*float:        指出了对象是否及如何浮动:值none | left | right
*clear:        清除浮动:none | left | right | both两侧
 visibility:设置或检索是否显示对象。visible|hidden|collapse。
            与display属性不同,此属性为隐藏的对象保留其占据的物理空间 
 clip:        检索或设置对象的可视区域。区域外的部分是透明的。 rect(上-右-下-左)
            如:clip:rect(auto 50px 20px auto);上和左不裁剪,右50,下20.
*overflow:    超出隐藏:hidden,visible:不剪切内容
 overflow-x:内容超过其指定宽度时如何管理内容: visible | hidden | scroll | auto
 overflow-y:内容超过其指定高度时如何管理内容

1.6.10 Flexible Box 弹性盒子(了解见手册)

box-orient: 设置或检索弹性盒模型对象的子元素的排列方式。horizontal(水平)|vertical(纵向)
box-pack    设置或检索弹性盒模型对象的子元素的对齐方式。
box-align    设置或检索弹性盒模型对象的子元素的对齐方式。
box-flex    设置或检索弹性盒模型对象的子元素如何分配其剩余空间。
box-flex-group    设置或检索弹性盒模型对象的子元素的所属组。
box-ordinal-group    设置或检索弹性盒模型对象的子元素的显示顺序。
box-direction    设置或检索弹性盒模型对象的子元素的排列顺序是否反转。
box-lines    设置或检索弹性盒模型对象的子元素是否可以换行显示。

1.6.11. 用户界面 User Interface

*cursor    鼠标指针采用何种系统预定义的光标形状。pointer小手,url自定义
zoom    设置或检索对象的缩放比例: normal|5倍|200%百分比
box-sizing    设置或检索对象的盒模型组成模式。content-box | border-box
            content-box: padding和border不被包含在定义的width和height之内。
            border-box: padding和border被包含在定义的width和height之内。

resize    设置或检索对象的区域是否允许用户缩放,调节元素尺寸大小。
            none: 不允许用户调整元素大小。 
            both: 用户可以调节元素的宽度和高度。 
            horizontal: 用户可以调节元素的宽度 
            vertical: 用户可以调节元素的高度。

outline     复合属性:设置或检索对象外的线条轮廓
outline-width    设置或检索对象外的线条轮廓的宽度
outline-style    设置或检索对象外的线条轮廓的样式
outline-color    设置或检索对象外的线条轮廓的颜色
outline-offset    设置或检索对象外的线条轮廓偏移位置的数值
nav-index    设置或检索对象的导航顺序。
nav-up    设置或检索对象的导航方向。
nav-right    设置或检索对象的导航方向。

1.6.12 多栏 Multi-column

columns         设置或检索对象的列数和每列的宽度
column-width     设置或检索对象每列的宽度
column-count     设置或检索对象的列数
column-gap         设置或检索对象的列与列之间的间隙
column-rule     设置或检索对象的列与列之间的边框
column-rule-width     设置或检索对象的列与列之间的边框厚度
column-rule-style     设置或检索对象的列与列之间的边框样式
column-rule-color     对象的列与列之间的边框颜色
column-span     象元素是否横跨所有列
column-fill     对象所有列的高度是否统一
column-break-before 对象之前是否断行
column-break-after     对象之后是否断行
column-break-inside 对象内部是否断行

1.6.13 表格相关属性

table-layout    设置或检索表格的布局算法    
border-collapse    设置或检索表格的行和单元格的边是合并在一起还是按照标准的HTML样式分开    separate | collapse
border-spacing    设置或检索当表格边框独立时,行和单元格的边框在横向和纵向上的间距    
caption-side    设置或检索表格的caption对象是在表格的那一边    top | right | bottom | left
empty-cell    设置或检索当表格的单元格无内容时,是否显示该单元格的边框    hide | show

1.6.14 过渡 Transition:

transition     检索或设置对象变换时的过渡效果
transition-property    检索或设置对象中的参与过渡的属性
transition-duration    检索或设置对象过渡的持续时间
transition-timing-function    检索或设置对象中过渡的类型
transition-delay    检索或设置对象延迟过渡的时间

1.6.15. 动画 Animation

animation     检索或设置对象所应用的动画特效
animation-name    检索或设置对象所应用的动画名称
animation-duration    检索或设置对象动画的持续时间
animation-timing-function    检索或设置对象动画的过渡类型
animation-delay    检索或设置对象动画延迟的时间
animation-iteration-count    检索或设置对象动画的循环次数
animation-direction    检索或设置对象动画在循环中是否反向运动
animation-play-state    检索或设置对象动画的状态
animation-fill-mode    检索或设置对象动画时间之外的状态

1.6.16. 2D变换 2D Transform:

transform     检索或设置对象的变换
transform-origin    检索或设置对象中的变换所参照的原点

1.6.17. Media Queries Properties媒体查询

width    定义输出设备中的页面可见区域宽度
height    定义输出设备中的页面可见区域高度
device-width    定义输出设备的屏幕可见宽度
device-height    定义输出设备的屏幕可见高度
orientation    定义'height'是否大于或等于'width'。值portrait代表是,landscape代表否
aspect-ratio    定义'width''height'的比率
device-aspect-ratio    定义'device-width''device-height'的比率。如常见的显示器比率:4/3, 16/9, 16/10

device-aspect-ratio    定义'device-width''device-height'的比率。如常见的显示器比率:4/3, 16/9, 16/10
color    定义每一组输出设备的彩色原件个数。如果不是彩色设备,则值等于0
color-index    定义在输出设备的彩色查询表中的条目数。如果没有使用彩色查询表,则值等于0
monochrome    定义在一个单色框架缓冲区中每像素包含的单色原件个数。如果不是单色设备,则值等于0
resolution    定义设备的分辨率。如:96dpi, 300dpi, 118dpcm
scan    定义电视类设备的扫描工序
grid    用来查询输出设备是否使用栅格或点阵。只有1和0才是有效值,1代表是,0代表否

1.7 网页布局实战

具体详见授课文档

1.8 JavaScript语言

1.8.1 JavaScript基础

(1) JavaScript介绍:

  1. 什么是JavaScript?
  2. JavaScript 是一种客户端脚本语言(脚本语言是一种轻量级的编程语言)。
  3. JavaScript 通常被直接嵌入 HTML 页面。
  4. JavaScript 是一种解释性语言(就是说,代码执行不进行预编译)。
  5. 特点:弱类型和基于对象。(因为面向对象需要具有封装、继承、多态的特征)
  6. JavaScript语言中包含三个核心:ECMAScript基本语法、DOM、BOM
  7. 在HTML中如何使用JavaScript(三种)
1. 使用<script></script>标签:
    属性:
    charset(可选)字符集设置、
    defer(可选执行顺序)值:defer、
    language(已废除)、
    src(可选)使用外部的js脚本文件
    type(必选)类型:值:text/javascript

    <script type="text/javascript">
        <!--
        javaScript语言
        //-->
    </script>

2. 在html标签的事件中,超级链接里。
    <button onclick="javaScript语言"></button>
    <a href="javascript:alert('aa');alert('bb')">点击</a>

3. 外部导入方式(推荐):
    <script type="text/javascript" src="my.js"></script>

(2) JavaScript的语法:

  1. 区分大小写:变量名、函数名、运算符以及其他一切东西都是区分大小写的。

  2. 他和Python一样属于弱类型语言。

  3. 每行结尾的分号可有可无。(js中的每条语句之间的分割符可以是回车换行也可以是";"分号(推荐))

  4. 脚本注释:// 单行注释/* 多行注释 */

  5. 括号表示代码块:{ }

  6. 变量的定义:使用var关键字来声明。

     变量的命名规范是:字母数字,$符和下划线构成,但是不可以以数字开始。
        变量名不可以使用关键字. 
    
     typeof函数获取一个变量的类型:
         * undefined - 如果变量是 Undefined 类型的
         * boolean - 如果变量是 Boolean 类型的
         * number - 如果变量是 Number 类型的 (整数、浮点数)
         * string - 如果变量是 String 类型的 (采用""''* object - 如果变量是一种引用类型或 Null 类型的 
                     如:new Array()/ new String()...
         * function -- 函数类型
    
  7. JavaScript的数据类型:

     undefined 类型 
     null 类型(对象)
     boolean 类型
     number 类型
         八进制数和十六进制数 012
         浮点数
         特殊的 Number 值
     string 类型
         var s = "hello";
         document.write(s+"<br/>");
         document.write(s[1]+"<br/>"); //使用下标可以取出对应的字符
         document.write(s.length+"<br/>");//求长度
    
     object引用类型
         引用类型通常叫做类(class),也就是说,遇到引用值,所处理的就是对象。
         Object 对象自身用处不大,不过在了解其他类之前,还是应该了解它。
         因为 ECMAScript 中的 Object 对象与 Java 中的 java.lang.Object 相似,
         ECMAScript 中的所有对象都由这个对象继承而来,Object 对象中的所有属性
         和方法都会出现在其他对象中,所以理解了 Object 对象,就可以更好地理解其他对象。
    
  8. 类型转换:

     使用:Number()、parseInt() 和parseFloat() 做类型转换
     Number()强转一个数值(包含整数和浮点数)*parseInt()强转整数,
     *parseFloat()强转浮点数
    
     函数isNaN()检测参数是否不是一个数字。 is not a number
    
     ECMAScript 中可用的 3 种强制类型转换如下:
         Boolean(value) - 把给定的值转换成 Boolean 型;
         Number(value) - 把给定的值转换成数字(可以是整数或浮点数);
         String(value) - 把给定的值转换成字符串;
    

(3) JavaScript的运算符

  1. 一元运算符

     delete:用于删除对象中属性的   如:delete o.name; //删除o对象中的name属性
     voidvoid 运算符对任何值返回 undefined。没有返回值的函数真正返回的都是 undefined。
     ++ -- : 一元加法和一元减法
    
  2. 位运算符

     位运算 NOT ~
     位运算 AND &
     位运算 OR |
     位运算 XOR ^  (不同为1,相同则为0)
     左移运算 <<
     右移运算 >>
    
  3. 逻辑运算符

     逻辑 NOT ! 运算符  非
     逻辑 AND && 运算符 与
     逻辑 OR  || 运算符 或
    
  4. 乘性运算符: *( 乘) /(除) %(取模)求余

  5. 加性运算符:

     + - 
     *其中+号具有两重意思:字串连接和数值求和。
     就是加号”+“两侧都是数值则求和,否则做字串连接
    
  6. 关系运算符: > >= < <=

  7. 等性运算符: == === != !==

  8. 条件运算符: ? : (三元运算符)

  9. 赋值运算符: = += -= *= /= %= >>= <<=

  10. 逗号运算符

    用逗号运算符可以在一条语句中执行多个运算。
    var iNum1=1, iNum2=2, iNum3=3;
    

(4) javaScript(语句流程控制)

1. 判断语句 if语句;  if... else ...    if ...  else if ... else...

2. 多分支语句: switch(){case :。。。。}
        switch (i) {
          case 20: alert("20");
            break;
          case 30: alert("30");
            break;
          case 40: alert("40");
            break;
          default: alert("other");
        }
3. 循环语句(迭代语句)
        forwhile

        do...while

        *for-in 语句: 语句是严格的迭代语句,用于枚举对象的属性。
            var a = [10,20,30,40,50];
            //迭代的是数组的下标。
            for(i in a){
               document.write(a[i]);
            }
            //输出: 1020304050

4. breakcontinue 语句对循环中的代码执行提供了更严格的控制。    

5. with 语句用于设置代码在特定对象中的作用域。

(5) 本节扩充知识:

1. 在网页文档中获取一个节点对象(HTML标签)
    document.getElementById("mid"); //获取标签id属性值为mid的节点对象

2. 定时相关函数:
    setTimeout(vCode, iMilliSeconds [, sLanguage]) -- 单次定时执行指定函数 
    clearTimeout(iTimeoutID) -- 取消上面的单次定时

    setInterval(vCode, iMilliSeconds [, sLanguage]) --无限次定时执行指定函数 
    clearInterval(iIntervalID)-- 取消上面的多次定时

本节练习:

​```
一、理论练习:
   1. 什么是JavaScript?
   2. 在HTML中嵌入JavaScript的方法有几种?
   3. JavaScript的常用类型都有哪些?
   4. 常用的JavaScript的类型转换函数有那两个?
   5. 我们使用哪个函数判断是否不是一个整数?
   6. JavaScript语言的运算符都有哪些?

二、代码题:
   1. 参考课程代码做一个简单的计算器
   2. (选做)一个倒计时的按钮(10,9,8,7,...这是是个灰色不可点击的,当为0是会换成同意字样,并可点击。)
   3. (选做) 做一个倒计时(时 分 秒)。可选带暂停效果

三、预习练习:
   1. JavaScript的函数如何定义和调用。
   2. 常用的系统函数都有哪些。
   3. 对象的应用与声明。
​```

1.8.2 JavaScript函数和对象

(1) JavaScript的函数:

标准格式: function 函数名([参数列表..]{
                函数体。。。
                [return 返回值;]
           }

JavaScript三种定义函数方法:
    *第一种是使用function语句定义函数
        如上面格式

    第二种是使用Function()构造函数来定义函数(不常用)
        var 函数名 = new Function(“参数1”,”参数2”,”参数3”……”函数体”);
        如:
        var 函数名 = new Function(”x”,”y”,var z=x+y;return z;);

    *第三种是在表达式中定义函数
        var 函数名 = function(参数1,参数2,…){函数体};
        //例如:
        //定义
            var add = function(a,b){
                return a+b;
            }
            //调用函数
            document.write(add(50,20));

    arguments 对象
            在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。
            例如,在函数 sayHi() 中,第一个参数是 message。用 arguments[0] 
            也可以访问这个值,即第一个参数的值(第一个参数位于位置 0,
            第二个参数位于位置 1,依此类推)。

     关于变量和参数问题:
        函数外面定义的变量是全局变量,函数内可以直接使用。
        在函数内部没有使用var定义的=变量则为全局变量,
        *在函数内使用var关键字定义的变量是局部变量,即出了函数外边无法获取。
        js函数定义的参数没有默认值(目前只有最新的火狐浏览器支持)

(2) 系统中常用的内置函数:

escape()    //字串编码
unescape()    //字串反编码
*eval()        //将参数字符串作为脚本代码来执行。
*isNaN()      // is not a number (不是一个数值)
*parseInt()
*parseFloat()

(3) JavaScript的对象的定义和使用

1.使用原始的方式创建内置对象
    var myObject = new Object();
    myObject.name = “lijie”;
    myObject.age = 20;
    myObject.say = function(){...}

2.直接创建自定义对象
    var 对象名 = {属性名1:属性值,属性名2:属性值2,…….}

3.使用自定义构造函数创建对象
    function pen(name,color,price){
        //对象的name属性
        this.name = name;
        //对象的color属性
        this.color = color;
        //对象的piece属性
        this.price = price;
        //对象的say方法
        this.say = function(){};
    }

    var pen = new pen(“铅笔”,”红色”,20);
    pen.say();
--------------------------------------------------------------
测试类型:
1.typeof()  //global对象的其中一个方法,typeof()
2.对象.constructor; //查看当前对象的构造函数是谁

if(arr.constructor==Array){
    alert("数组"); //数组推荐用这种方法,因为typeof得到是object
}

(4) 常用技巧函数:

HTML的标签(节点)操作:
document.write(""); //输出的
document.getElementById("id名")//获取html页面标签中,标签id属性等于此值的对象。
    如:var id = document.getElementById("hid"); //获取id值为hid的标签对象

document.getElementsByTagName("标签名"); //获取当前文档执行的标签对象

html标签对象的操作:
    标签对象.innerHTML="内容"//在标签对象内放置指定内容
    标签对象.style.css属性名="值" //改变标签对象的样式。
        示例:id.style.color="red";
        注意:属性名相当于变量名,所以css属性名中的减号要去掉,将后面的首字母大写。
            如:font-size(css)---> fontSize(JS属性)
    标签对象.value;     //获取标签对象的value值
    标签对象.value=”值“;//设置标签对象的value值                 

本节练习

​```
一、理论练习:
   1. JavaScript三种定义函数方法?
   2. arguments对象的理解?
   3. 简述JS中全局变量和局部变量的作用域?
   4. 系统中常用的内置函数有哪些?

二、代码题:
   1. 练习全选/全不选/反选的实例
   2. 做一个文件进度条的特效。
   3. 使用自定义构造函数创建对象
   4. (选做) 做一个树形菜单的点击效果

三、预习练习:
   1. JavaScript中常用内置对象都有哪些?
   2. 如何使用Date获取当前时间。
   3. 如何创建一个数组对象。
   4. 如何使用对象的基本操作for..in。
​```

1.8.3 JavaScript的内置对象

(1) for…in语句

for(var i in window){
    document.write(i+”----”+window[i]);
}
这种语句可以遍历对象中的所有属性或数组中的所有元素。

(2) with语句

如果使用with语句,就可以简化对象属性调用的层次。
    document.write(‘test1’);
    document.write(‘test2’);
    document.write(‘test3’);
可以使用with来简化:
    with(document){
        write(‘test1’);
        write(‘test2’);
        write(‘test3’);
    }

(3) JavaScript内置对象

  * Array(数组)
    var a= new Array(); //创建一个空数组
    a = new Array(10);  //创建一个数组单元为10个的数组。
    a = new Array(10,20,30);//创建一个指定数组单元的数组。

    a=['a','b','c','d']; //快捷定义数组
    常用属性:
        length--获取长度。

    常用方法:
        toString()     把数组转换为字符串,并返回结果。
        sort()     对数组的元素进行排序
        join()     把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
        pop() 删除并返回数组的最后一个元素 
        push() 向数组的末尾添加一个或更多元素,并返回新的长度。 

        。。。。。

* Boolean  布尔值包装类对象
    方法:toSource()     返回该对象的源代码。 
        toString()     把逻辑值转换为字符串,并返回结果。
        valueOf()     返回 Boolean 对象的原始值。
* Date
    var dd = new Date();

    getDate()     从 Date 对象返回一个月中的某一天 (1 ~ 31)getDay()     从 Date 对象返回一周中的某一天 (0 ~ 6)getMonth()     从 Date 对象返回月份 (0 ~ 11)getFullYear()     从 Date 对象以四位数字返回年份。 
    getYear()     请使用 getFullYear() 方法代替。 
    getHours()     返回 Date 对象的小时 (0 ~ 23)getMinutes()     返回 Date 对象的分钟 (0 ~ 59)getSeconds()     返回 Date 对象的秒数 (0 ~ 59)getMilliseconds()     返回 Date 对象的毫秒(0 ~ 999)getTime()     返回 197011 日至今的毫秒数。
    同上还有很多set方法用来设置。

* Math  对象用于执行数学任务。方法是静态的。
    abs(x)     返回数的绝对值。
    ceil(x)     对数进行上舍入。
    floor(x)     对数进行下舍入。
    random()     返回 0 ~ 1 之间的随机数。
    round(x)     把数四舍五入为最接近的整数。

    max(x,y)     返回 x 和 y 中的最高值。 
    min(x,y)     返回 x 和 y 中的最低值。

* Number
    toString();
    toFixed 把数字转换为字符串,结果的小数点后有指定位数的数字。 

* String 子串处理对象
    anchor()     创建 HTML 锚。
    *charAt()     返回在指定位置的字符。     
    charCodeAt()返回在指定的位置的字符的 Unicode 编码。
    *indexOf()     检索字符串。 
    *lastIndexOf()     从后向前搜索字符串。
    match()     找到一个或多个正在表达式的匹配。
    *replace()     替换与正则表达式匹配的子串。
    search()     检索与正则表达式相匹配的值。
    slice()     提取字符串的片断,并在新的字符串中返回被提取的部分。
    split()     把字符串分割为字符串数组。
    substr()     从起始索引号提取字符串中指定数目的字符。
    *substring()     提取字符串中两个指定的索引号之间的字符。
    toLocaleLowerCase()     把字符串转换为小写。
    toLocaleUpperCase()     把字符串转换为大写。
    *toLowerCase()     把字符串转换为小写。
    *toUpperCase()     把字符串转换为大写。
* RegExp
    exec()正则匹配
    test()
    match()
* Global
    escape(string) -- 可对字符串进行编码
    unescape(string) -- 函数可对通过 escape() 编码的字符串进行解码。
    encodeURI(URIstring) -- 函数可把字符串作为 URI 进行编码。
    decodeURI(URIstring) -- 函数可对 encodeURI() 函数编码过的 URI 进行解码。
    *eval(string) -- 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
    getClass(javaobj) -- 函数可返回一个 JavaObject 的 JavaClass。
    *isNaN(x) -- 函数用于检查其参数是否是非数字值。
    Number(object) --函数把对象的值转换为数字。
    *parseFloat(string) -- 函数可解析一个字符串,并返回一个浮点数。
    *parseInt(string, radix)

本节练习

一、理论练习:
   1. JavaScript中常用内置对象都有哪些?
   3. 如何创建一个数组对象方式有几种。

二、代码题:
   1. 做一个注册的表单验证,
   2. 实时问候:如:早上好!
   3. 给你一个日期"2013-06-01 12:24:36"的时间戳值。
   4. 显示中文的星期几。
   5. 做一个随机点名系统(点名多次,也不会重复!);

三、预习练习:
   1. JavaScript中常用事件都有哪些?
​```

1.8.4 JavaScript的事件

(1) 事件处理过程:

一、事件源: 任何一个HTML元素(节点) body, div , button p, a, h1 ....... 
二、事件: 你的操作
    鼠标:
    *    click     单击
        dblclick  双击
        contextmenu (在body) 文本菜单(鼠标右键使用) 
            要想屏蔽鼠标右键使用return false
            window.document.oncontextmenu=function(ent){...}

    *    mouseover 放上(移入)
    *    mouseout  离开(移出)
        mousedown 按下
        mouseup   抬起
    *    mousemove 移动
    键盘:
        keypress  键盘事件
        keydown   按下

    文档:(主要使用在body标签中)
    *    load   加载
        unload 关闭(为了兼容可使用下面函数)
        beforeunload 关闭之前

    表单: 
    *    focus 焦点
    *    blur  失去焦点
    *    submit 提交事件    
    *    change 改变(如下拉框选择事件)
    其它:
    *    scroll 滚动事件(常用延迟加载、瀑布流技术)
        window.onscroll=function(){
            document.documentElement.scrollTop;//获取滚动条的上距离
            document.documentElement.scrollLeft;//滚动条的左距离
        }

        selectd 事件

        。。。。

三、事件处理程序
     使用一个匿名或回调函数

(2) 三种方法加事件:

第一种: 
    格式: <tag  on事件="事件处理程序" />
*第二种:
    <script>
        对象.on事件=事件处理程序
    </script>
第三种:(火狐不兼容)
    <script for="事件源ID" event="on事件">事件处理程序</script>

(3) 事件对象:

属性:
    1. srcElement
    2. keyCode  键盘值

事件 event    window.event

  1. srcElement  代表事件源对象
  2. keyCode     事件发生时的键盘码  keypress ,  keydown keyup
  3. clientX, clientY  坐标位置
  4. screenX, screenY
  5. returnValue
  6. cancelBubble;     

//为页面添加鼠标右点击事件
window.document.oncontextmenu=function(ent){
    //兼容IE和火狐浏览器兼容
    var event=ent || window.event;
    //获取事件坐标位置
    var x=event.clientX;
    var y=event.clientY;
    ...
}

document.getElementById("one").offsetHeight; //获取one对应对象的高度
    obj.offsetTop 指 obj 距离上方或上层控件的位置,整型,单位像素。
    obj.offsetLeft 指 obj 距离左方或上层控件的位置,整型,单位像素。
    obj.offsetWidth 指 obj 控件自身的宽度,整型,单位像素。
    obj.offsetHeight 指 obj 控件自身的高度,整型,单位像素。

document.all ? 'IE' : 'others':在IE下document.all值为1,而其他浏览器下的值为0

本节练习:

​```
练习: 1. 完善注册的表单验证提示,
      2. 横向的菜单特效
      3. 为图片轮换播放添加按钮
      5.(选做)滚动图片替换
      6.(选做)键盘事件的处理(通过键盘事件移动图层)

预习:1.JavaScript中的其他事件:(滚动事件,键盘事件。。)
     2.常用的BOM都有哪些?
     3.HTML中的DOM都有哪些?
​```

1.8.5 JavaScript的BOM

<button onclick="window.location=''">跳转</button>
1. window对象
    常用的属性:
        *document :对 Document 对象的只读引用
        *history    :对 History 对象的只读引用。
        *location:用于窗口或框架的 Location 对象 
        Navigator: 对 Navigator 对象的只读引用 
        *parent: 返回父窗口。 
        length: 设置或返回窗口中的框架数量。 
        Screen: 对 Screen 对象的只读引用 
        status: 设置窗口状态栏的文本。 
        top: 返回最顶层的先辈窗口。 

    常用方法:
        alert() 显示带有一段消息和一个确认按钮的警告框。 
        confirm() 显示带有一段消息以及确认按钮和取消按钮的对话框。
        prompt() 显示可提示用户输入的对话框。

        close() 关闭浏览器窗口。            
        open() 打开一个新的浏览器窗口或查找一个已命名的窗口。 
        scrollTo() 把内容滚动到指定的坐标。 

        setTimeout() 在指定的毫秒数后调用函数或计算表达式。 
        clearTimeout() 取消由 setTimeout() 方法设置的 timeout。 
        setInterval() 按照指定的周期(以毫秒计)来调用函数或计算表达式。 
        clearInterval() 取消由 setInterval() 设置的 timeout。 

2. Navigator 对象
        Navigator 对象包含的属性描述了正在使用的浏览器。可以使用这些属性进行平台专用的配置。
    常用属性:
        with(document) {
             write ("你的浏览器信息:<ul>");
             write ("<li>代码:"+navigator.appCodeName+"</li>");
             write ("<li>名称:"+navigator.appName+"</li>");
             write ("<li>版本:"+navigator.appVersion+"</li>");
             write ("<li>语言:"+navigator.language+"</li>");
             write ("<li>编译平台:"+navigator.platform+"</li>");
             write ("<li>用户表头:"+navigator.userAgent+"</li>");
             write ("</ul>");
        }


3. Screen 对象包含有关客户端显示屏幕的信息。

    常用属性:
        document.write( "屏幕宽度:"+screen.width+"px<br />" );
        document.write( "屏幕高度:"+screen.height+"px<br />" );
        document.write( "屏幕可用宽度:"+screen.availWidth+"px<br />" );
        document.write( "屏幕可用高度:"+screen.availHeight+"px" );

    参考了解其他属性信息获取方式
        网页可见区域宽: document.body.clientWidth
        网页可见区域高: document.body.clientHeight
        网页可见区域宽: document.body.offsetWidth (包括边线的宽)
        网页可见区域高: document.body.offsetHeight (包括边线的高)
        网页正文全文宽: document.body.scrollWidth
        网页正文全文高: document.body.scrollHeight
        网页被卷去的高: document.body.scrollTop
        网页被卷去的左: document.body.scrollLeft
        网页正文部分上: window.screenTop
        网页正文部分左: window.screenLeft
        屏幕分辨率的高: window.screen.height
        屏幕分辨率的宽: window.screen.width
        屏幕可用工作区高度: window.screen.availHeight
        屏幕可用工作区宽度: window.screen.availWidth

4. History 对象包含用户(在浏览器窗口中)访问过的 URL5. Location 对象包含有关当前 URL 的信息。


//获取页面中第二form表单中,一个username输入框的值(7种方式)
    //alert(document.forms[1].username.value);
    alert(document.myform.username.value);
    //alert(document.forms.myform.username.value);
    //alert(document.forms.item(1).username.value);
    //alert(document.forms['myform'].username.value);
    //alert(document['myform'].username.value);
    //alert(document.forms.item('myform').username.value); //火狐不兼容

1.8.6 讲解HTML DOM

(1)基本概念

HTML DOM 定义了访问和操作HTML文档的标准方法。
HTML DOMHTML 文档呈现为带有元素、属性和文本的树结构(节点树)。
DOM 被分为不同的部分:
  1.Core DOM 
    定义了一套标准的针对任何结构化文档的对象 
  2.XML DOM 
    定义了一套标准的针对 XML 文档的对象 
  3.HTML DOM 
    定义了一套标准的针对 HTML 文档的对象。 

节点:根据 DOMHTML 文档中的每个成分都是一个节点。
  DOM 是这样规定的:
    >整个文档是一个文档节点 
    >每个 HTML 标签是一个元素节点 
    >包含在 HTML 元素中的文本是文本节点 
    >每一个 HTML 属性是一个属性节点 
    >注释属于注释节点 

节点彼此间都存在关系。
    >除文档节点之外的每个节点都有父节点。
    >大部分元素节点都有子节点。
    >当节点分享同一个父节点时,它们就是同辈(同级节点)。
    >节点也可以拥有后代,后代指某个节点的所有子节点,或者这些子节点的子节点
    >节点也可以拥有先辈。先辈是某个节点的父节点,或者父节点的父节点

查找并访问节点
  你可通过若干种方法来查找您希望操作的元素:
    >通过使用 getElementById()getElementsByTagName() 方法 
    >通过使用一个元素节点的 parentNode、firstChild 以及 lastChild childNodes属性 
    > nextSibling返回节点之后紧跟的同级节点。/ previousSibling返回节点之前紧跟的同级节点。

节点信息
  每个节点都拥有包含着关于节点某些信息的属性。这些属性是:
    nodeName(节点名称) 
    nodeValue(节点值) 
    nodeType(节点类型)

nodeName 属性含有某个节点的名称。
    元素节点的 nodeName 是标签名称 
    属性节点的 nodeName 是属性名称 
    文本节点的 nodeName 永远是 #text 
    文档节点的 nodeName 永远是 #document 

(2) HTML DOM 对象参考

Document: 代表整个 HTML 文档,可被用来访问页面中的所有元素 
    常用集合属性:forms
Anchor     : 代表 <a> 元素 
Area     : 代表图像映射中的 <area> 元素 
Base     : 代表 <base> 元素 
Body     : 代表 <body> 元素 
Button     : 代表 <button> 元素 
Event     : 代表某个事件的状态 
Form     : 代表 <form> 元素 
Frame     : 代表 <frame> 元素 
Frameset: 代表 <frameset> 元素 
Iframe     : 代表 <iframe> 元素 
Image     : 代表 <img> 元素 
Input button     : 代表 HTML 表单中的一个按钮 
Input checkbox     : 代表 HTML 表单中的复选框 
Input file         : 代表 HTML 表单中的文件上传 
Input hidden     : 代表 HTML 表单中的隐藏域 
Input password  : 代表 HTML 表单中的密码域 
Input radio     : 代表 HTML 表单中的单选按钮 
Input reset     : 代表 HTML 表单中的重置按钮 
Input submit     : 代表 HTML 表单中的确认按钮 
Input text         : 代表 HTML 表单中的文本输入域(文本框) 
Link     : 代表 <link> 元素 
Meta     : 代表 <meta> 元素 
Object  : 代表 <Object> 元素 
Option  : 代表 <option> 元素 
Select     : 代表 HTML 表单中的选择列表 
Style     : 代表单独的样式声明 
Table     : 代表 <table> 元素 
TableData : 代表 <td> 元素 
TableRow  : 代表 <tr> 元素 
Textarea  : 代表 <textarea> 元素 

1.8.7 继续讲解DOM(重点讲XML DOM)

(1) HTML的DOM

Object  : 代表 <Object> 元素 
Option  : 代表 <option> 元素 
Select     : 代表 HTML 表单中的选择列表 
Style     : 代表单独的样式声明 
Table     : 代表 <table> 元素 
TableData : 代表 <td> 元素 
TableRow  : 代表 <tr> 元素 
Textarea  : 代表 <textarea> 元素 

(2) XML的DOM

DOM (Document Object Model) 文档对象模型
1. document 文档  HTML XML 文件 (标记语言)
 <body>
    <div>
        <!--  -->
        <a href="#">wwww</a>
    </div>
 </body>
 节点:
    将文档想成一个倒树, 每一个部分(根、元素、文本(内容), 属性, 注释)都是一节点。
    根据 DOMHTML 文档中的每个成分都是一个节点。

    DOM 是这样规定的:
        1. 整个文档是一个文档节点(根节点) 
        2. 每个 HTML 标签是一个元素节点 
        3. 包含在 HTML 元素中的文本是文本节点 
        4. 每一个 HTML 属性是一个属性节点 
        5. 注释属于注释节点 

2. 父、子和同级节点
    节点树中的节点彼此之间都有等级关系。

    父、子和同级节点用于描述这种关系。父节点拥有子节点,位于相同层级上的子节点称为同级节点(兄弟或姐妹)。
        1. 在节点树中,顶端的节点成为根节点 
        2. 根节点之外的每个节点都有一个父节点 
        3. 节点可以有任何数量的子节点 
        4. 叶子是没有子节点的节点 
        5. 同级节点是拥有相同父节点的节点 

    只要知道一个节点, 按关系找到其它节点
        父节点:   parentNode
        子节点(第一个, 最后一个) childNodes    firstChild   lastChild
        同胞(同辈)节点 (上一个, 下一个)nextSibling   previousSibling

3。 获取节点的方式:
    array  getElementsByTagName("节点名"); //获取所对应节点名(所有),返回的是数组
    object getElementById("id名"); //获取id名的唯一节点对象

    示例:(找节点)
        document.getElementsByTagName("li"); //所有所有li节点
        document.getElementById("lid"); //获取id值为lid的唯一节点
        document.getElementById("uid").getElementsByTagName("li"); 
        //获取id值为uid中所有li子节点
        document.getElementsByTagName("ul")[0].getElementsByTagName("li"); 
        //获取第一个ul节点中所有li子节点

    获取到的标记名(多个)、 id(唯一)、 name(多个)

4. 每个节点中的内容
        节点类型nodeType、节点名nodeName,节点值nodeValue 

    节点名nodeName:
        nodeName 是只读的 
        元素节点的 nodeName 与标签名相同 
        属性节点的 nodeName 是属性的名称 
        文本节点的 nodeName 永远是 #text 
        文档节点的 nodeName 永远是 #document 

    节点值nodeValue 
        元素节点的 nodeValue 是 undefined 
        文本节点的 nodeValue 是文本自身 
        属性节点的 nodeValue 是属性的值 

    nodeType(节点类型)
         元素类型        节点类型
            元素            1
            属性            2
            文本            3
            注释            8
            文档            9


 4. Object 对象 (HTML元素 转成的对象(js对象))
注意: 如果使用js操作HTML文档, 就需要选将HTML文档结构转成Js对象
    a. 操作属性: 
        nodeName(节点名称) 
        nodeValue(节点值) 
        nodeType(节点类型)
        其他属性:(针对于节点)
            childNodes 返回节点到子节点的节点列表。
            firstChild 返回节点的首个子节点。
            lastChild 返回节点的最后一个子节点。
            nextSibling 返回节点之后紧跟的同级节点。
            previousSibling 属性可返回某节点之前紧跟的节点(处于同一树层级)                
            parentNode 返回节点的父节点。 
            textContent设置或返回节点及其后代的文本内容。

    b. 操作内容
        innerText(IE) textContent(FF) //获取的是显示的内容,不包含HTML标签
        innerHTML //获取的是显示的内容,会包含HTML
        outerText
        outerHTML
        表单
           value
    c. 操作样式
        aobj.style.backgroundColor="red";
        aobj.style.fontSize="3cm";
        className
        aobj.className="test";
        aobj.className+=" demo";
        aobj.className="";
    e. 操作节点:
        appendChild()     向节点的子节点列表的结尾添加新的子节点。
        cloneNode()        复制节点。
        removeChild()    删除(并返回)当前节点的指定子节点。
        replaceChild()     用新节点替换一个子节点。
        hasAttributes() 判断当前节点是否拥有属性。  
        hasChildNodes() 判断当前节点是否拥有子节点。 
        insertBefore()  在指定的子节点前插入新的子节点。

    f. 创建节点:
        * createElement() 创建元素节点 
          createAttribute() 来创建属性节点  可以:元素节点.属性名=值;
          createTextNode() 来创建新的文本节点 可以:元素节点.innerHTML=文本内容;

    有了以上三点的操作之前先转成对象
    转成对象的两种形式:
     1.  标记名(多个)、 id(唯一)、 name(多个)
         document中的三个方法
        var objs=document.getElementsByTagName("div"); //获取多个
        var objs=document.getElementById("one");    //获取一个
        var objs=document.getElementsByName("two");

1.8.8 Ajax

(1) JavaScript版的Ajax实现步骤:

  var xmlhttp;

 1. 创建请求对象
    if(window.XMLHttpRequest){
        // code for IE7+, Firefox, Chrome, Opera, Safari
        xmlhttp=new XMLHttpRequest();
    }else{
        // code for IE6, IE5
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }

 2. 设置回调函数(监听)
    xmlhttp.onreadystatechange=函数名;
    或
    xmlhttp.onreadystatechange=function(){
        函数体。。。
    }

 3. 初始化:
    xmlhttp.open("GET","gethint.php?q="+str,true); //异步以get方式发送到gethint.php

 4. 发送:
    xmlhttp.send();

(2) xmlhttp请求对象:

属性:
    *readyState  //请求状态:0,1,2,3,4
    *responseText//响应内容
    responseXML //xml响应对象
    *status    //浏览器响应状态:200正常, 404 请求地址不存在 ,,
    statusText //状态内容
    *onreadystatechange //回调函数属性

方法:
    abort() //取消当前响应,关闭连接并且结束任何未决的网络活动。
    getAllResponseHeaders() //把 HTTP 响应头部作为未解析的字符串返回。
    getResponseHeader() //返回指定的 HTTP 响应头部的值
    *open()    //初始化 HTTP 请求参数
    *send() //发送 HTTP 请求,使用传递给 open() 方法的参数
    *setRequestHeader() //向一个打开但未发送的请求设置或添加一个 HTTP 请求。

模拟POST提交代码:
    xmlhttp.open("POST","ajax_test.php",true);
    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    xmlhttp.send("fname=Bill&lname=Gates");

1.9 jQuery

  • jQuery是一个快速、简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架)。
  • jQuery设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。
  • 它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。
  • jQuery的使用:
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>jQuery实例</title>
        <script type="text/javascript" src="jquery-1.8.3.min.js"></script>
        <script type="text/javascript">
           //两种使用方式:
           $(document).ready(function(){
              // 在这里写你的代码...
           });

           //简写
           $(function($) {
              // 你可以在这里继续使用$作为别名...
           });

        </script>
    </head>
    <body>
        <!--  HTML代码... -->
    </body>
</html>

学习内容如下:具体使用文档详见《jQuery手册》

#### 1.9.1 选择器
#### 1.9.2 属性
#### 1.9.3 CSS样式
#### 1.9.4 文档操作
#### 1.9.5 筛选
#### 1.9.6 事件
#### 1.9.7 效果
#### 1.9.8 Ajax

1.10 BootStrap案例实战

关于BootStrap的文档详见: https://v3.bootcss.com/

四、Django框架

2.1 Django框架介绍与安装

(1). Web开发介绍:

  • 目前Web开发属于Browser/Server模式,简称BS架构,开发语言有(Python、PHP、Java …)。

  • 基于Python的Web工作原理如下:

Web工作原理

(2). 框架介绍:

①. 什么是框架?

  • 软件框架就是为实现或完成某种软件开发时,提供了一些基础的软件产品,
  • 框架的功能类似于基础设施,提供并实现最为基础的软件架构和体系
  • 通常情况下我们依据框架来实现更为复杂的业务程序开发
  • 二个字,框架就是程序的骨架

②. 框架的优缺点

  • 可重用
  • 成熟,稳健
  • 易扩展、易维护

③. Python中常见的框架

  • 大包大揽 Django 被官方称之为完美主义者的Web框架。
  • 力求精简 web.py和Tornado
  • 新生代微框架 Flask和Bottle

④. Web框架中的一些概念

  • MVC
    • 大部分开发语言中都有MVC框架
    • MVC框架的核心思想是:解耦
    • 降低各功能模块之间的耦合性,方便变更,更容易重构代码,最大程度上实现代码的重用
    • m表示model,主要用于对数据库层的封装
    • v表示view,用于向用户展示结果
    • c表示controller,是核心,用于处理请求、获取数据、返回结果
  • MVT
    • Django是一款python的web开发框架
    • 与MVC有所不同,属于MVT框架
    • m表示model,负责与数据库交互
    • v表示view,是核心,负责接收请求、获取数据、返回结果
    • t表示template,负责呈现内容到浏览器

(3). Django框架介绍

  • Django是一个高级的Python Web框架,它鼓励快速开发和清洁,务实的设计。

  • 由经验丰富的开发人员构建,它负责Web开发的许多麻烦,因此您可以专注于编写应用程序,而无需重新创建轮子。

  • 它是免费的和开源的。

  • 被官方称之为完美主义者的Web框架。

  • Django可以更快地构建更好的Web应用程序并减少代码。

    官方网址:https://www.djangoproject.com/

① Django框架的特点:

  • 快速开发:Django的宗旨在于帮助开发人员快速从概念到完成应用程序。
  • 安全可靠:Django认真对待安全性,帮助开发人员避免许多常见的安全错误。
  • 超可伸缩性:Web上的一些最繁忙的网站利用了Django快速灵活扩展的能力。

② Django可以使用什么Python版本?

Django版本Python版本
1.82.7,3.2(直到2016年底),3.3, 3.4, 3.5
1.9, 1.102.7, 3.4, 3.5
1.112.7 , 3.4 , 3.5 , 3.6
2.03.5+
  • Django的开发版本

Django的开发版本
在这里插入图片描述

(4). Django的安装

  • 作为Python Web框架,Django需要Python,在安装Python同时需要安装pip。
在线安装Django,指定版本安装,目前1.11的最新版为1.11.11

pip install django==1.11.11  

#默认会安装:Django==1.11.11 和 pytz==2018.3 

检测当前是否安装Django及版本

python -m django --version

1.11.11

# 我们也可以先下载安装包:pip download django=1.11.11 -d ./
# 指定安装包安装:pip install Django-1.11.11-py2.py3-none-any.whl

2.2 Django的快速入门

第一步 项目的创建与运行

(1). 创建项目

如果这是你第一次使用Django,那么你必须要照顾一些初始设置。也就是说,您需要自动生成一些建立Django 项目的代码

从命令行cd到您要存储代码的目录,然后运行以下命令:

$ django-admin startproject mysite

我们来看看startproject创建的内容:

[root@localhost mysite]# tree
.
├── manage.py
└── mysite
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

关于上面自动生成的目录与文件解释如下:

  • 外部mysite/根目录只是一个项目的容器。它的名字与Django无关; 您可以将其重命名为您喜欢的任何内容。
  • manage.py:一个命令行实用程序,可以让您以各种方式与此Django项目进行交互。你可以阅读所有的细节 manage.py在Django的管理和manage.py。
  • 内部mysite/目录是您的项目的实际Python包。它的名字是您需要用来导入其中的任何内容的Python包名称(例如mysite.urls)。
  • mysite/init.py:一个空的文件,告诉Python这个目录应该被认为是一个Python包。
  • mysite/settings.py:此Django项目的设置/配置。 Django设置会告诉你所有关于设置的工作原理。
  • mysite/urls.py:该Django项目的URL声明; 您的Django动力网站的“目录”。
  • mysite/wsgi.py:WSGI兼容的Web服务器为您的项目提供服务的入口点。

(2). 运行开发服务器

我们来验证您的Django项目的作品。更改为外部mysite目录,如果您还没有,并运行以下命令:

$ python manage.py runserver

注:若当前环境中有两个python环境,可使用python3或python3.6命令来调用3.6的环境,如:
$ python3 manage.py runserver

您将在命令行中看到以下输出:

Performing system checks...

System check identified no issues (0 silenced).

You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.(注意:现在忽略关于未执行应用数据库迁移的警告)

August 07, 2017 - 15:50:53
Django version 1.11, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

以上说明已经开始使用Django的开发服务器,这是一个纯粹以Python编写的轻量级Web服务器。 我们将其与Django结合在一起,因此您可以快速开发,而无需处理配置生产服务器(如Apache),直到您准备好生产。

默认情况下,该runserver命令在端口8000的内部IP上启动开发服务器。当然也可以指定端口开启服务,如8080端口:

$ python manage.py runserver 8080

如果要更改服务器的IP,请将其与端口一起传递。例如:

$ python manage.py runserver 0:8000

注意:通过IP访问后报如下错误:

    DisallowedHost at /polls
    Invalid HTTP_HOST header: '192.168.*.*:8000'. You may need to add '192.168.*.*' to ALLOWED_HOSTS.

    HTTP_HOST标头无效:'192.168.*.*:8000'。您可能需要将“192.168.*.*”添加到ALLOWED_HOSTS
    如:ALLOWED_HOSTS = ['192.168.104.240']

(3). 创建一个应用程序

Django自带一个实用程序,可以自动生成应用程序的基本目录结构,因此您可以专注于编写代码而不是创建目录。

要创建您的应用程序,请确保您与目录位于同一目录,manage.py 并键入以下命令:

$ python manage.py startapp polls

注:若当前环境中有两个python环境,可使用python3或python3.6命令来调用3.6的环境,如:
$ python3 manage.py startapp polls

这将创建一个目录polls,其目录如下:此目录结构将容纳轮询应用程序。

[root@localhost demo]# tree mysite/
mysite/
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── polls
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

(4). 定义我们的第一个视图

我们来写第一个视图。打开文件polls/views.py 并放入以下Python代码:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

这是Django中最简单的视图。要调用视图,我们需要将其映射到一个URL - 为此,我们需要一个URLconf。

要在polls目录中创建一个URLconf,创建一个名为urls.py。您的应用目录应该如下所示:

└── polls
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    ├── urls.py
    └── views.py

在polls/urls.py文件中包含以下代码:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

下一步是将根URLconf指向polls.urls模块。 在 mysite/urls.py添加一条import用于django.conf.urls.include和插入include()的urlpatterns列表,所以你必须:

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

urlpatterns = [
    url(r'^polls/', include('polls.urls')),
    url(r'^admin/', admin.site.urls),
]

其中include()函数允许引用其他URLconfs。请注意,该include()函数的正则表达式 没有$(字符串匹配字符),而是尾部的斜杠。 每当Django遇到时 include(),它会排除与该点匹配的任何部分,并将剩余的字符串发送到随附的URLconf进行进一步处理。

背后的想法include()是使即插即用的URL变得容易。由于民意调查是在自己的URLconf(polls/urls.py)中,它们可以被放置在“/ polls /”下面,或者在“/ fun_polls /”下面,或者在“/ content / polls /”或其他路径根目录下,工作。

注:include()当您包含其他网址格式时,您应始终使用。 admin.site.urls是唯一的例外。

您现在已将index视图连接到URLconf中。让它验证它的工作,运行以下命令:

$ python manage.py runserver 0:8000

在浏览器中转到http:// localhost:8000 / polls /,您应该看到文本"Hello, world. You’re at the polls index."

url() 函数

Django url() 可以接收四个参数,分别是两个必选参数:regexview 和两个可选参数:kwargsname,接下来详细介绍这四个参数。

  • regex: 正则表达式,与之匹配的 URL 会执行对应的第二个参数 view。
  • view: 用于执行与正则表达式匹配的 URL 请求。
  • kwargs: 视图使用的字典类型的参数。
  • name: 用来反向获取 URL。

附录:

第二步 应用的创建和使用

(1). 创建一个应用程序

Django自带一个实用程序,可以自动生成应用程序的基本目录结构,因此您可以专注于编写代码而不是创建目录。

要创建您的应用程序,请确保您与目录位于同一目录,manage.py 并键入以下命令:

$ python manage.py startapp myapp

注:若当前环境中有两个python环境,可使用python3或python3.6命令来调用3.6的环境,如:
$ python3 manage.py startapp myapp

这将创建一个目录myapp,其目录如下:此目录结构将容纳轮询应用程序。

[root@localhost demo]# tree myweb/
myweb/
├── manage.py
├── myweb
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── myapp
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

(2). 编写我们的第一个视图

我们来写第一个视图。打开文件myapp/views.py 并放入以下Python代码:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the myapp index.")

这是Django中最简单的视图。要调用视图,我们需要将其映射到一个URL - 为此,我们需要一个URLconf。

要在myapp目录中创建一个URLconf,创建一个名为urls.py。您的应用目录应该如下所示:

└── myapp
    ├── admin.py
    ├── apps.py
    ├── __init__.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    ├── urls.py
    └── views.py

在myapp/urls.py文件中包含以下代码:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

下一步是将根URLconf指向myapp.urls模块。 在 myweb/urls.py添加一条import用于django.conf.urls.include和插入include()的urlpatterns列表,所以你必须:

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

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^myapp/', include('myapp.urls')),
]

其中include()函数允许引用其他URLconfs。请注意,该include()函数的正则表达式 没有$(字符串匹配字符),而是尾部的斜杠。 每当Django遇到时 include(),它会排除与该点匹配的任何部分,并将剩余的字符串发送到随附的URLconf进行进一步处理。

背后的想法include()是使即插即用的URL变得容易。由于民意调查是在自己的URLconf(myapp/urls.py)中,它们可以被放置在“/ myapp /”下面,或者在“/ fun_myapp /”下面,或者在“/ content / myapp /”或其他路径根目录下,工作。

注:include()当您包含其他网址格式时,您应始终使用。 admin.site.urls是唯一的例外。

您现在已将index视图连接到URLconf中。让它验证它的工作,运行以下命令:

$ python manage.py runserver 0:8000

在浏览器中转到http:// localhost:8000 / myapp /,您应该看到文本"Hello, world. You’re at the myapp index."

(3). 附录:url() 函数介绍

Django url() 可以接收四个参数,分别是两个必选参数:regexview 和两个可选参数:kwargsname,接下来详细介绍这四个参数。

  • regex: 正则表达式,与之匹配的 URL 会执行对应的第二个参数 view。
  • view: 用于执行与正则表达式匹配的 URL 请求。
  • kwargs: 视图使用的字典类型的参数。
  • name: 用来反向获取 URL。

第三步 项目的模型

(1). 连接MySQL数据库设置

默认情况下,配置使用SQLite。若不使用SQLite作为数据库,则需要额外的设置,例如 USER,PASSWORD和HOST必须加入。

其中ENGINE设置为数据库后端使用。内置数据库后端有:

  • ‘django.db.backends.postgresql’
  • ‘django.db.backends.mysql’
  • ‘django.db.backends.sqlite3’
  • ‘django.db.backends.oracle’

在myweb/settings.py文件中,通过DATABASES项进行数据库设置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydemo',
        'USER': 'root',
        'PASSWORD': '',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

注意:Django使用MySQL数据库需要安装PyMySQL,若已经安装请略过。

  $ pip install pymysql

打开 myweb/__init__.py,写入以下代码导入pymysql:

import pymysql
pymysql.install_as_MySQLdb()

(2). 创建模型

在我们的简单的应用程序中,去创建一个stu表信息操作的Model类。

编辑 myapp/models.py文件

from django.db import models

# Create your models here.

class Stu(models.Model):
    '''自定义Stu表对应的Model类'''
    #定义属性:默认主键自增id字段可不写
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    age = models.SmallIntegerField()
    sex = models.CharField(max_length=1)
    classid=models.CharField(max_length=8)

    # 定义默认输出格式
    def __str__(self):
        return "%d:%s:%d:%s:%s"%(self.id,self.name,self.age,self.sex,self.classid)

    # 自定义对应的表名,默认表名:myapp_stu
    class Meta:
        db_table="stu"

(3). 激活模型

要将该应用程序包括在我们的项目中,我们需要在设置中添加对其配置类的引用INSTALLED_APPS。

该 myappConfig班是在myapp/apps.py文件中,所以它的虚线路径’myapp.apps.myappConfig’。

编辑myweb/settings.py文件,并将该虚线路径添加到该INSTALLED_APPS设置。

INSTALLED_APPS  =  [ 
    'django.contrib.admin''django.contrib.auth''django.contrib.contenttypes''django.contrib.sessions''django.contrib.messages''django.contrib.staticfiles''myapp.apps.MyappConfig',  #或者直接写 myapp
]

(4). 使用(两种)

① 现在进入交互式的Python shell,并使用Django提供的免费API
C:\Users\张涛\Desktop\code\myweb>python manage.py shell
Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)]
 on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from myapp.models import Stu

>>> mod = Stu.objects
# 获取所有信息
>>> lists = mod.all()
>>> for v in lists:
...     print(v)
...
1:zhangsan:22:m:python03
2:lisi:25:w:python04
3:wangwu:20:m:python03
4:zhaoliu:19:w:python04
5:qq01:20:m:python03
6:qq02:21:w:python04
7:qq03:20:m:python05
8:uu01:21:w:python04
9:uu02:20:m:python05
10:aa:29:w:python03
11:bb:20:m:python04

# 获取单条信息
>>> mod.get(id=1)
<Stu: 1:zhangsan:22:m:python03>
>>> mod.get(id=2)
<Stu: 2:lisi:25:w:python04>
>>> mod.get(id=3)
<Stu: 3:wangwu:20:m:python03>

>>>
② 在myapp应用的视图中使用
# 文件:myapp/views.py 文件代码

from django.shortcuts import render
from django.http  import HttpResponse
from myapp.models import Stu
# Create your views here.

def index(request):
    return HttpResponse("Hello Django!")

def stu(request):
    #获取所有stu表信息
    lists = Stu.objects.all()
    print(lists)
    #获取单条学生信息
    print(Stu.objects.get(id=1))

    return HttpResponse("ok")
  • 配置stu函数的访问路由
#在myapp/urls.py文件中配置

url(r'^stu$', views.stu),

启动服务后,在浏览器中访问,在命令行终端中查看输出效果: http://localhost:8000/myapp/stu

第四步 启用网站admin管理

(1). 数据迁移

Django框架中有一个非常强大的应用功能–自动管理界面,常被Web平台管理者使用,去管理整个Web平台。

默认情况下,在settings.py配置文件中INSTALLED_APPS包含以下应用程序,这些应用程序都是由Django提供:

  • django.contrib.admin - 管理网站。你会很快使用它。
  • django.contrib.auth - 认证系统。
  • django.contrib.contenttypes - 内容类型的框架。
  • django.contrib.sessions - 会话框架
  • django.contrib.messages - 消息框架。
  • django.contrib.staticfiles - 管理静态文件的框架。

为了后续的开发,默认这些应用程序都是包含在里面的。

使用这些Django自带的应用程序,需要我们在数据库中创建一些数据表对应,然后才能使用它们。为此,请运行以下命令(数据结构迁移):

$ python manage.py migrate

其中该migrate命令查看该INSTALLED_APPS设置,并根据myweb/settings.py文件中的数据库设置和应用程序随附的数据库迁移创建任何必需的数据库表(稍后将介绍)。您会看到适用于每个迁移的消息。

执行上面命令后的输出结果
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying sessions.0001_initial... OK

# 默认情况下自动在我们的数据库中创建了10张表,具体如下:
MariaDB [mydemo]> show tables;
+----------------------------+
| Tables_in_mydemo           |
+----------------------------+
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
| stu                        |
+----------------------------+
11 rows in set (0.00 sec)

(2). 创建管理员用户

首先,我们需要创建一个可以登录管理站点的用户。运行以下命令:

    $ python manage.py createsuperuser

    # 输入您所需的用户名,然后按Enter键。
    Username: admin

    # 然后将提示您输入所需的电子邮件地址:
    Email address: admin@example.com

    # 最后一步是输入你的密码。您将被要求输入密码两次,第二次作为第一次的确认
    Password: **********
    Password (again): *********
    Superuser created successfully.

(2). 启动开发服务器

默认情况下,Django管理员站点被激活。让我们开始开发服务器并探索它。

启动开发服务器命令如下:

    $ python manage.py runserver 0:8000

现在,打开一个Web浏览器,访问地址: http://127.0.0.1:8000/admin/

(3). 设置时区和语言:

编辑myweb/settings.py配置文件:

...

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

...

(4). 将我们自定义的应用程序的加入到后台管理

但我们的自定义应用程序在哪里?并没有显示在后台管理索引页面上。

要做到这一点,打开myapp/admin.py 文件,并编辑代码如下:

from django.contrib import admin

from myapp.models import Stu

admin.site.register(Stu)

(5). 更深入设计后台管理

# 编辑myapp/models.py文件,在Stu类中添加如下信息,让后台管理显示中文字段。

class Stu(models.Model):
    '''自定义Stu表对应的Model类'''
    #定义属性:默认主键自增id字段可不写
    id = models.AutoField("学号",primary_key=True)
    name = models.CharField("姓名",max_length=16)
    age = models.SmallIntegerField("年龄")
    sex = models.CharField("性别",max_length=1)
    classid=models.CharField("班级",max_length=8)

    # 定义默认输出格式
    def __str__(self):
        return "%d:%s:%d:%s:%s"%(self.id,self.name,self.age,self.sex,self.classid)

    # 自定义对应的表名,默认表名:myapp_stu
    class Meta:
        db_table="stu"
        verbose_name = '浏览学生信息'  
        verbose_name_plural = '学生信息管理'
# 编辑myapp/admin.py 文件,实现信息管理的个性化定制

from django.contrib import admin

# Register your models here.
from myapp.models import Stu

#Stu模型的管理器(装饰器写法)
@admin.register(Stu)
class StuAdmin(admin.ModelAdmin):
    #listdisplay设置要显示在列表中的字段(id字段是Django模型的默认主键)
    list_display = ('id','name','age','sex','classid')

    #设置哪些字段可以点击进入编辑界面
    list_display_links = ('id','name')

    #list_per_page设置每页显示多少条记录,默认是100条
    list_per_page = 10

    #ordering设置默认排序字段,负号表示降序排序
    ordering = ('id',)  #-id降序

    #list_editable 设置默认可编辑字段
    #list_editable = ['age','sex','classid']

    #其他请详见手册文档说明

2.3 Django的URL路由

一个干净优雅URL方案高质量Web应用程序中的一个重要细节

Django可以让你自己设计URL,无论你想要什么,没有框架限制。

要为应用程序设计URL,您可以非正式地创建一个名为**URLconf**(URL配置)的Python模块

这个模块是纯Python代码,是一个简单的Python模式(简单的正则表达式)到Python函数(您的视图)之间的映射

(1). Django是如何处理一个请求?

当用户从Django的站点请求页面时,系统遵循以下步骤来执行的Python代码:

  1. 首先Django确定要使用的根URLconf模块,通过ROOT_URLCONF来设置,具体在settings.py配置文件中。但是如果传入 HttpRequest对象具有urlconf 属性(由中间件设置),则其值将用于替换ROOT_URLCONF设置。
  2. Django加载该Python模块并查找该变量 urlpatterns。这应该是一个Python的django.conf.urls.url()实例列表。
  3. Django按顺序运行每个URL模式,并在匹配所请求的URL的第一个URL中停止
  4. 一旦正则表达式匹配,Django将导入并调用给定的视图,这是一个简单的Python函数(或基于类的视图)。该视图通过以下参数传递:
    • 一个实例HttpRequest。
    • 如果匹配的正则表达式没有返回任何命名组,那么来自正则表达式的匹配将作为位置参数提供。
    • 关键字参数由正则表达式匹配的任何命名组组成,由可选kwargs参数中指定的任何参数覆盖 django.conf.urls.url()。
  5. 如果没有正则表达式匹配,或者在此过程中的任何一点出现异常,Django将调用适当的错误处理视图。

示例

以下是一个URLconf示例:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]

说明:

  • 要从URL捕获一个值,只需将其括起来
  • 没有必要添加一个主要的斜杠,因为每个URL都有。例如articles,不是/articles。
  • 正则中的’r’正面的每个正则表达式字符串的中是可选的,但推荐使用。它告诉Python一个字符串是“raw” - 字符串中没有任何内容应该被转义。请参阅Dive Into Python的解释。

示例请求:

  • /articles/2005/03/将匹配列表中的第三个条目。Django会调用该函数 。views.month_archive(request, ‘2005’, ‘03’)
  • /articles/2005/3/ 不符合任何网址格式,因为列表中的第三个条目需要两个数字的月份。
  • /articles/2003/将匹配列表中的第一个模式,而不是第二个模式,因为模式是按顺序测试的,第一个模式是第一个测试通过。随意利用这些命令插入特殊情况。在这里,Django会调用该函数 views.special_case_2003(request)
  • /articles/2003 将不匹配任何这些模式,因为每个模式要求URL以斜杠结尾。
  • /articles/2003/03/03/将匹配最终模式。Django会调用该函数。views.article_detail(request, ‘2003’, ‘03’, ‘03’)

注意:每个捕获的参数都作为纯Python字符串发送到视图,无论正则表达式的匹配是什么,即使[0-9]{4}只会匹配整数字符串。

通过浏览器访问服务

注意:url路由,由上而下 进行匹配,如果在上面就匹配成功,则不会向下匹配

通过浏览器访问服务
    127.0.0.1:8000/abc ==>  root url(根路由) ==> 加载子路由(myweb/urls.py)

    ==> 正则匹配访问的路径(path) =-=> 视图函数(views.index)

    ==> views.py index() 响应内容

(2). 命名组

  • 上述使用为简单实例,属于正则表达式非命名组(通过括号)捕获URL定位,并将它们作为位置参数传递给视图。
  • 在更高级的使用中,我们可以使用正则表达式命名组来捕获URL定位,并将它们作为关键字 参数传递给视图。
  • 在Python正则表达式中,正则表达式命名组的语法是(?P<name>pattern),其中命名组中的命名就是name,并且 pattern是某些匹配的模式。

实例:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

这完成了与上一个例子完全相同的事情,有一个微妙的区别:捕获的值被传递到视图函数作为关键字参数,而不是位置参数

例如:

  • 请求/articles/2005/03/调用函数 ,。views.month_archive(request, year=‘2005’, month=‘03’) 而不是 views.month_archive(request, ‘2005’, ‘03’)
  • 请求/articles/2003/03/03/调用函数 。views.article_detail(request, year=‘2003’, month=‘03’, day=‘03’)
  • 在实践中,这意味着您的URLconfs稍微更明确,更不容易出现参数命令错误 - 您可以重新排序视图的函数定义中的参数。当然,这些好处是以简洁为代价的; 一些开发人员发现命名组语法丑陋而且太冗长。
URLconf的搜索

URLconf将根据所请求的URL进行搜索,作为普通的Python字符串。这不包括GET或POST参数或域名。

例如:

  • 在请求中https://www.example.com/myapp/,URLconf将寻找myapp/。
  • 在请求中https://www.example.com/myapp/?page=3,URLconf将会查找myapp/。

URLconf不查看请求方法。换句话说,所有的请求方法(GET,POST,HEAD等)都将被路由到相同的URL功能。

指定用于视图参数的默认值

一个方便的技巧是为您的视图参数指定默认参数。下面是一个URLconf和view的例子:

在下面的示例中,两个URL模式指向相同的视图views.page- 但是第一个模式不会从URL捕获任何内容。

如果第一个模式匹配,该page()函数将使用它的默认参数num,“1”。

如果第二个模式匹配, page()将使用num正则表达式捕获的任何值。

# URLconf
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^blog/$', views.page),
    url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
]

# View (in blog/views.py)
def page(request, num="1"):
    # Output the appropriate page of blog entries, according to num.
    ...

(3). 错误处理

当Django找不到与请求的URL匹配的正则表达式时,或者异常引发时,Django将调用错误处理视图。

用于这些情况的视图由四个变量指定。它们的默认值对于大多数项目都是足够的,但通过覆盖其默认值可以进一步定制。

有关详细信息,请参阅自定义错误视图的文档。

这样的值可以在你的根URLconf中设置。在任何其他URLconf中设置这些变量将不起作用。

值必须是可调用的,或者代表视图的完整的Python导入路径的字符串,应该被调用来处理手头的错误条件。

变量是:

  • handler400- 见django.conf.urls.handler400。
  • handler403- 见django.conf.urls.handler403。
  • handler404- 见django.conf.urls.handler404。
  • handler500- 见django.conf.urls.handler500。
关于404错误
  • 404的错误页面,在模板目录中创建一个404.html的页面
  • 在配置文件中 settings.py DEBUG=False
  • 在出现404的情况时,自动寻找404页面。
  • 也可以在视图函数中 手动报出404错误,带提醒信息

在视图函数中也可以指定返回一个404

注意 Http404需要在django.http的模块中引入
 # 响应404
 raise Http404('纳尼a')

在模板中 404.html

<!DOCTYPE html>
<html>
<head>
    <title>404</title>
</head>
<body>
    <center>
        <h2>404 not found</h2>
        <h3>{ {   exception   } }</h3>
    </center>
</body>
</html>

(4). 包括其他的URLconf

在任何时候,您urlpatterns都可以“包含”其他URLconf模块。

这实质上是将一组网址“植根于”其他网址之下

例如,下面是Django网站本身的URLconf的摘录。它包含许多其他URLconf:

from django.conf.urls import include, url

urlpatterns = [
    # ... snip ...
    url(r'^community/', include('django_website.aggregator.urls')),
    url(r'^contact/', include('django_website.contact.urls')),
    # ... snip ...
]

请注意,此示例中的正则表达式没有$(字符串尾匹配字符),但包含尾部斜线。

每当Django遇到include()django.conf.urls.include())时,它会截断与该点匹配的URL的任何部分,并将剩余的字符串发送到包含的URLconf以供进一步处理。

(5). URL的反向解析

如果在视图、模板中使用硬编码的链接,在urlconf发生改变时,维护是一件非常麻烦的事情

  • 解决:在做链接时,通过指向urlconf的名称,动态生成链接地址
  • 视图:使用django.core.urlresolvers.reverse()函数
  • 模板:使用url模板标签

示例

在URLconf中

from django.conf.urls import url

from . import views

urlpatterns = [
    #...
    url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),
    #...
]

您可以使用以下模板代码获取这些:

<a href="{ %   url 'news-year-archive' 2012   % }">2012 Archive</a>
    {# Or with the year in a template context variable: #}
<ul>
    { %   for yearvar in year_list   % }
        <li><a href="{ %   url 'news-year-archive' yearvar   % }">{ {   yearvar   } } Archive</a></li>
    { %   endfor   % }
</ul>

在Python代码中:

from django.urls import reverse
from django.http import HttpResponseRedirect

def redirect_to_year(request):
    # ...
    year = 2006
    # ...
    return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))

或简写

from django.shortcuts import redirect
from django.core.urlresolvers import reverse

def index(request):
    year = 2006
    return redirect(reverse('ews-year-archive',args=(year,)))

2.4 Django的模型层

Model模型

模型是你的数据的唯一的、权威的信息源。它包含你所储存数据的必要字段和行为。

通常,每个模型对应数据库中唯一的一张表。

  • 每个模型都是django.db.models.Model的一个Python 子类。
  • 模型的每个属性都表示为数据库中的一个字段。
  • Django 提供一套自动生成的用于数据库访问的API;
  • 这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳

模型与数据库的关系

模型(Model)负责业务对象和数据库的关系映射(ORM)

ORM是“对象-关系-映射”的简称,主要任务是:

  1. 根据对象的类型生成表结构
  2. 将对象、列表的操作,转换为sql语句
  3. 将sql查询到的结果转换为对象、列表

为什么要用模型?

Model是MVC框架中重要的一部分,主要负责程序中用于处理数据逻辑的部分。通常模型对象负责在数据库中存取数据

它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库

配置Mysql数据库

  1. 在当前环境中安装mysql

    sudo apt-get install mysql-server
    
    sudo apt install mysql-client
    
    sudo apt install libmysqlclient-dev
    
  2. 在当前python环境中安装 pymysql

    pip3 install pymysql
    
  3. 在mysql中创建数据库

    create databases mytest default charset=utf8
    
  4. 在Django项目中配置数据库
    修改settings.py文件中的DATABASE配置项

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'mytest',#选择数据库的名,请确认你的mysql中有这个库
            'USER': 'root',
            'PASSWORD': '',
            'HOST': 'localhost',
            'PORT': '3306',
            }
    }
    
  5. 告诉Django在接下来的mysql操作中使用pymysql

    打开myweb/__init__.py,写入以下代码导入pymysql:

    import pymysql
    pymysql.install_as_MySQLdb()
    

开发流程

  1. 在models.py中定义模型类,要求继承自models.Model

    from django.db import models
    from datetime import datetime
    
    # Create your models here.
    class Users(models.Model):
     name = models.CharField(max_length=32)
     age = models.IntegerField(default=20)
     phone = models.CharField(max_length=16)
     addtime=models.DateTimeField(default=datetime.now)
    
     #class Meta:
     #    db_table = "myapp_users"  # 指定表名
    
  2. 把应用加入settings.py文件的installed_app项
    编辑myweb/settings.py文件,并将项目应用文件名添加到该INSTALLED_APPS设置。

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'myapp',
    ]
    
  3. 生成迁移文件

    python3 manage.py makemigrations
    
    django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No mo
    dule named 'MySQLdb'.
    Did you install mysqlclient or MySQL-python?
    安装上面"配置Mysql数据库"的第五步配置,或安装:pip install mysqlclient后就可以了
    
    若执行python manage.py makemigrations命令(也可能人比较皮,把migrations文件夹给删了),会提示"No changes detected." 可能有用的解决方式如下:
    
     先 python manage.py makemigrations --empty yourappname 生成一个空的initial.py
     再 python manage.py makemigrations 生成原先的model对应的migration file
    
  4. 执行迁移

    python3 manage.py migrate
    
  5. 使用模型类进行crud操作(具体详见第二小节)

①. 定义模型

  • 在模型中定义属性,会生成表中的字段
  • django根据属性的类型确定以下信息:
    • 当前选择的数据库支持字段的类型
    • 渲染管理表单时使用的默认html控件
    • 在管理站点最低限度的验证
  • django会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后,则django不会再生成默认的主键列
  • 属性命名限制
    • 不能是python的保留关键字
    • 由于django的查询方式,不允许使用连续的下划线

1. 定义属性

  • 定义属性时,需要字段类型
  • 字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models中
  • 使用方式
    1. 导入from django.db import models
    2. 通过models.Field创建字段类型的对象,赋值给属性
  • 对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False
字段类型
  • AutoField

    :一个根据实际ID自动增长的IntegerField,通常不指定

    • 如果不指定,一个主键字段将自动添加到模型中
  • BooleanField:true/false 字段,此字段的默认表单控制是CheckboxInput

  • NullBooleanField:支持null、true、false三种值

  • CharField(max_length=字符长度):字符串,默认的表单样式是 TextInput

  • TextField:大文本字段,一般超过4000使用,默认的表单控件是Textarea

  • IntegerField:整数

  • DecimalField(max_digits=None, decimal_places=None):使用python的Decimal实例表示的十进制浮点数

    • DecimalField.max_digits:位数总数
    • DecimalField.decimal_places:小数点后的数字位数
  • FloatField:用Python的float实例来表示的浮点数

  • DateField[auto_now=False, auto_now_add=False]):使用Python的datetime.date实例表示的日期

    • 参数DateField.auto_now:每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false
    • 参数DateField.auto_now_add:当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false
    • 该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,和一个“Today"的快捷按钮,包含了一个额外的invalid_date错误消息键
    • auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果
  • TimeField:使用Python的datetime.time实例表示的时间,参数同DateField

  • DateTimeField:使用Python的datetime.datetime实例表示的日期和时间,参数同DateField

  • FileField:一个上传文件的字段

  • ImageField:继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image

字段选项
  • 通过字段选项,可以实现对字段的约束
  • 在字段对象时通过关键字参数指定
  • null:如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False
  • blank:如果为True,则该字段允许为空白,默认值是 False
  • 对比:null是数据库范畴的概念,blank是表单验证证范畴的
  • db_column:字段的名称,如果未指定,则使用属性的名称
  • db_index:若值为 True, 则在表中会为此字段创建索引
  • default:默认值
  • primary_key:若为 True, 则该字段会成为模型的主键字段
  • unique:如果为 True, 这个字段在表中必须有唯一值
关系
  • 关系的类型包括
    • ForeignKey:一对多,将字段定义在多的端中
    • ManyToManyField:多对多,将字段定义在两端中
    • OneToOneField:一对一,将字段定义在任意一端中
  • 可以维护递归的关联关系,使用’self’指定,详见“自关联”
  • 用一访问多:对象.模型类小写_set
bookinfo.heroinfo_set
  • 用一访问一:对象.模型类小写
heroinfo.bookinfo
  • 访问id:对象.属性_id
heroinfo.book_id

2. 元选项

  • 在模型类中定义类Meta,用于设置元信息

  • 元信息db_table:定义数据表名称,推荐使用小写字母,

  • 数据表的默认名称:<app_name>_<model_name>

  • 例如myweb_users

  • ordering:对象的默认排序字段,获取对象的列表时使用,接收属性构成的列表

    class BookInfo(models.Model):
        ...
        class Meta():
            ordering = ['id']
    
  • 字符串前加-表示倒序,不加-表示正序

    class BookInfo(models.Model):
        ...
        class Meta():
            ordering = ['-id']
    
  • 排序会增加数据库的开销

3. 示例演示

  • 创建test2项目,并创建booktest应用,使用mysql数据库
  • 定义图书模型
class BookInfo(models.Model):
    btitle = models.CharField(max_length=32)
    bpub_date = models.DateTimeField()
    bread = models.IntegerField(default=0)
    bcommet = models.IntegerField(default=0)
    isDelete = models.BooleanField(default=False)
  • 英雄模型
class HeroInfo(models.Model):
    hname = models.CharField(max_length=32)
    hgender = models.BooleanField(default=True)
    isDelete = models.BooleanField(default=False)
    hcontent = models.CharField(max_length=100)
    hbook = models.ForeignKey('BookInfo')
  • 定义index、detail视图
  • index.html、detail.html模板
  • 配置url,能够完成图书及英雄的展示

4. 测试数据

  • 模型BookInfo的测试数据
insert into booktest_bookinfo(btitle,bpub_date,bread,bcommet,isDelete) values
('射雕英雄传','1980-5-1',12,34,0),
('天龙八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飞狐','1987-11-11',58,24,0)
  • 模型HeroInfo的测试数据
insert into booktest_heroinfo(hname,hgender,hbook_id,hcontent,isDelete) values
('郭靖',1,1,'降龙十八掌',0),
('黄蓉',0,1,'打狗棍法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙十八掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'天山六阳掌',0),
('王语嫣',0,2,'神仙姐姐',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'弹琴',0),
('岳不群',1,3,'华山剑法',0),
('东方不败',0,3,'葵花宝典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若兰',0,4,'黄衣',0),
('程灵素',0,4,'医术',0),
('袁紫衣',0,4,'六合拳',0)

②. 模型实例

1. 类的属性

  • objects:是Manager类型的对象,用于与数据库进行交互

  • 当定义模型类时没有指定管理器,则Django会为模型类提供一个名为objects的管理器

  • 支持明确指定模型类的管理器

    class BookInfo(models.Model):
      ...
      books = models.Manager()
    
  • 当为模型类指定管理器后,django不再为模型类生成名为objects的默认管理器

2. 创建对象

  • 当创建对象时,django不会对数据库进行读写操作
  • 调用save()方法才与数据库交互,将对象保存到数据库中
  • 使用关键字参数构造模型对象很麻烦,推荐使用下面的两种之式
  • 说明:init方法已经在基类models.Model中使用,在自定义模型中无法使用,

3. 实例的属性

  • DoesNotExist:在进行单个查询时,模型的对象不存在时会引发此异常,结合try/except使用

4. 实例的方法

  • __str__(self):重写object方法,此方法在将对象转换成字符串时会被调用
  • save():将模型对象保存到数据表中
  • delete():将模型对象从数据表中删除

③. 模型查询

  • 查询集表示从数据库中获取的对象集合
  • 查询集可以含有零个、一个或多个过滤器
  • 过滤器基于所给的参数限制查询的结果
  • 从Sql的角度,查询集和select语句等价,过滤器像where和limit子句
  • 接下来主要讨论如下知识点
    • 查询集
    • 字段查询:比较运算符,F对象,Q对象

1. 查询集

  • 在管理器上调用过滤器方法会返回查询集

  • 查询集经过过滤器筛选后返回新的查询集,因此可以写成链式过滤

  • 惰性执行:创建查询集不会带来任何数据库的访问,直到调用数据时,才会访问数据库

  • 何时对查询集求值:迭代,序列化,与if合用

  • 返回查询集的方法,称为过滤器

    • all()
    • filter()
    • exclude()
    • order_by()
    • values():一个对象构成一个字典,然后构成一个列表返回
  • 写法:

    filter(1=1,2=2)
    等价于
    filter(1=1).filter(2=2)
    
  • 返回单个值的方法

    • get():返回单个满足条件的对象
      • 如果未找到会引发"模型类.DoesNotExist"异常
      • 如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常
    • count():返回当前查询的总条数
    • first():返回第一个对象
    • last():返回最后一个对象
    • exists():判断查询集中是否有数据,如果有则返回True
限制查询集
  • 查询集返回列表,可以使用下标的方式进行限制,等同于sql中的limit和offset子句

  • 注意:不支持负数索引

  • 使用下标后返回一个新的查询集,不会立即执行查询

  • 如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()引发DoesNotExist异常

    #这会返回前5个对象 LIMIT 5
    Entry.objects.all()[:5]
    #这将返回第六个到第十个对象 OFFSET 5 LIMIT 5
    Entry.objects.all()[5:10]
    
查询集的缓存
  • 每个查询集都包含一个缓存来最小化对数据库的访问

  • 在新建的查询集中,缓存为空,首次对查询集求值时,会发生数据库查询,django会将查询的结果存在查询集的缓存中,并返回请求的结果,接下来对查询集求值将重用缓存的结果

  • 情况一:这构成了两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载

    print([e.title for e in Entry.objects.all()])
    print([e.title for e in Entry.objects.all()])
    
  • 情况二:两次循环使用同一个查询集,第二次使用缓存中的数据

    querylist=Entry.objects.all()
    print([e.title for e in querylist])
    print([e.title for e in querylist])
    
  • 何时查询集不会被缓存:当只对查询集的部分进行求值时会检查缓存,但是如果这部分不在缓存中,那么接下来查询返回的记录将不会被缓存,这意味着使用索引来限制查询集将不会填充缓存,如果这部分数据已经被缓存,则直接使用缓存中的数据

2. 字段查询

  • 实现where子名,作为方法filter()、exclude()、get()的参数
  • 语法:属性名称__比较运算符=值
  • 表示两个下划线,左侧是属性名称,右侧是比较类型
  • 对于外键,使用“属性名_id”表示外键的原始值
  • 转义:like语句中使用了%与,匹配数据中的%与,在过滤器中直接写,例如:filter(title__contains="%")=>where title like ‘%%%’,表示查找标题中包含%的
比较运算符
  • exact:表示判等,大小写敏感;如果没有写“ 比较运算符”,表示判等

    filter(isDelete=False)
    
  • contains:是否包含,大小写敏感

    exclude(btitle__contains='传')
    
  • startswith、endswith:以value开头或结尾,大小写敏感

    exclude(btitle__endswith='传')
    
  • isnull、isnotnull:是否为null

    filter(btitle__isnull=False)
    
  • 在前面加个i表示不区分大小写,如iexact、icontains、istarswith、iendswith

  • in:是否包含在范围内

    filter(pk__in=[1, 2, 3, 4, 5])
    
  • gt、gte、lt、lte:大于、大于等于、小于、小于等于

    filter(id__gt=3)
    
  • year、month、day、week_day、hour、minute、second:对日期间类型的属性进行运算

    filter(bpub_date__year=1980)
    filter(bpub_date__gt=date(1980, 12, 31))
    
跨关联关系的查询:处理join查询
  • 语法:模型类名 <属性名> <比较>

  • 注:可以没有__<比较>部分,表示等于,结果同inner join

  • 可返向使用,即在关联的两个模型中都可以使用

    filter(heroinfo_ _hcontent_ _contains='八')
    
聚合函数
  • 使用aggregate()函数返回聚合函数的值

  • 函数:Avg,Count,Max,Min,Sum

    from django.db.models import Max
    maxDate = list.aggregate(Max('bpub_date'))
    
  • count的一般用法:

    count = list.count()
    

④. 用户信息管理实战

Model模型的实战操作笔记

1. 创建数据库和表(若是执行表迁移,可跳过下面操作)

  • 进入MySQL数据库创建数据库:mytest

  • 进入数据库创建数据表:myapp_users

    CREATE TABLE `myapp_users` (                          
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,       
      `name` varchar(32) NOT NULL,                         
      `age` tinyint(3) unsigned NOT NULL DEFAULT '20',     
      `phone` varchar(16) DEFAULT NULL,
      `addtime` datetime(6) NOT NULL,                    
      PRIMARY KEY (`id`)                                   
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
    
  • 添加几条测试数据

2. 创建项目myweb和应用myapp

    # 创建项目框架myweb
    $ django-admin startproject myweb

    $ cd myweb

    # 在项目中创建一个myapp应用
    $ python3.6 manage.py startapp myapp

    # 创建模板目录
    $ mkdir templates
    $ mkdir templates/myapp

    $ cd ..

    $ tree myweb

    myweb
    ├── myweb
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    ├── manage.py
    ├── myapp
    │   ├── admin.py
    │   ├── apps.py
    │   ├── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    └── templates
        └── myapp

3. 执行数据库连接配置,网站配置

3.1 编辑myweb/myweb/__init__.py文件,添加Pymysql的数据库操作支持

import pymysql
pymysql.install_as_MySQLdb()

3.2 编辑myweb/myweb/settings.py文件,配置数据库连接

...
#配置自己的服务器IP地址
ALLOWED_HOSTS = ['localhost','127.0.0.1','172.16.142.129']

...
#添加自己应用
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
]
...

# 配置模板路径信息
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]


...
# 数据库连接配置
DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'mytest',
    'USER': 'root',
    'PASSWORD': '',
    'HOST': 'localhost',
    'PORT': '3306',
}
...

4. 定义Model类

4.1 编辑myweb/myapp/models.py

from django.db import models


class Users(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField(default=20)
    phone = models.CharField(max_length=16)
    addtime=models.DateTimeField(default=datetime.now)

    def __str__(self):
        return self.name+":"+self.phone

4.2 测试Model类的使用

在项目根目录下执行命令: python3 manage.py shell

[root@localhost myweb]# ls
myweb  manage.py  myapp

[root@localhost myweb]#  python3 manage.py shell
Python 3.6.1 (default, Jul 18 2017, 01:35:19) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-18)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)

>>> from myapp.models import Users

>>> Users.objects.all()
<QuerySet [<Users: 张三:12345678901>, <Users: aa:13456789023>]>

>>> s = Users.objects.get(id=1)

>>> s.id
1

>>> s.name
'张三'

>>> s.age
20

>>> s.phone
'12345678901'

>>>

5. 实现Web端访问

5.1 编辑myweb/myweb/settings.py文件.做 ALLOWED_HOSTS 主机访问配置(若第三步已做可跳过此步骤)

    #此处添加自己的IP地址
    ALLOWED_HOSTS = ['localhost','127.0.0.1','172.16.142.129']

5.2 编写项目主路由urls配置,配置对myapp应用路由的访问连接配置

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

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('myapp.urls')),
]

5.3 配置当前应用myapp的路由配置

在myapp应用目录下创建一个路由文件urls.py文件,注意此文件编码为utf-8(建议复制一个)。

编辑应用中的路由配置文件:myweb/myapp/urls.py, 内容如下:

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name="index"),
]

5.4 编辑视图文件:myweb/myapp/views.py,内容如下

#from django.shortcuts import render
from django.http import HttpResponse

from myapp.models import Users

def index(request):
    try:
        s = Users.objects.get(id=1)
        return HttpResponse(s)
    except:
        return HttpResponse("没有找到对应的信息!")

5.5 测试

项目根目录下运行 python3 manage.py sunserver 0:8000 命令,开启服务:

[root@localhost myweb]# python3.6 manage.py runserver 0:8000
Performing system checks...

System check identified no issues (0 silenced).

July 28, 2017 - 14:01:52
Django version 1.11, using settings 'myweb.settings'
Starting development server at http://0:8000/
Quit the server with CONTROL-C.

打开浏览器,在浏览其中输入网址测试:http://172.16.142.129:8000

显示结果:张三:12345678901

继续上面操作完成Web版的Users信息增 删 改 查
1. 准备模板文件,创建模板目录
  1. 在项目目录下创建templates模板目录
  2. 进入模板目录templates,在模板目录下创建应用名myapp的目录
  3. 进入myapp目录,在里面创建一个users目录
  4. 进入users目录,在里面创建文件:index.html,add.html,edit.html,menu.html,info.html

5 设置模板目录信息:编辑myweb/myweb/settings.py文件(若第三步已做可跳过此步骤)

...
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR,'templates'),],
    'APP_DIRS': True,
...
2. 配置路由信息

打开文件:myweb/myapp/urls.py路由文件,加入六条路由配置信息

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name="index"),
    url(r'^users$', views.indexUsers, name="users"), #浏览用户信息
    url(r'^users/add$', views.addUsers, name="addusers"), #加载添加用户信息表单
    url(r'^users/insert$', views.insertUsers, name="insertusers"), #执行用户信息添加
    url(r'^users/(?P<uid>[0-9]+)/del$', views.delUsers, name="delusers"), #执行用户信息删除
    url(r'^users/(?P<uid>[0-9]+)/edit$', views.editUsers, name="editusers"), #加载用户信息编辑表单
    url(r'^users/update$', views.updateUsers, name="updateusers"), #执行用户信息编辑
]
3. 编写视图文件:myweb/myapp/views.py
# 注意:需导入from django.shortcuts import render

from django.shortcuts import render
from django.http import HttpResponse

from myapp.models import Users

def index(request):
    try:
        list = Users.objects.filter(id__in=[1,3,5])
        s = ','.join([vo.name for vo in list])

        #修改(将id值为5的age值改为30)
        #ob = Users.objects.get(id=5)
        #ob.age = 30
        #ob.save()

        #删除(删除id为3的信息)  
        #ob = Users.objects.get(id=3)
        #ob.delete()

        return HttpResponse(s)
    except:
        return HttpResponse("没有找到对应的信息!")

# 浏览用户信息        
def indexUsers(request):
    # 执行数据查询,并放置到模板中
    list = Users.objects.all()
    context = {"stulist":list}
    return render(request,"myapp/users/index.html",context)

# 加载添加信息表单
def addUsers(request):  
    return render(request,"myapp/users/add.html")

# 执行信息添加操作
def insertUsers(request): 
    try:
        ob = Users()
        ob.name = request.POST['name']
        ob.age = request.POST['age']
        ob.phone = request.POST['phone']
        ob.save()
        context = {'info':'添加成功!'}
    except:
        context = {'info':'添加失败!'}
    return render(request,"myapp/users/info.html",context)

# 执行信息删除操作    
def delUsers(request,uid):  
    try:
        ob = Users.objects.get(id=uid)
        ob.delete()
        context = {'info':'删除成功!'}
    except:
        context = {'info':'删除失败!'}
    return render(request,"myapp/users/info.html",context)

# 加载信息编辑表单    
def editUsers(request,uid):  
    try:
        ob = Users.objects.get(id=uid)
        context = {'user':ob}
        return render(request,"myapp/users/edit.html",context)
    except:
        context = {'info':'没有找到要修改的信息!'}
        return render(request,"myapp/users/info.html",context)

# 执行信息编辑操作
def updateUsers(request):
    try:
        ob = Users.objects.get(id= request.POST['id'])
        ob.name = request.POST['name']
        ob.age = request.POST['age']
        ob.phone = request.POST['phone']
        #ob.addtime = datetime.now
        ob.save()
        context = {'info':'修改成功!'}
    except:
        context = {'info':'修改失败!'}
    return render(request,"myapp/users/info.html",context)
4. 编辑浏览信息视图文件

文件位置:myweb/templates/myapp/users/index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>用户信息管理</title>
        <script>
            //自定义执行信息删除提示判断,参数uu是成功的删除url地址
            function doDel(uu){
                if(confirm("确定要删除吗?")){
                    //网页跳转
                    window.location=uu;
                }
            }

        </script>
    </head>
    <body>
        <center>

            {% include 'myapp/users/menu.html' %}

            <h3>浏览用户信息</h3>
            <table width="800" border="1">
                <tr>
                    <th>id号</th>
                    <th>姓名</th>
                    <th>年龄</th>
                    <th>电话</th>
                    <th>添加时间</th>
                    <th>操作</th>
                </tr>
                {% for stu in stulist %}
                    <tr>
                        <td>{{ stu.id }}</td>
                        <td>{{ stu.name }}</td>
                        <td>{{ stu.age }}</td>
                        <td>{{ stu.phone }}</td>
                        <td>{{ stu.addtime|date:'Y-m-d H:i:s' }}</td>
                        <td>
                            <a href="{% url 'editusers' stu.id %}">编辑</a>
                            <a href="javascript:doDel('{% url 'delusers' stu.id %}');">删除</a>
                        </td>
                    </tr>
                {% endfor %}
            </table>
        </center>
    </body>
</html>
5. 编辑添加表单视图文件

文件位置:myweb/templates/myapp/users/add.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>用户信息管理</title>
    </head>
    <body>
        <center>
            {% include "myapp/users/menu.html" %}

            <h3>添加用户信息</h3>
            <form action="{% url 'insertusers' %}" method="post">
            {% csrf_token %}
            <table width="280" border="0">
               <tr>
                 <td>姓名:</td>
                 <td><input type="text" name="name"/></td>
               </tr>
               <tr>
                 <td>年龄:</td>
                 <td><input type="text" name="age"/></td>
               </tr>
               <tr>
                 <td>电话:</td>
                 <td><input type="text" name="phone"/></td>
               </tr>
               <tr>
                 <td colspan="2" align="center">
                    <input type="submit" value="添加"/>
                    <input type="reset" value="重置"/>
                 </td>
               </tr>
            </table>
            </form>
        </center>
    </body>
</html>
6. 编辑信息表单视图文件

文件位置:myweb/templates/myapp/users/edit.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>用户信息管理</title>
    </head>
    <body>
        <center>
            {% include "myapp/users/menu.html" %}
            <h3>修改用户信息</h3>
            <form action="{% url 'updateusers' %}" method="post">
            <input type="hidden" name="id" value="{{ user.id}}"/>
            {% csrf_token %}
            <table width="280" border="0">
               <tr>
                 <td>姓名:</td>
                 <td><input type="text" name="name" value="{{ user.name }}"/></td>
               </tr>
               <tr>
                 <td>年龄:</td>
                 <td><input type="text" name="age"  value="{{ user.age }}"/></td>
               </tr>
               <tr>
                 <td>电话:</td>
                 <td><input type="text" name="phone" value="{{ user.phone }}"/></td>
               </tr>
               <tr>
                 <td colspan="2" align="center">
                    <input type="submit" value="编辑"/>
                    <input type="reset" value="重置"/>
                 </td>
               </tr>
            </table>
            </form>
        </center>
    </body>
</html>
7. 编辑公共导航栏页视图文件

文件位置:myweb/templates/myapp/users/menu.html

        <h2>用户信息管理</h2>
        <a href="{% url 'users' %}">浏览用户</a> |
        <a href="{% url 'addusers' %}">添加用户</a>
        <hr/>

文件位置:myweb/templates/myapp/users/info.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>用户信息管理</title>
    </head>
    <body>
        <center>
            {% include "myapp/users/menu.html" %}

            <h3>{{ info }}</h3>

        </center>
    </body>
</html>

2.5 Django的视图层(View)

Django框架中的视图(View)是用来负责处理用户请求和返回响应的逻辑程序

视图(View)简而言之就是一个Python的函数或方法,接受处理Web请求。

视图的响应可以是网页的HTML内容,重定向或404错误,XML文档或图像。

视图的代码按惯例是放置一个名为views.py的文件中,此文件放在项目或应用程序目录中。(其实视图文件名可以自己定义)

1. 一个简单的视图

这是一个返回当前日期和时间的视图,作为HTML文档:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

2. 返回错误

# 直接返回一个404,没有去加载404的模板页面
# return HttpResponseNotFound('<h1>Page not found</h1>')

# 可以直接返回一个status状态码
# return HttpResponse(status=403)

# 返回一个404的错误页面
raise Http404("Poll does not exist")

3.关于重定向

重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置

from django.shortcuts import redirect
from django.core.urlresolvers import reverse

# redirect重定向  reverse反向解析url地址
# return redirect(reverse('userindex'))

# 执行一段js代码,用js进行重定向
# return HttpResponse('<script>alert("添加成功");location.href = "/userindex"; </script>')

# 加载一个提醒信息的跳转页面
context = {'info':'数据添加成功','u':'/userindex'}
return render(request,'info.html',context)

4. 基于类的基本视图:

示例views.py:

from django.http import HttpResponse
from django.views import View

class MyView(View):

    def get(self, request, *args, **kwargs):
        return HttpResponse('Hello, World!')

示例urls.py:

from django.urls import path

from myapp.views import MyView

urlpatterns = [
    path('mine/', MyView.as_view(), name='my-view'),
]

# 其中as_view()是接受请求并返回响应的可调用视图['get', 'post', 'put', 'patch', 'delete, 'options'.]

①. HttpResponse对象

  1. 在django.http模块中定义了HttpResponse对象的API
  2. HttpRequest对象由Django自动创建,HttpResponse对象由程序员创建
  3. 在每一个视图函数中必须返回一个HttpResponse对象,当然也可以是HttpResponse子对象

1. 不用模板,直接返回数据

from django.http import HttpResponse

def index(request):
    return HttpResponse('你好')

2. 调用模板返回数据

from django.http import HttpResponse

# 返回模板
return render(request,'user/edit.html',{'info':'你好'})

3. 子类HttpResponseRedirect

重定向,服务器端跳转
构造函数的第一个参数用来指定重定向的地址
可以简写为 redirect

from django.shortcuts import redirect
from django.core.urlresolvers import reverse

def index(request):
    return redirect(reverse('myindex')

4. 子类JsonResponse

返回json数据,一般用于异步请求
帮助用户创建JSON编码的响应
JsonResponse的默认Content-Type为application/json

from django.http import JsonResponse

def index2(requeset):
    return JsonResponse({'list': 'abc'})

5. set_cookie方法

Cookie 是由 Web 服务器保存在用户浏览器(客户端)上的小文本文件,它可以包含有关用户的信息。

服务器可以利用Cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。

Cookies最典型的应用是判定注册用户是否已经登录网站

设置cookie
 # 获取当前的 响应对象
 response = HttpResponse('cookie的设置')

 # 使用响应对象进行cookie的设置
 response.set_cookie('a','abc')

 # 返回响应对象
 return response
获取cookie
# 读取
a = request.COOKIES.get('a',None)

if a:
    return HttpResponse('cookie的读取:'+a)
else:
    return HttpResponse('cookie不存在')

②. HttpReqeust对象

  • 服务器接收到http协议的请求后,会根据报文创建HttpRequest对象
  • 视图函数的第一个参数是HttpRequest对象
  • 在django.http模块中定义了HttpRequest对象的API

1. 属性

下面除非特别说明,属性都是只读的

  • path:一个字符串,表示请求的页面的完整路径,不包含域名
  • method:一个字符串,表示请求使用的HTTP方法,常用值包括:‘GET’、‘POST’
  • encoding:一个字符串,表示提交的数据的编码方式
    • 如果为None则表示使用浏览器的默认设置,一般为utf-8
    • 这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值
  • GET:一个类似于字典的对象,包含get请求方式的所有参数
  • POST:一个类似于字典的对象,包含post请求方式的所有参数
  • FILES:一个类似于字典的对象,包含所有的上传文件
  • COOKIES:一个标准的Python字典,包含所有的cookie,键和值都为字符串
  • session:一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django 启用会话的支持时才可用,详细内容见“状态保持”

2. 方法

  • is_ajax():如果请求是通过XMLHttpRequest发起的,则返回True

③. QueryDict对象

  • 定义在django.http.QueryDict

  • request对象的属性GET、POST都是QueryDict类型的对象

  • 与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况

  • 方法get():根据键获取值

    • 只能获取键的一个值

    • 如果一个键同时拥有多个值,获取最后一个值

      dict.get('键',default)
      或简写为
      dict['键']
      
  • 方法getlist():根据键获取值

    • 将键的值以列表返回,可以获取一个键的多个值

      dict.getlist('键',default)
      

1. GET && POST

一键一值

http://127.0.0.1/get?a=1&b=2&c=3

request.GET['name']
request.GET.get('name',None)

一键多值

http://127.0.0.1/get?a=1&a=2&b=3

request.GET.getlist('name',None)

request.POST.getlist('name',None)

④. 验证码实战 (验证码)

  • 在用户注册、登录页面,为了防止暴力请求,可以加入验证码功能,如果验证码错误,则不需要继续处理,可以减轻一些服务器的压力
  • 使用验证码也是一种有效的防止crsf的方法
  • 需要安装扩展:pip install pillow
  • 验证码效果如下图:

1. 验证码视图

  • 新建viewsUtil.py,定义函数verifycode
  • 此段代码用到了PIL中的Image、ImageDraw、ImageFont模块,需要先安装Pillow(3.4.1)包,详细文档参考http://pillow.readthedocs.io/en/3.4.x/
  • Image表示画布对象
  • ImageDraw表示画笔对象
  • ImageFont表示字体对象,ubuntu的字体路径为“/usr/share/fonts/truetype/freefont”

*代码如下:

from django.http import HttpResponse
def verifycode(request):
    #引入绘图模块
    from PIL import Image, ImageDraw, ImageFont
    #引入随机函数模块
    import random
    #定义变量,用于画面的背景色、宽、高
    bgcolor = (random.randrange(20, 100), random.randrange(
        20, 100), 255)
    width = 100
    height = 25
    #创建画面对象
    im = Image.new('RGB', (width, height), bgcolor)
    #创建画笔对象
    draw = ImageDraw.Draw(im)
    #调用画笔的point()函数绘制噪点
    for i in range(0, 100):
        xy = (random.randrange(0, width), random.randrange(0, height))
        fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
        draw.point(xy, fill=fill)
    #定义验证码的备选值
    str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
    #随机选取4个值作为验证码
    rand_str = ''
    for i in range(0, 4):
        rand_str += str1[random.randrange(0, len(str1))]
    #构造字体对象
    font = ImageFont.truetype('static/msyh.ttf', 23)
    #font = ImageFont.load_default().font
    #构造字体颜色
    fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
    #绘制4个字
    draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
    draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
    draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
    draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
    #释放画笔
    del draw
    #存入session,用于做进一步验证
    request.session['verifycode'] = rand_str
    #内存文件操作
    """
    python2的为
    # 内存文件操作
    import cStringIO
    buf = cStringIO.StringIO()
    """
    # 内存文件操作-->此方法为python3的
    import io
    buf = io.BytesIO()
    #将图片保存在内存中,文件类型为png
    im.save(buf, 'png')
    #将内存中的图片数据返回给客户端,MIME类型为图片png
    return HttpResponse(buf.getvalue(), 'image/png')

2. 配置url

  • 在urls.py中定义请求验证码视图的url
from . import viewsUtil

urlpatterns = [
    url(r'^verifycode/$', viewsUtil.verifycode),
]

3. 显示验证码

  • 在模板中使用img标签,src指向验证码视图
<img id='verifycode' src="/verifycode/" alt="CheckCode"/>
  • 启动服务器,查看显示成功
  • 扩展:点击“看不清,换一个”时,可以换一个新的验证码
<script type="text/javascript" src="/static/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#verifycodeChange').css('cursor','pointer').click(function() {
            $('#verifycode').attr('src',$('#verifycode').attr('src')+1)
        });
    });
</script>
<img id='verifycode' src="/verifycode/?1" alt="CheckCode"/>
<span id='verifycodeChange'>看不清,换一个</span>
  • 为了能够实现提交功能,需要增加form和input标签
<form method='post' action='/verifycodeValid/'>
    <input type="text" name="vc">
    <img id='verifycode' src="/verifycode/?1" alt="CheckCode"/>
<span id='verifycodeChange'>看不清,换一个</span>
<br>
<input type="submit" value="提交">
</form>

4. 验证

  • 接收请求的信息,与session中的内容对比
from django.http import HttpResponse

def verifycodeValid(request):
    vc = request.POST['vc']
    if vc.upper() == request.session['verifycode']:
        return HttpResponse('ok')
    else:
        return HttpResponse('no')
  • 配置验证处理的url
urlpatterns = [
    url(r'^verifycodeValid/$', views.verifycodeValid),
]

5. 第三方

可以在网上搜索“验证码”,找到一些第三方验证码提供网站,阅读文档,使用到项目中

2.6 Django的模板层

Template模板

作为Web 框架,Django 需要一种很便利的方法以动态地生成HTML。最常见的做法是使用模板。

模板包含所需HTML 输出的静态部分,以及一些特殊的语法,描述如何将动态内容插入。

模板引擎配置

模板引擎使用该TEMPLATES设置进行配置。这是一个配置列表,每个引擎一个。

默认值为空。在 settings.py由所产生的startproject命令定义一个更有用的值:

在做下面模板配置的同时,也要在项目的根目录下创建一个templates目录

# 项目目录下的settings.py配置文件添加TEMPLATES中的DIRS配置
TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR,'templates')],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]

①. 模板语法

1.变量

  • 变量输出语法

    { {  var  } }
    
  • 当模版引擎遇到一个变量,将计算这个变量,然后将结果输出

  • 变量名必须由字母、数字、下划线(不能以下划线开头)和点组成

  • 当模版引擎遇到点("."),会按照下列顺序查询:

    • 字典查询,例如:foo[“bar”]
    • 属性或方法查询,例如:foo.bar
    • 数字索引查询,例如:foo[bar]
  • 如果变量不存在, 模版系统将插入’’ (空字符串)

  • 在模板中调用方法时不能传递参数

2.标签

  • 语法

    { %  tag  % }
    
  • 作用

    • 在输出中创建文本
    • 控制循环或逻辑
    • 加载外部信息到模板中
for 标签
{ %  for ... in ...  % }
    循环逻辑

{ %  endfor  % }
if 标签
{ %  if ...  % }
    逻辑1
{ %  elif ...  % }
    逻辑2
{ %  else  % }
    逻辑3
{ %  endif  % }
comment 标签
{ %  comment  % }
    多行注释
{ %  endcomment  % }
include 加载模板并以标签内的参数渲染
{ %  include "base/index.html"  % }
url 反向解析
{ %  url 'name' p1 p2  % }
csrf_token 这个标签用于跨站请求伪造保护
{ %  csrf_token  % }

3.过滤器

  • 语法:

    { {  变量|过滤器  } },例如{ {  name|lower  } },表示将变量name的值变为小写输出
    
  • 使用管道符号 (|)来应用过滤器

  • 通过使用过滤器来改变变量的计算结果

  • 关闭HTML自动转义

    { {  data|safe  } }
    
  • 可以在if标签中使用过滤器结合运算符

    if list1|length > 1
    
  • 过滤器能够被“串联”,构成过滤器链

    name|lower|upper
    
  • 过滤器可以传递参数,参数使用引号包起来

    list|join:", "
    
  • default:如果一个变量没有被提供,或者值为false或空,则使用默认值,否则使用变量的值

    value|default:"什么也没有"
    
  • date:根据给定格式对一个date变量格式化

    value|date:'Y-m-d'
    

4.注释

  • 单行注释
{# 注释 #}
  • 多行注释
{%  comment  %}
      多行注释
{%  endcomment  %}

5.模板运算

  • { {  value|add:10  } }
    note:value=5,则结果返回15
    
  • { {  value|add:-10  } }
    note:value=5,则结果返回-5,加一个负数就是减法了
    
  • { %  widthratio 5 1 100  % }
    note:等同于:(5 / 1) * 100 ,结果返回500,
    withratio需要三个参数,它会使用参数1/参数2*参数3的方式进行运算,进行乘法运算,使「参数2=1
    
  • { %  widthratio 5 100 1  % }
    note:等同于:(5 / 100) * 1,则结果返回0.05,和乘法一样,使「参数3= 1就是除法了。
    

6.自定义 标签 或 过滤器

  • 首先在当前应用目录下创建一个templatetags模板标签目录,建议内放一个__init__.py的空文件
  • 然后在templatetags目录下创建一个模板标签文件pagetag.py,具体代码如下:
 templatetags
    ├── pagetag.py
    ----------------pagetag.py-------------------------
    from django import template

    register = template.Library()

    # 自定义过滤器(实现大写转换)
    @register.filter
    def myupper(val):
        # print ('val from template:',val)
        return val.upper()

    # 自定义标签(实现减法计算)
    #from django.utils.html import format_html
    @register.simple_tag
    def jian(a,b):
        res = int(a) - int(b)
        return res
  • 使用:在模板文件使用 { % load pagetag % }
  <h4>6. 自定义标签 </h4>
  {% load pagetag %}
  大写:{{name|myupper}} <br/>
  相减:{% jian m1 m2 %}

②. 模板继承

  • 模板继承可以减少页面内容的重复定义,实现页面内容的重用
  • 典型应用:网站的头部、尾部是一样的,这些内容可以定义在父模板中,子模板不需要重复定义
  • block标签:在父模板中预留区域,在子模板中填充
  • extends继承:继承,写在模板文件的第一行
  • 定义父模板base.html
{ %  block block_name  % }
   这里可以定义默认值
   如果不定义默认值,则表示空字符串
{ %  endblock  % }
  • 定义子模板index.html
{ %  extends "base.html"  % }
  • 在子模板中使用block填充预留区域
{ %  block block_name  % }
实际填充内容
{ %  endblock  % }

说明

  • 如果在模版中使用extends标签,它必须是模版中的第一个标签
  • 不能在一个模版中定义多个相同名字的block标签
  • 子模版不必定义全部父模版中的blocks,如果子模版没有定义block,则使用了父模版中的默认值
  • 如果发现在模板中大量的复制内容,那就应该把内容移动到父模板中
  • 使用可以获取父模板中block的内容
  • 为了更好的可读性,可以给endblock标签一个名字
{ %  block block_name  % }
    区域内容
{ %  endblock block_name  % }

三层继承结构

  • 三层继承结构使代码得到最大程度的复用,并且使得添加内容更加简单
  • 如下图为常见的电商页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
(img-3N6H1Ul6-1603702526668)(https://edu.csdn.net/notebook/python/assets/Image 1.png)]

1.创建根级模板
  • 名称为“base.html”
  • 存放整个站点共用的内容
<!DOCTYPE html>
<html>
    <head>
        <title>{ %  block title  % }{ %  endblock  % } 水果超市</title>
    </head>
    <body>
        top--{{logo}}
        <hr/>
        { %  block left  % }

        { %  endblock  % }

        { %  block content  % }

        { %  endblock  % }
        <hr/>
        bottom
    </body>
</html>
2.创建分支模版
  • 继承自base.html
  • 名为“base_***.html”
  • 定义特定分支共用的内容
  • 定义base_goods.html
{ %  extends 'temtest/base.html'  % }

{ %  block title  % }商品{ %   endblock   % }

{ %  block left  % }
    <h1>goods left</h1>
{ %  endblock  % }
  • 定义base_user.html
{ %  extends 'temtest/base.html'  % }

{ %  block title  % }用户中心{ %  endblock   % }

{ %  block left  % }
    <font color='blue'>user left</font>
{ %  endblock  % }
  • 定义index.html,继承自base.html,不需要写left块
{ %  extends 'temtest/base.html'  % }

{ %  block content  % }
    首页内容
{ %  endblock content  % }
3.为具体页面创建模板,继承自分支模板
  • 定义商品列表页goodslist.html
{ %  extends 'temtest/base_goods.html'  % }
{ %  block content  % }
    商品正文列表
{ %  endblock content  % }
  • 定义用户密码页userpwd.html
{ %  extends 'temtest/base_user.html'  % }
{ %  block content  % }
    用户密码修改
{ %  endblock content  % }
4.视图调用具体页面,并传递模板中需要的数据
  • 首页视图index
logo='welcome to itcast'
def index(request):
    return render(request, 'temtest/index.html', {'logo': logo})
  • 商品列表视图goodslist
def goodslist(request):
    return render(request, 'temtest/goodslist.html', {'logo': logo})
  • 用户密码视图userpwd
def userpwd(request):
    return render(request, 'temtest/userpwd.html', {'logo': logo})
5.配置url
from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^list/$', views.goodslist, name='list'),
    url(r'^pwd/$', views.userpwd, name='pwd'),
]

③. Ajax应用实战

Ajax实战笔记–城市级联操作

1. 项目架构搭建

  • 1.1 创建项目tpdemo,创建应用myapp

      # 创建项目框架tpdemo
      $ django-admin startproject tpdemo
    
      $ cd tpdemo
    
      # 在项目中创建一个myapp应用
      $ python3 manage.py startapp myapp
    
      # 创建模板目录
      $ mkdir templates
      $ mkdir templates/myapp
    
      $ cd ..
    
      $ tree tpdemo
    
      tpdemo
      ├── tpdemo
      │   ├── __init__.py
      │   ├── settings.py
      │   ├── urls.py
      │   └── wsgi.py
      ├── manage.py
      ├── myapp
      │   ├── admin.py
      │   ├── apps.py
      │   ├── __init__.py
      │   ├── models.py
      │   ├── tests.py
      │   └── views.py
      └── templates
          └── mytest
    
  • 1.2 编辑tpdemo/tpdemo/settings.py文件,配置数据库连接

...
#配置自己的服务器IP地址
ALLOWED_HOSTS = ['*']

...
#添加自己应用
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
]
...

# 配置模板路径信息
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]


...
# 数据库连接配置
DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'mytest',
    'USER': 'root',
    'PASSWORD': '',
    'HOST': 'localhost',
    'PORT': '3306',
}
...
  • 1.3 编辑tpdemo/tpdemo/__init__.py文件,添加Pymysql的数据库操作支持
    import pymysql
    pymysql.install_as_MySQLdb()
  • 1.4 编写项目主路由urls配置,配置对myapp应用路由的访问连接配置: tpdemo/tpdemo/urls.py
from django.conf.urls import include,url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('myapp.urls')),
]
  • 1.5 配置当前应用myapp的路由配置
  • 在myapp应用目录下创建一个路由文件urls.py文件,注意此文件编码为utf-8(建议复制一个)。
  • 编辑应用中的路由配置文件:tpdemo/myapp/urls.py, 内容如下:
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name="index"),
]
  • 1.6 编写视图tpdemo/myapp/views.py
from django.shortcuts import render
from django.http import HttpResponse

# 网站首页
def index(request):
    return render(request,'myapp/index.html')
  • 1.7 定义模板并编写模板 tpdemo/templates/myapp/index.html
<!DOCTYPE html>
<html lang="cn">
<head>
    <meta charset="UTF-8">
    <title>Django框架案例</title>
</head>
<body>
      <h2>Django框架案例</h2>

      <h4><a href="#">1. Ajax实战笔记--城市级联操作</a></h4>
</body>
</html>
  • 1.8 启动服务,通过浏览器测试效果
[root@localhost tpdemo]# ls
tpdemo  manage.py  myapp  templates

[root@localhost tpdemo]# python3 manage.py runserver 0:8000
  • 打开浏览器输入网址:http:localhost:8000

2. 开发《城市级联信息操作》

  • 2.1 将提前准备好的district.sql信息导入到mydb数据库中

    在mydb数据库中存在一个district(城市区县信息表)

  • 2.2 编写model类:打开tpdemo/myapp/models.py文件

from django.db import models

# 自定义城市区县信息model类
class District(models.Model):
    name = models.CharField(max_length=255)
    upid = models.IntegerField()

    class Meta:
        db_table = "district"  # 指定真实表名
  • 2.3 编写子路由文件:tpdemo/myapp/urls.py
...
    # 城市级联操作
    url(r'^showdistrict$', views.showdistrict, name='showdistrict'), #加载网页
    url(r'^district/([0-9]+)$', views.district, name='district'),  #Ajax加载城市信息
...
  • 2.4 编写视图文件:tpdemo/myapp/views.py
from django.http import HttpResponse,JsonResponse

from myapp.models import District

...
# 加载城市级联信息操作模板
def showdistrict(request):
    return render(request,"myapp/district.html")

# 加载对应的城市信息,并json格式ajax方式响应
def district(request,upid):
    dlist = District.objects.filter(upid=upid)
    list = []
    for ob in dlist:
        list.append({'id':ob.id,'name':ob.name})
    return JsonResponse({'data':list})
...
  • 启动服务测试:url:http://localhost:8000/district/0 加载一级城市信息
  • 2.5 开发网页前端的准备:首先启用静态资源目录
    • 在项目的根目录下创建一个静态资源目录:static 路径:tpdemo/static
    • 并在此目录下创建一个js目录。然后将jquery文件:jquery-1.8.2.min.js放到此目录中 具体位置:tpdemo/static/js/jquery-1.8.2.min.js
    • 编辑tpdemo/tpdemo/settings.py配置文件,在最后加入代码:(配置静态资源目录)
...
STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static'),
]
  • 2.6 配置访问url:编辑tpdemo/templates/myapp/index.html
...
   <h4><a href="{% url 'showdistrict' %}">1. Ajax实战笔记--城市级联操作</a></h4> 
...
  • 2.7 定义并编写模板文件:tpdemo/templates/myapp/district.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ajax实战--城市级联操作</title>
    <script type="text/javascript" src="/static/js/jquery-1.8.2.min.js"></script>
    <script type="text/javascript">
        //编写js代码
        $(function(){
            $.ajax({
                type:'get',
                url:"{% url 'district' 0 %}",
                dataType:'json',
                async: false,
                success:function(res){
                    list = res.data;
                    //遍历响应的城市信息
                    for(var i=0;i<list.length;i++){
                        $("#cid").append("<option value='"+list[i].id+"'>"+list[i].name+"</option>");
                    }
                },
            });

            //获取最后一个下拉框并添加选中事件
            $("select").live('change',function(){
                //获取选中的id号
                var id = $(this).val();
                $(this).nextAll().remove();
                $.ajax({
                    url: "/district/"+id,
                    type: 'get',
                    data: {},
                    dataType:'json',
                    success:function(res){
                        if(res.data.length<1)
                            return;
                        var data = res.data;
                        var select = $("<select></select>")
                        for(var i=0;i<data.length;i++){
                            $('<option value="'+data[i].id+'">'+data[i].name+'</option>').appendTo(select)
                            //$('select:last').append('<option value="'+data[i].id+'">'+data[i].name+'</option>'); 
                        }
                        $("select:last").after(select);
                    }
                });
            });

        })

    </script>
</head>
<body>
    <h2>Ajax实战笔记--城市级联操作</h2>

    <select id="cid">
        <option>-请选择-</option>
    </select>
</body>
</html>

2.7 Django常用Web工具

①.文件上传 (缺)

②. 分页操作

  • Django提供了一些类实现管理数据分页,这些类位于django/core/paginator.py中

1. Paginator对象

  • Paginator(列表,int):返回分页对象,参数为列表数据,每面数据的条数
属性
  • count:对象总数
  • num_pages:页面总数
  • page_range:页码列表,从1开始,例如[1, 2, 3, 4]
方法
  • page(num):下标以1开始,如果提供的页码不存在,抛出InvalidPage异常
异常exception
  • InvalidPage:当向page()传入一个无效的页码时抛出
  • PageNotAnInteger:当向page()传入一个不是整数的值时抛出
  • EmptyPage:当向page()提供一个有效值,但是那个页面上没有任何对象时抛出

2. Page对象

创建对象
  • Paginator对象的page()方法返回Page对象,不需要手动构造
属性
  • object_list:当前页上所有对象的列表
  • number:当前页的序号,从1开始
  • paginator:当前page对象相关的Paginator对象
方法
  • has_next():如果有下一页返回True
  • has_previous():如果有上一页返回True
  • has_other_pages():如果有上一页或下一页返回True
  • next_page_number():返回下一页的页码,如果下一页不存在,抛出InvalidPage异常
  • previous_page_number():返回上一页的页码,如果上一页不存在,抛出InvalidPage异常
  • len():返回当前页面对象的个数
  • 迭代页面对象:访问当前页面中的每个对象

3. 代码示例

1. 创建项目mydemo

创建视图pagTest

from django.core.paginator import Paginator

def pagTest(request, pIndex):
    list1 = AreaInfo.objects.filter(aParent__isnull=True)
    p = Paginator(list1, 10)
    if pIndex == '':
        pIndex = '1'
    pIndex = int(pIndex)
    list2 = p.page(pIndex)
    plist = p.page_range
    return render(request, 'booktest/pagTest.html', {'list': list2, 'plist': plist, 'pIndex': pIndex})

配置url

url(r'^pag(?P<pIndex>[0-9]*)/$', views.pagTest, name='pagTest'),

定义模板pagTest.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
<ul>
{%for area in list%}
<li>{{area.id}}--{{area.atitle}}</li>
{%endfor%}
</ul>

{%for pindex in plist%}
{%if pIndex == pindex%}
{{pindex}}&nbsp;&nbsp;
{%else%}
<a href="/pag{{pindex}}/">{{pindex}}</a>&nbsp;&nbsp;
{%endif%}
{%endfor%}
</body>
</html>

③. 富文本编辑器

Django集成UEditor (封装成应用) 百度富文本编辑器

http://ueditor.baidu.com/website/

1. 使用效果

在这里插入图片描述

2. 测试环境

  • ubuntu 16.04
  • python3.5.2
  • django1.11.7
目前测试解决了出现的以下两个问题,都是python版本问题
  • error1
# name 'file' is not defined
 controller.py  68# jsonfile = file(config_path)
 jsonfile = open(config_path)
  • error2
File "/home/yc/py6/myproject-test/ueditor/controller.py", line 45, 
in buildFileName
for key, value in texts.iteritems():
AttributeError: 'dict' object has no attribute 'iteritems'

controller.py  45# for key, value in texts.iteritems():
for key, value in texts.items():

3. 配置方法

1,下载解压ueditor文件包,放置在项目中.,作为一个应用目录
myproject:
    manage.py  myproject  static     ueditor
    myadmin    myweb      templates 

uediter文件夹包括以下:
    controller.py   __init__.py   msyhbd.ttf   UE/             urls.py
    controller.pyc  __init__.pyc  __pycache__  ueconfig.json  urls.pyc
2,打开settings.py,给INSTALLED_APPS加入应用ueditor
INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'myadmin',
        'myweb',
        'ueditor',
    ]
3,检查一下settings.py是否设置好static静态目录,可参考如下设置
STATIC_URL = '/static/'
#静态目录
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)
4,打开django项目的urls.py文件,添加ueditor的url路由配置
myproject/myproject/urls.py:

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

urlpatterns = [
    url(r'^ueditor/', include('ueditor.urls')),
    url(r'^admin/',include('myadmin.urls')),
    url(r'^',include('myweb.urls')),
]
5,上面步骤配置完成之后,基本可以使用了。
ueditor配置可能需要根据你的项目具体情况修改。 
ueditor前端配置文件,在ueditor/UE/ueditor.config.js 
ueditor后端配置文件,在ueditor/ueconfig.json 具体配置可参考ueditor官网

此时可以在需要使用富文本编辑器的位置设置一下代码:
html:
    <link rel="stylesheet" type="text/css" href="/ueditor/UE/third-party/SyntaxHighlighter/shCoreDefault.css">
    <script type="text/javascript" src="/ueditor/UE/third-party/SyntaxHighlighter/shCore.js"></script>
    <script type="text/javascript" src="/ueditor/UE/ueditor.config.js"></script>
    <script type="text/javascript" src="/ueditor/UE/ueditor.all.min.js"></script>
    <script type="text/javascript" src="/ueditor/UE/lang/zh-cn/zh-cn.js"></script>


    <div class="am-form-group">
        <label for="user-intro" class="am-u-sm-3 am-form-label">商品简介</label>
        <div class="am-u-sm-9">
            <!-- <textarea name="descr" class="" rows="10" id="user-intro" placeholder="请输入商品简介"></textarea> -->
            <!-- <script id="editor" type="text/plain" style="width:100%;height:500px;"></script> -->
            <script id="editor" name="content" type="text/plain" style="height:500px;"></script>
        </div>
    </div>


    <script type="text/javascript">
        var ue = UE.getEditor('editor');
        SyntaxHighlighter.all();
    </script>
6,其它问题

当前使用 妹子UI 模板 css影响了当前的编辑器的样式

修改,/static/myadmin/assets/css/app.css  379行
.tpl-content-wrapper {
  transition: all 0.4s ease-in-out;
  /*position: relative;*/
  margin-left: 240px;
  z-index: 1101;
  min-height: 922px;
  border-bottom-left-radius: 3px;
}
7,水印功能
  • 上传图片自动加水印 该功能默认没开启。

  • 上传图片加水印功能需要安装PIL

    pip3 install pillow
    
  • 水印相关设置在ueconfig.json末尾:

    "openWaterMark": false,  //是否开启
    "waterMarkText": "我的水印\nhttp://xxxxx.com", //水印内容,建议一行文本
    "waterMarkFont": "msyhbd.ttf",  //字体,中文需要字体支持才不会出错
    "waterMarkSize": 15,    //字体大小
    "waterMarkBottom": 45,  //下边距
    "waterMarkRight": 155   //右边距
    

④. Django部署Apache

在前面的章节中我们使用python3 manage.py runserver来运行服务器。这只适用测试环境中使用。

正式发布的服务,我们需要一个可以稳定而持续的服务器,比如Apache, Nginx, IIS等,本文将以 Apache为例。

使用Apachemod_wsgi部署Django 是一种久经考验的将Django投入生产的方法。

mod_wsgi是一个Apache模块,可以托管任何Python WSGI应用程序,包括Django。

Django将使用任何支持mod_wsgi的Apache版本。

1. 测试环境

说明

  • Ubuntu 16.04
  • Python 3.5.2
  • Django 1.11.7
  • Apache 2.4

2. 配置步骤

1,Apache2安装
Apache2安装
sudo apt-get install apache2

查看版本

apachectl -v

Server version: Apache/2.4.18 (Ubuntu)

Server built: 2017-09-18T15:09:02
2,确保有127.0.0.1 localhost,没有就加上。
sudo vim /etc/hosts

127.0.0.1       localhost
127.0.0.1       www.pyweb.cn
3,打开浏览器 输入 127.0.0.1或localhost
出现 Apache2 Ubuntu Default Page

或It works!

则成功
4,安装apache2解析python的包 wsgi程序包
sudo apt-get install libapache2-mod-wsgi-py3

安装完成后 进入 /usr/lib/apache2/modules 目录
cd /usr/lib/apache2/modules
查看是否存在mod_wsgi.so-3.5
5,配置使apache2加载mod-wsgi包
编辑配置文件
sudo vim /etc/apache2/apache2.conf

在文件的最后 添加

LoadModule wsgi_module /usr/lib/apache2/modules/mod_wsgi.so-3.5
6,创建网站配置文件
编辑网站配置文件
sudo vim /etc/apache2/sites-available/myproject.conf

配置内容:
<VirtualHost *:80>
   ServerName www.pyweb.cn
   ServerAdmin py@163.cn
   #wsgi文件目录
   WSGIDaemonProcess python-path=/var/www/myproject
   WSGIScriptAlias / /var/www/myproject/myproject/wsgi.py
   <Directory /var/www/myproject/myproject>
       <Files wsgi.py>
           Require all granted
       </Files>
   </Directory>
   #项目文件目录
   DocumentRoot /var/www/myproject
   <Directory /var/www/myproject>
       Require all granted
   </Directory>
   #静态文件目录
   Alias /static/ /var/www/myproject/static/
   <Directory /var/www/myproject/static/>
       Require all granted
   </Directory>
   #错误日志
   ErrorLog ${APACHE_LOG_DIR}/django-myproject-error.log
   CustomLog ${APACHE_LOG_DIR}/myproject-django.log combined
</VirtualHost>
7,将当前的配置文件创建一个软连接到/etc/apache2/sites-enabled
cd /etc/apache2/sites-enabled

sudo ln -s ../sites-available/myproject.conf ./
8,执行命令 生效当前配置
 sudo a2ensite myproject.conf

如果需要让这个配置失效,可以执行 sudo a2dissite myproject.conf
9,配置Django项目目录及修改seeting.py文件,
首先把myproject项目目录拷贝至 /var/www/目录下

在将其ALLOWED_HOSTS=[]改为

ALLOWED_HOSTS=['www.pyweb.cn'],多个域名可以通过逗号隔开。
10,修改Django的wsgi.py文件
import os
os.environ["DJANGO_SETTINGS_MODULE"] = "myproject.settings"
#os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pyjfive.settings")

from os.path import join,dirname,abspath
PROJECT_DIR = dirname(dirname(abspath(__file__)))

import sys # 4
sys.path.insert(0,PROJECT_DIR)


from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

3. 最后:重启apache2

sudo service apache2 restart

4. 浏览器访问

http://www.pyweb.cn/

5. 浏览器错误 500

Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator at [no address given] to inform them of the time this error occurred,
and the actions you performed just before this error.
More information about this error may be available in the server error log.
Apache/2.4.18 (Ubuntu) Server at www.py6web.com Port 80
  • 查看apache2的错误日志
cd /var/log/apache2/

File "/var/www/myproject-test/myproject/wsgi.py", line 17, in <module>, referer: http://www.pyweb.com/
from django.core.wsgi import get_wsgi_application, referer: http://www.pyweb.com/
ImportError: No module named 'django', referer: http://www.pyweb.com/
  • 问题分析
进入项目目录,使用命令 pip3 show Djando 查看当前是否已经安装django
---
Metadata-Version: 1.1
Name: Django
Version: 1.11.8

切换至root用户 sudo su 

进入python3的shell模式
python3
#加载django模块
import django
#错误:No module named 'django'
  • 解决方案
在当前root用户下 安装django
sudo su
pip3 install django==1.11

2.8 Django的其他核心功能

①. 静态文件

项目中的CSS、图片、js都是静态文件

1. 配置静态文件

1.在settings 文件中定义静态内容
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]
2.在项目根目录下创建static目录,再创建当前应用名称的目录
mysite/static/myapp/
3.在模板中可以使用硬编码
/static/my_app/myexample.jpg
4.在模板中可以使用static编码
{ % load static from staticfiles % }
<img src="{ % static "my_app/myexample.jpg" % }" alt="My image"/>

②. csrf

CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本XSS,但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性

CSRF中间件和模板标签为防止跨站点请求伪造提供了易用的保护

当恶意网站包含链接,表单按钮或某些旨在在您的网站上执行某些操作的JavaScript时,会使用在浏览器中访问恶意网站的登录用户的凭据进行此类攻击。

还介绍了一种相关攻击类型,即“登录CSRF”,攻击网站欺骗用户的浏览器,以便使用其他人的凭证登录到网站。

1. csrf的使用

在django的模板中,提供了防止跨站攻击的方法,使用步骤如下:

  • step1:在settings.py中启用’django.middleware.csrf.CsrfViewMiddleware’中间件,此项在创建项目时,默认被启用

  • step2:在HTML的表单中添加标签

    <form>
    { % csrf_token % }
    ...
    </form>
    

2. 取消保护

如果某些视图不需要保护,可以使用装饰器csrf_exempt,模板中也不需要写标签,修改csrf2的视图如下 from django.views.decorators.csrf import csrf_exempt

@csrf_exempt 
def csrf2(request):
    uname=request.POST['uname'] 
    return render(request,'booktest/csrf2.html',{'uname':uname}) 
    运行上面的两个请求,发现都可以请求

3. 保护原理

加入标签后,可以查看源代码,发现多了如下代码

<input type='hidden' name='csrfmiddlewaretoken' value='nGjAB3Md9ZSb4NmG1sXDolPmh3bR2g59' />
  • 在浏览器的调试工具中,通过network标签可以查看cookie信息
  • 本站中自动添加了cookie信息,如下图csrf3
  • 查看跨站的信息,并没有cookie信息,即使加入上面的隐藏域代码,发现又可以访问了
  • 结论:django的csrf不是完全的安全
  • 当提交请求时,中间件’django.middleware.csrf.CsrfViewMiddleware’会对提交的cookie及隐藏域的内容进行验证,如果失败则返回403错误

4. Ajax CSRF 认证

GET 请求不需要 CSRF 认证,POST 请求需要正确认证才能得到正确的返回结果。

如果使用Ajax调用的时候,就要麻烦一些。需要注意以下几点:

  • 在视图中使用render (而不要使用 render_to_response)

  • 使用 jQuery 的 ajax 或者 post 之前 加入这个 js 代码

    jQuery(document).ajaxSend(function(event, xhr, settings) {
        function getCookie(name) {
            var cookieValue = null;
            if (document.cookie && document.cookie != '') {
                var cookies = document.cookie.split(';');
                for (var i = 0; i < cookies.length; i++) {
                    var cookie = jQuery.trim(cookies[i]);
                    // Does this cookie string begin with the name we want?
                    if (cookie.substring(0, name.length + 1) == (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        }
        function sameOrigin(url) {
            // url could be relative or scheme relative or absolute
            var host = document.location.host; // host + port
            var protocol = document.location.protocol;
            var sr_origin = '//' + host;
            var origin = protocol + sr_origin;
            // Allow absolute or scheme relative URLs to same origin
            return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
                (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
                // or any other URL that isn't scheme relative or absolute i.e relative.
                !(/^(\/\/|http:|https:).*/.test(url));
        }
        function safeMethod(method) {
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
    
        if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
            xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        }
    });
    
  • 或者 更为优雅简洁的代码(不能写在 .js 中,要直接写在模板文件中):

    $.ajaxSetup({
        data: {csrfmiddlewaretoken: '{ { csrf_token } }' },
    });
    

这样之后,就可以像原来一样的使用 jQuery.ajax() 和 jQuery.post()了

③. 状态保持

  • HTTP协议是无状态的:每次请求都是一次新的请求,不会记得之前通信的状
  • 客户端与服务器端的一次通信,就是一次会话
  • 实现状态保持的方式:在客户端或服务器端存储与会话有关的数据
  • 存储方式包括cookie、session,会话一般指session对象
  • 使用cookie,所有数据存储在客户端,注意不要存储敏感信息
  • 推荐使用sesison方式,所有数据存储在服务器端,在客户端cookie中存储session_id
  • 状态保持的目的是在一段时间内跟踪请求者的状态,可以实现跨页面访问当前请求者的数据
  • 注意:不同的请求者之间不会共享这个数据,与请求者一一对应

1. 开启session

  • 使用django-admin startproject创建的项目默认启用

  • 禁用会话:删除下面指定的两个值,禁用会话将节省一些性能消耗

  • Django 中session需要依赖数据库,因此需要确认数据库中是否存在 与session相关的 表

  • 在settings.py文件中

    * 项INSTALLED_APPS列表中添加:
    * 'django.contrib.sessions',
    
    * 项MIDDLEWARE_CLASSES列表中添加:
    * 'django.contrib.sessions.middleware.SessionMiddleware',
    

2. 使用session

  • 启用会话后,每个HttpRequest对象将具有一个session属性,它是一个类字典对象

  • get(key, default=None):根据键获取会话的值

  • clear():清除所有会话

  • flush():删除当前的会话数据并删除会话的Cookie

  • del request.session[‘member_id’]:删除会话

  • 示例:

    #session设置
     request.session[key] = value
    
    #session获取
     request.session.get(key,default=Node)
    
    #session删除
    
    # 删除单个key 不存在时报错
     del request.session['a'] 
    
    #清除所有会话,但不会删除数据
     request.session.clear() 
    
    #删除当前的会话数据
     request.session.flush()
    

④. 中间件

  • 中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出
  • 激活:添加到Django配置文件中的MIDDLEWARE_CLASSES元组中
  • 使用中间件,可以干扰整个处理过程,每次请求中都会执行中间件的这个方法

1. 验证用户是否登陆示例

在应用中创建AdminLoginMiddleware.py文件

from django.shortcuts import render
from django.http import HttpResponse
import re

class AdminLoginMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        # One-time configuration and initialization.

    def __call__(self, request):


        # 检测当前的请求是否已经登录,如果已经登录,.则放行,如果未登录,则跳转到登录页
        # 获取当前用户的请求路径  /admin/开头  但不是 /admin/login/  /admin/dologin/   /admin/verifycode
        urllist = ['/admin/login','/admin/dologin','/admin/vcode']
        # 判断是否进入了后台,并且不是进入登录页面
        if re.match('/admin/',request.path) and request.path not in urllist:

            # 检测session中是否存在 adminlogin的数据记录
            if request.session.get('Vuser','') == '':
                # 如果在session没有记录,则证明没有登录,跳转到登录页面
                return HttpResponse('<script>alert("请先登录");location.href="/admin/login";</script>')



        response = self.get_response(request)
        return response

2. 配置中间件

在settings.py文件中修改MIDDLEWARE_CLASSES选项

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    #自定义的中间件
    'myadmin.AdminMiddleware.AdminLoginMiddleware'
]

⑤. 密码管理

1. 使用Django中提供的密码方案

django.contrib.auth.hashers模块提供了一组函数来创建和验证散列密码。您可以独立于User模型使用它们。

 # from django.contrib.auth.hashers import make_password, check_password

 # 对密码进行加密操作
 # upass = make_password(request.POST['password'], None, 'pbkdf2_sha256')
 # upass = check_password('1234567','pbkdf2_sha256$36000$197nqXM6yxYv$Zxh/Vsns8qszkvUmY81BgrjCeLPXhCHLEilP6VO+Rnc=')

2. Python中的MD5加密

#获取密码并md5
import hashlib
m = hashlib.md5() 
m.update(bytes(request.POST['password'],encoding="utf8"))
print(m.hexdigest())
  • 0
    点赞
  • 1
    评论
  • 7
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

<p> <span style="color:#E53333;font-family:"font-size:24px;background-color:#FFFFFF;"><strong>本页面购买不发书!!!仅为视频课购买!!!</strong></span><strong><span style="font-size:24px;"></span></strong> </p> <p style="font-family:"color:#3D3D3D;font-size:16px;background-color:#FFFFFF;"> <strong><span style="color:#E53333;font-size:18px;">请务必到</span></strong><strong><span style="color:#E53333;font-size:18px;"><a href="https://edu.csdn.net/bundled/detail/59?utm_source=banner">https://edu.csdn.net/bundled/detail/59</a> 下单</span></strong><strong><span style="color:#E53333;font-size:18px;">,方可购买课程+图书。</span></strong> </p> <p style="font-family:"color:#3D3D3D;font-size:16px;background-color:#FFFFFF;"> <strong><span style="color:#E53333;font-size:18px;"><br /> </span></strong> </p> <p style="font-family:"color:#3D3D3D;font-size:16px;background-color:#FFFFFF;"> 本页面,仅为观看视频页面,如需购买图书,请<span style="font-family:"">务必到</span><a href="https://edu.csdn.net/bundled/detail/49?utm_source=banner"></a><a href="https://edu.csdn.net/bundled/detail/59?utm_source=banner">https://edu.csdn.net/bundled/detail/59</a><span style="font-family:"">下单购买。</span> </p> <p style="font-family:"color:#3D3D3D;font-size:16px;background-color:#FFFFFF;"> <br /> </p> <p> 本课程由浅入深的讲授人工智能、机器学习、深度学习的原理和实现,尤其会重点介绍搜索引擎和自然语言处理等热门技术,不但会用生动的例子帮助学员理解理论知识,还会手把手详细示范动手实践环节,让你能够亲自实现一个智能问答系统。 </p>
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页

打赏作者

花开如雨

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值