recursal/MDN huggingface dataset:
关系选择器
=====

* 上一页
* Overview: Building blocks
* 下一页

我们要了解的最后一种选择器被命名为关系选择器（Combinator），这是因为它们在其他选择器之间和其他选择器与文档内容的位置之间建立了一种有用的关系的缘故。

|  |  |
| --- | --- |
| 学习前提： | 基础电脑知识、安装了基本的软件、文件处理基本知识、HTML 基础（学习 HTML 介绍），以及对 CSS 工作原理的了解（学习CSS 初步） |
| 目标： | 了解 CSS 里面可用的不同关系选择器。 |

后代选择器
-----

后代选择器——典型用单个空格（" "）字符——组合两个选择器，比如，第二个选择器匹配的元素被选择，如果他们有一个祖先（父亲，父亲的父亲，父亲的父亲的父亲，等等）元素匹配第一个选择器。选择器利用后代组合符被称作后代选择器。


```css
body article p
```


下面的示例中，我们只会匹配处于带有`.box`类的元素里面的`<p>`元素。

子代关系选择器
-------

子代关系选择器是个大于号（`>`），只会在选择器选中直接子元素的时候匹配。继承关系上更远的后代则不会匹配。例如，只选中作为`<article>`的直接子元素的`<p>`元素：


```css
article > p
```


下个示例中，我们弄了个有序列表，内嵌于另一个无序列表里面。我用子代关系选择器，只选中为`<ul>`的直接子元素的`<li>`元素，给了它们一个顶端边框。

如果你移去指定子代选择器的`>`的话，你最后得到的是后代选择器，所有的`<li>`会有个红色的边框。

邻接兄弟
----

邻接兄弟选择器（`+`）用来选中恰好处于另一个在继承关系上同级的元素旁边的物件。例如，选中所有紧随`<p>`元素之后的`<img>`元素：


```css
p + img
```


常见的使用场景是，改变紧跟着一个标题的段的某些表现方面，就像是我下面的示例那样。这里我们寻找一个紧挨`<h1>`的段，然后样式化它。

如果你往`<h1>`和`<p>`之间插入其他的某个元素，例如`<h2>`，你将会发现，段落不再与选择器匹配，因而不会应用元素邻接时的前景和背景色。

通用兄弟
----

如果你想选中一个元素的兄弟元素，即使它们不直接相邻，你还是可以使用通用兄弟关系选择器（`~`）。要选中所有的`<p>`元素后*任何地方*的`<img>`元素，我们会这样做：


```css
p ~ img
```


在下面的示例中，我们选中了所有的 `<h1>`之后的`<p>`元素，虽然文档中还有个 `<div>`，其后的`<p>`还是被选中了。

使用关系选择器
-------

你能用关系选择器，将任何在我们前面的学习过程中学到的选择器组合起来，选出你的文档中的一部分。例如如果我们想选中为`<ul>`的直接子元素的带有“a”类的列表项的话，我可以用下面的代码。


```css
ul > li[class="a"] {
}
```


不过，建立一长列选中你的文档中很明确的部分的选择器的时候，小心一些。这些 CSS 规则难以复用，因为你让选择器在表示标记文本中的元素的相对位置上过于明确。

建立简单的一个类，然后把它应用到有需求的元素上，经常会是更好的做法。不过话说回来，如果你需要让你的文档变换一下样式，但是没法编辑 HTML（也许是因为它由 CMS 生成）的话，你的关系选择器的知识会派上用场。

技能测试！
-----

我们已经在这篇文章里讲了许多内容，不过你能记住最重要的信息吗？你可以找些更深入的测试，在继续下去之前，验证你是否已经获取了这些信息——见技能测试：选择器。

继续学习
----

这是我们选择器这节课的最后一节了。下面我们将会继续前进，学习 CSS 的另一个重要部分——层叠与继承。

* 上一页
* Overview: Building blocks
* 下一页
技能测试：网格布局
=========

此任务的目的是让你使用 CSS 网格布局，并测试你是否了解网格和网格项的行为方式。你将会完成三个包括不同的元素小任务。

**备注：** 你可以在下面的交互式编辑器中试用解决方案，不过，下载代码并使用在线工具 (如 CodePen、jsFiddle 或 Glitch) 处理这些任务可能会更有帮助。

如果你遇到困难，请向我们寻求帮助 — 参阅本页底部的 评估或进一步帮助 部分。

网格布局 一
------

在此任务中，你需要创建一个网格，要求其中的四个子元素能自动排布。网格内要有三列并且将可用空间等分，列和行的间距均为 20px。

在三列网格布局中有四个物体放入其中。

尝试更新下面的实时代码以复现上面的示例：

**备注：** 评估或进一步的工作目的，可以下载此任务的源文件在你自己的编辑器或使用线编辑器。

网格布局 二
------

在此例中，我们已经定义好了一个 grid, 请通过修改下面两个子元素的 CSS 规则，导致它们跨过彼此的网格轨道; 第二个 item 应该在第一个 item 之上 (如下图所示).

![盒子中的两个元素，其中一个元素覆盖在另一个元素上。](/zh-CN/docs/Learn/CSS/CSS_layout/Grid_skills/grid-task2.png)

尝试更新下面的实时代码以复现上面的示例：

附加问题：

* 你可以把第一个元素覆盖到第二个元素，而不通过改变 html 元素的顺序吗？

**备注：** 评估或进一步的工作目的，可以 下载此任务的源文件 在你自己的编辑器或使用线编辑器。

网格布局 三
------

此 grid 中 4 个子元素，初始状态是显示的是 auto-placement. 请通过使用 grid-area 和 grid-template-areas 属性对照下图放置元素的布局。

![网格中显示的四个项目。](/zh-CN/docs/Learn/CSS/CSS_layout/Grid_skills/grid-task3.png)

尝试更新下面的实时代码以复现上面的示例：

**备注：** 评估或进一步的工作目的，可以 下载此任务的源文件 在你自己的编辑器或使用线编辑器。

网格布局 四
------

此例中，你需要同时使用 Grid Layout 和 Flexbox 来完成下图所示的任务。这个过程中你不需要通过改变 HTML 来完成。

![两行卡片，每个卡片有一个图像和一组标签。](/zh-CN/docs/Learn/CSS/CSS_layout/Grid_skills/grid-task4.png)

尝试更新下面的实时代码以复现上面的示例：

**备注：** 评估或进一步的工作目的，可以 下载此任务的源文件 在你自己的编辑器或使用线编辑器。

评估 或者 帮助
--------

你可以在上述的交互编辑器上练习。

如果你的作业需要评估，或者有困难想要帮助：

1. 把你的作业放在一个在线可分享的编辑器上，比如 CodePen, jsFiddle, 或者 Glitch. 你可以自己重头开始写，或者使用上面章节提供的源文件。
2. Write a post asking for assessment and/or help at the MDN Discourse forum Learning category. Your post should include:
 发布一个评估的帖子 或者 帮助在MDN Discourse forum Learning category你的发布应该涵盖以下几点：
    * A descriptive title such as "Assessment wanted for Grid layout 1 skill test".
    * Details of what you have already tried, and what you would like us to do, e.g. if you are stuck and need help, or want an assessment.
    * A link to the example you want assessed or need help with, in an online shareable editor (as mentioned in step 1 above). This is a good practice to get into — it's very hard to help someone with a coding problem if you can't see their code.
    * A link to the actual task or assessment page, so we can find the question you want help with.
Test your skills: position
==========================

此任务的目的是让你使用在我们的 position 课程中介绍的 CSS `position`属性以及对应值，你将通过两个小任务来复习刚才课程材料中介绍的不同元素。

**备注：** 你可以在下面的交互式编辑器中尝试解决方案，下载代码并使用在线工具（如 CodePen、jsFiddle 或 Glitch）处理任务可能会有帮助。

如果你遇到困难，请向我们寻求帮助 - 请参阅本页底部的 Assessment or further help 部分

定位练习一
-----

在这项任务中，你需要将目标类别为 5px 灰色边框的元素定位到外部容器的右上角。

![The green box is at the top right of a container with a grey border.](/zh-CN/docs/Learn/CSS/CSS_layout/Position_skills/position-task1.png)

尝试更改下面的代码示例，重新完成的上述任务：

作为一个额外的挑战，你能改变目标元素显示在文本下面吗？

**备注：** 为了评估和进一步编辑，下载源代码在本地编辑器或在线编辑器中编辑

定位练习二
-----

在下面的示例中，滚动条滚动时侧边栏将随内容一起滚动。更改它使滚动条滚动时侧边栏保持原位并且只滚动内容。

![The content is scrolled but the sidebar has stayed in place.](/zh-CN/docs/Learn/CSS/CSS_layout/Position_skills/position-task2.png)

尝试更改下面的代码示例，重新完成的上述任务：

**备注：** 为了评估和进一步编辑，下载源代码在本地编辑器或在线编辑器中编辑

Assessment or further help
--------------------------

You can practice these examples in the Interactive Editors mentioned above.

If you would like your work assessed, or are stuck and want to ask for help:

1. Put your work into an online shareable editor such as CodePen, jsFiddle, or Glitch. You can write the code yourself, or use the starting point files linked to in the above sections.
2. Write a post asking for assessment and/or help at the MDN Discourse forum Learning category. Your post should include:
    * A descriptive title such as "Assessment wanted for Position skill test 1".
    * Details of what you have already tried, and what you would like us to do, e.g. if you are stuck and need help, or want an assessment.
    * A link to the example you want assessed or need help with, in an online shareable editor (as mentioned in step 1 above). This is a good practice to get into — it's very hard to help someone with a coding problem if you can't see their code.
    * A link to the actual task or assessment page, so we can find the question you want help with.
常规流布局
=====

* 上一页
* Overview: CSS layout
* 下一页

本文介绍常规流布局，或者说，在你没有改变默认布局规则情况下的页面元素布局方式。

|  |  |
| --- | --- |
| 前提： | 
 HTML 基础知识（学习
 HTML 简介），以及了解 CSS 如何工作的（学习
 CSS 入门概述）。
  |
| 目标： | 在做出改动之前，能够解释浏览器默认的布局方式。 |

如上节对布局的介绍，如果你未曾应用任何 CSS 规则来改变网页中元素的展现方式，那么它们将会按照常规流布局来组织。同样地，正如我们一开始发现的那样，你可以通过调整元素位置，或者完全的移除元素来改变它们的表现效果。从一个简单的、结构良好并且在常规流布局下仍然易读的文档开始，是上手任何网页的最佳方式。这样确保了你的内容的易读性，即便用户使用受限的浏览器或者屏幕阅读设备。此外，由于常规流布局的设计初衷在于构建易读、合理的文档，遵循这样的指引原则，你在对布局做出改动时应该是与文档*协同*，而不是与之*对抗*。

在深入探索不同的布局方式之前，你最好回顾一下在之前模块学习到的关于常规文档流的知识点。

元素在默认情况下是如何布局的？
---------------

首先，取得元素的内容并将其放在一个独立的元素盒子中，然后在其周边加上内边距、边框和外边距——就是我们所说的**盒子模型**。

默认情况下，一个块级元素会填充其父元素所有的行向空间，并沿着其块向伸长以容纳其内容。行级元素的大小就是其本身的大小。你可以为某些 `display` 属性值默认为 `inline` 的元素（例如 `<img>`）设置 `width` 或 `height`，但其 `display` 仍将保持为 `inline`。

如果你想要控制行级元素的 `display` 属性，请使用 CSS 将其设置为块级元素（例如，使用 `display: block;` 或 `display: inline-block;`，后者混合了两者特性）。

这样解释了独立元素的布局，但是元素之间又是如何相互影响的呢？常规流布局（在布局介绍里提到过）是一套用于在浏览器视口内组织元素如何放置的系统。默认地，块级元素按照基于其父元素的书写模式（*默认值*：horizontal-tb）的*块流动方向*（block flow direction）放置。每个块级元素会在上一个元素下面另起一行，它们会以指定的外边距分隔。以英语为例（或者其他水平书写、自上而下的书写模式中），块级元素是垂直组织的。

行级（inline）元素的表现有所不同。它们不会另起一行；只要在其父级块级元素的宽度内有足够的空间，它们与其他内联元素、相邻（或换行）的文本内容被安排在同一行。如果空间不够，溢出的内容将下移到新的一行。

如果两个垂直相邻的元素都设置了外边距并且两个外边距相接触，那么更大的外边距会被保留，小的则会消失——这被称为**外边距折叠**。外边距折叠仅与**垂直方向**有关。

我们来看一个对全部这些做出解释的简单示例：


```html
<h1>基础文档流</h1>

<p>我是一个基本的块级元素。我的相邻块级元素在我的下方另起一行。</p>

<p>
  默认情况下，我们会占据父元素 100%
  的宽度，并且我们的高度与我们的子元素内容一样高。我们的总宽度和高度是我们的内容
  + 内边距 + 边框宽度/高度。
</p>

<p>
  我们以我们的外边距分隔。由于外边距折叠，我们以其中一个外边距的宽度分隔，而不是两个。
</p>

<p>
  如果在同一行上足够的空间，行级元素（如<span>这个</span>和<span>这个</span>），那么它们将与相邻的文本节点将会一起放置在同一行上。如果行级元素溢出，<span>那么它们将会换行，就像这个包含文本的行级元素一样</span>，或者如果没有足够的空间，那么它们将会换到新的一行，就像这个图片一样：
  <img src="long.jpg" alt="snippet of cloth" />
</p>
```



```css
body {
  width: 500px;
  margin: 0 auto;
}

p {
  background: rgba(255, 84, 104, 0.3);
  border: 2px solid rgb(255, 84, 104);
  padding: 10px;
  margin: 10px;
}

span {
  background: white;
  border: 1px solid black;
}
```

总结
--

在本节中，你学习了常规流布局的基础指示——知晓元素的默认 CSS 布局方式。通过了解行级元素、块级元素以及外边距的默认行为，在未来你可以更轻松地修改这些行为。

在下一节，我们将会在这些基础指示的基础上，使用弹性盒子来修改元素的 CSS 布局方式。

* 上一页
* Overview: CSS layout
* 下一页
作业：基本布局理解
=========

* 上一页
* Overview: CSS layout

如果你已经完成了本模块的学习，那么你就已经掌握了今天进行 CSS 布局所需要的基本知识，并且也可以使用旧的 CSS。这个任务将通过使用各种技术开发一个简单的网页布局来测试你的一些知识。

|  |  |
| --- | --- |
| 预备条件： | 在尝试此评估之前，你应该已经阅读了本模块中的所有文章。 |
| 学习目标： | 测试对 CSS 弹性盒、栅格、浮动和定位布局方法的基本理解。 |

从这里开始
-----

你可以在这里下载基本的 HTML、CSS 和六张图片素材。

将 HTML 文档和样式表文件保存到你自己计算机的目录中，并将图像添加到名为 `images` 的文件夹中，在浏览器中打开 `index.html` 文件应该会提供一个具有基本样式但没有布局的页面，该页面应该类似下面所示的图像。

![布局任务的起点。这些元素没有被整齐地排列。有一个网站的标题，上面是一个黑色的导航条，有 5 个链接平齐在左边，后面是博客文章的标题和文章内容。在博客标题和博客内容之间，有一张照片是平齐在左边。](/zh-CN/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension/layout-task-start.png)

此页面开始于浏览器在正常流中显示的布局的所有内容。

另外，你可以使用像 Glitch 这样的网站来做评估，把 HTML 和 CSS 代码粘贴进去。注意，如果你使用在线编辑器，你将需要上传图片并替换 `src` 属性中的值，以指向新的图片位置。如果你使用的在线编辑器没有单独的 CSS 面板，可以随意将其放在文档头部的 `<style>` 元素中。

**备注：** 如果你卡住了，向我们请求协助——你可以在页面底部的评估或更多帮助获取指引。

项目简介
----

我们已经为你提供了一些原始的 HTML、基本的 CSS 文件和图像——现在你需要设计布局页面。

### 目标

你需要实现你自己的布局。下面是你应该完成的目标：

1. 在一行中显示导航选项，并且选项之间拥有相同的空间。
2. 导航条应随着内容一起滚动并且在触碰到视口顶部之后于顶部固定。
3. 文章内的图片应该被文本包围。
4. `<article>` 与 `<aside>` 元素应该为双列布局。它们的列尺寸应该是弹性的，以便在浏览器窗口收缩得更小的时候能够变窄。
5. 照片应显示为两列网格，图像之间有 1 像素的间隙。
提示和小技巧
------

在实现布局的过程中你不需要修改 HTML，下面是你应该使用的技术：

* 弹性盒
* 栅格
* 浮动
* 定位

有几种方法可以实现其中的一些任务，而且往往没有单一的正确或错误的方法来做事情。试试几种不同的方法，看看哪种方法最有效。在实验过程中做下笔记。

示例
--

以下截图呈现了设计完成后的示例：

![完成了布局任务的网站。这些元素被整齐地排列着。有一个网站标题，上面是一个黑色的导航条，包含 5 个等距的链接。在导航栏下面，有两个部分。在左边有一篇博客文章。博文标题后面是博文内容。博客内容环绕着一张照片，照片在左边平齐。在右边有一个“photography”标题，图片以两张图片宽度的栅格大小排列。](/zh-CN/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension/layout-task-complete.png)

评估或更多帮助
-------

如果你希望你的作业得到评估，或遇到问题需要帮助：

1. 将你的作业放在在线可分享编辑器中，如 CodePen、jsFiddle 或 Glitch
2. 在 MDN Discouse 论坛 Learning 分区发贴，你的贴文应包含：
    * 一个描述性的标题，如“Assessment wanted for Fundamental layout comprehension”。
    * 你已经尝试过的细节，以及你希望我们做什么；例如，告诉我们你是否被卡住了，需要帮助或希望进行评估。
    * 在一个在线可共享的编辑器中，提供你想要评估或需要帮助的例子的链接（在上面第 1 步中提到的）。这是一个很好的做法，如果你不能看到他们的代码，就很难帮助别人解决编码问题。
    * 实际任务或评估页面的链接，以便我们能够找到你想要帮助的问题。
* 上一页
* Overview: CSS layout
Express Web 框架（Node.js/JavaScript）
==================================

Express 是一款受欢迎的开源 web 框架，构建语言是 JavaScript，可以在 node.js 环境运行。本系列文章介绍了该框架的优点，如何搭建开发环境以及部署 web 开发环境并进行开发任务。

前提
--

在开始这个模块之前你需要知道什么是服务端网页编程和 web 框架，建议你先阅读 服务端网页编程 模块。强烈推荐了解编程概念和 JavaScript ，但这对理解核心概念不是必需的。

**备注：** 这个网站有很多有用的资源用来学习 JavaScript 做客户端开发： JavaScript, JavaScript Guide, JavaScript Basics, JavaScript (learning). 核心的 JavaScript 语言和概念用 Nodejs 服务端开发是相同的，也是相关的。Node.js 提供 额外的 API 用于支持在无浏览器环境中有用的功能，例如，创建 HTTP 服务器并访问文件系统，但不支持 JavaScript API 以使用浏览器和 DOM。

这篇指南将会提供一些 Node.js 和 Express 的信息，并且有很多优秀的网络资源和书籍。一些链接 比如How do I get started with Node.js (StackOverflow) 和 What are the best resources for learning Node.js? (Quora).

指南
--

Express/Node 介绍

在这篇文章中，我们回答了“什么是 Node？”和“什么是 Express？”并为你概述了 Express web 框架的特殊之处。我们将介绍主要功能，并向你展示 Express 应用程序的一些主要构建模块（尽管此时你还没有可用于测试它的开发环境）。

搭建 Node(Express) 开发环境

介绍了 Express 的所用之处后，我们将向你展示如何在不同操作系统下建立并验证 Node/Express 开发环境。无论你使用任何操作系统，这篇文章都可以完全指导如何开始构建 Express 应用。

Express 教程——第一部分：本地图书馆

该实用教程系列中的第一篇文章，介绍了即将学习的内容，并概述了在后续文章中不断迭代的“本地图书馆”例子。

Express 教程——第二部分：建立网站的骨架

这篇文章将介绍如何建立一个网站项目的“骨架”，然后你可以继续添加自己的路由、模板/视图和数据库。

Express 教程——第三部分：使用数据库（Mongoose）

这篇文章简单介绍了在 Node/Express 中如何使用数据库。本文中我们将会使用 Mongoose 为该项目（本地图书馆）提供数据访问，同时解释了如何定义对象模式、模型和基础和验证。本文也简单介绍了访问模型数据的一些主流方式。

Express 教程——第四部分：路由和控制器

我们在本教程中会设置路由来编写一些本地图书馆所需的伪造端点（endpoints）。在接下来的文章中，路由会有一个模块结构，可用来拓展 real handler functions。最终，我们会对用 Express 创建模块化路由有很好的理解。

Express 教程——第五部分：在 HTML 上展示图书数据

我们现在已经准备好为展示本地图书馆图书和其他数据添加页面，包括展示每个 model 有多少记录的主页，以及 list 和 detail 页面。我们会积累从 database 获取记录以及使用模版的实战经验。

Express 教程——第六部分：如何使用表单

本教程我们会教你如何在 Express 使用 HTML 表单，Pug，以及从数据库中创建，更新，删除文件。

Express 教程——第七部分：如何部署到生产环境

现在你已经创建了一个很棒的本地图书馆网站，你可以把本地环境迁移到公共网络服务器上，别人也可以使用网站。本章提供了如何找服务器，部署网站到生产环境的概览。

添加更多教程
------

上面列出了所有现有的教程，如果你有兴趣，可以进一步扩展教程，一些其他有趣的主题包括：

* 使用 session
* 用户认证
* 用户授权与许可
* 测试 Express web 应用
* Express web 应用的安全

当然，如果做一个评估任务会更好！
服务端网站编程的第一步
===========

在我们的服务端编程板块中，我们回答了服务端编程的一系列基础问题—“它是什么？”，“它和客户端编程的区别是什么？”，还有“为什么它是有价值的？”。然后我们提供了对几个最受欢迎的服务端 Web 框架的概览，同时还有对如何选择最适合的框架来创建你第一个网站的指导。最后我们提供了一篇从高层次介绍 Web 服务器安全的文章。前提
--

在开始这个模块之前，你不必知道任何关于服务端网站编程的知识，或者任何一种其他编程经验。

你需要先知道“Web 如何工作”，我们推荐你首先阅读下面几个话题：

* 什么是一个 Web 服务器？
* 建立一个网站需要什么软件？
* 如何向 Web 服务器上传文件？

有了这些基础知识，你已经准备好开始这些模块的学习了。

引导
--

服务端简介

欢迎来到 MDN 提供的初学者服务端编程课程！在我们第一篇文章中，我们从一个很高的角度来审视服务端编程，回答的问题都是类似于：什么是服务端编程？它与客户端编程的区别在哪？以及为什么它如此有价值？在阅读本文之后，你将通过服务端编程了解更多关于网站开发的知识。

客户端编程回顾

现在你应该了解服务端编程的目的以及它可能带来的好处，我们现在要去探究一些细节，当服务端接收到浏览器的“动态请求”时，到底发生了什么。大多数服务端代码都是用相似的方式来处理请求以及应答，这一点将帮助你更好地明白在编写你自己的代码时，你到底需要做些什么。

服务端 web 框架

最后一篇文章将会介绍当服务端 web 程序为了响应 web 浏览器发出的请求，它需要做些什么。现在我们来看看 web 框架是如何简化这些任务的，除此之外，本文还将帮助你为你自己的第一个服务端 web 程序选择一个合适的框架。

网站安全性

在网站的设计与使用过程中，网站安全在方方面面都需要引起警惕。这篇引导性的文章不会让你成为网站安全方面的专家，但是它能够帮你了解为了强化你的 web 应用用以抵抗大多数常见的威胁时，你应该做的第一件重要的事是什么。

评估
--

这块“概览性”的内容并不会有任何评估练习，因为我们至今还没向你展示一句代码。我们确切地希望到了这里，你已经对服务端编程提供的各种功能有了一个很好的理解，并且已经为创建你自己的第一个 web 站点选好了合适的 web 框架。
Django Web 框架 (python)
======================

Django 是使用 Python 语言编写的一个广受欢迎且功能完整的服务器端网站框架。本模块将为你展示为什么 Django 能够成为一个广受欢迎的服务器端框架，如何设置开发环境，以及如何开始创建你自己的网络应用。

前提
--

开始学习本模块并不需要任何 Django 知识。但你要理解什么是服务器端网络编程、什么是网络框架，最好能够阅读我们的服务端网站编程的第一步模块。

最好能有基本的编程概念并了解 Python 语言，但其并不是理解本教程的核心概念的必然条件。

**备注：** 对于初学者来说，Python 是最容易阅读和理解的编程语言之一。也就是说，如果你想更好的理解本教程，网上有很多免费书籍及免费教程可供参考学习（建议初学者查看 Python 官网的 Python for Non Programmers 教程）。

指南
--

Django 简介

在第一篇关于 Django 的文章里，我们会回答"什么是 Django?",并概述这个网络框架的特殊之处。我们会列出主要的功能，包括一些高级的功能特性，这些高级特性我们在这部分教程里没有时间详细说明。在你设置好 Django 应用并开始把玩它之前，我们会展示 Django 应用的一些主要模块，让你明白 Django 应用能做什么。

创建 Django 开发环境

现在你知道 Django 是做什么的，我们会展示怎样在 Windows, Linux(Ubuntu) 和 Mac OS X 上创建和测试 Django 的开发环境—不管你是用什么操作系统，这篇文章会教给你能够开发 Django 应用所需要的开发环境。

Django 教程 1:本地图书馆网站

我们实用教程系列的第一篇文章会解释你将学习到什么，并提供"本地图书馆"网站这个例子的概述。我们会在接下来的文章里完成并不断的进化这个网站。

Django 教程 2:创建网站的框架

这篇文章会教你怎样创建一个网站的"框架".以这个网站为基础，你可以填充网站特定的 settings,urls, models,views 和 templates

Django 教程 3:使用模型

这篇文章会为 *本地图书馆* 网站定义数据模板—数据模板是我们为应用存储的数据结构。并且允许 Django 在数据库中存储数据 (以后可以修改).文章解释了什么是数据模板，怎样声明它和一些主要的数据种类。文章还简要的介绍了一些你可以获得数据模板的方法。

Django Tutorial Part 4: Django 管理站点

现在我们已经为本地图书馆网站创建了模型，我们将使用 Django 管理站点 添加一些‘真实的’的图书数据。首先，我们将向你介绍如何使用管理站点注册模型，然后我们介绍如何登录和创建一些数据。最后我们展示一些进一步改进管理站点的演示方法。

Django Tutorial Part 5: 创建我们的主页

我们现在可以添加代码来展示我们的第一次完整页面—本地图书馆主页，来显示我们对每个模型类型有多少条记录，并提供我们其他页面的侧边栏导航链接。一路上，我们将获得编写基本 URL 地图和视图，从数据库获取记录以及使用模版的实践经验。

Django Tutorial Part 6: 通用列表和详细视图

本教程扩展了我们的本地图书馆网站，添加书籍和作者和详细页面。在这里，我们将了解基于类的通用视图，并展示如何减少常用代码用例的代码量。我们还将更详细地深入理解 URL 处理，显示如何执行基本模式匹配。

Django Tutorial Part 7: 会话框架

本教程扩展本地图书馆网站，向主页添加了一个基于会话的访问计数器。这是个比较简单的例子，但它显示如何使用会话框架为你自己的站点中的匿名用户提供一致的行为。

Django Tutorial Part 8: 用户身份验证和权限

本教程，我们将向你展示如何允许用户使用自己的账户登录到你的网站，以及如何根据他们是否登录及其权限来控制他们可以做什么和看到什么。作为此次演示的一部分，我们将扩展本地图书馆网站，添加登录和注销页面以及用户和工作人员特定页面，以查看已借用的书籍。

Django Tutorial Part 9: 使用表单

本教程，我们将向你展示如何使用 Django 中的HTML 表单，特别是编写创建表单，更新和删除模型实例的最简单方法。作为此次演示的一部分，我们将扩展本地图书馆网站，以便图书馆员可以使用我们自己的表单 (而不是使用管理应用程序) 来更新书籍，创建，更新和删除作者。

Django Tutorial Part 10:测试 Django Web 应用程序

随着网站的的发展，手工测试越来越难测试—不仅要测试更多，而且随着组件之间的相互作用变得越来越复杂，一个领域的一个小的变化可能需要许多额外的测试来验证其对其他领域的影响。减轻这些问题的一种方法是编写自动化测试，每次更改时都可以轻松可靠地运行。本教程将介绍如何使用 Django 的测试框架对你的网站进行**单元测试**自动化。

Django Tutorial Part 11: 将 Django 部署到生产

现在，你已创建（并测试）一个酷的 本地图书馆网站，你将要把它安装在公共 Web 服务器上，以便图书馆员工和成员可以通过 Internet 访问。本文概述了如何找到主机来部署你的网站，以及你需要做什么才能使你的网站准备好进行生产。

Django web 应用程序安全

保护用户数据是任何网站设计的重要组成部分，我们以前解释了 Web 安全文章中一些更常见的安全威胁—本文提供了 Django 内置如何保护处理这种危险的实际演示。

评估
--

以下评估将测试你对如何使用 Django 创建网站的理解，如上述指南中所述。

DIY Django mini blog

在这个评估中，你将使用你从本单元中学到的一些知识来创建自己的博客。
Express 教程：本地图书馆网站
==================

* 上一页
* Overview: Express Nodejs
* 下一页

在实战教程第一节中，你将了解要学习哪些内容，对「本地图书馆」示例网站有一个初步的印象。本章接下来的内容就是逐步完成这个网站。

|  |  |
| --- | --- |
| 前提： | 
 阅读
 Express 入门。进行以后的小节还需要阅读
 配置 Node 开发环境。
  |
| 学习目标： | 引入本教程的示例应用，了解所涉及的所有主题。 |

概览
--

欢迎来到 MDN "本地图书馆" Express (Node) 教程，我们将开发一个管理本地图书馆编目的网站。

本系列教程中，你将：

* 使用 *Express* 应用生成器创建一个应用骨架。
* 启动和停止 Node web 服务器。
* 使用数据库存放应用数据。
* 创建路由来处理不同信息的请求，创建模板（"视图"）来渲染 HTML 数据以在浏览器中显示。
* 使用表单。
* 部署应用到生产环境。

你可能已经学过（或之前接触过）其中的部分主题。学完系列教程后，你就拥有足够技能独立开发简单的 Express 应用了。

本地图书馆网站（LocalLibrary）
---------------------

我们给本地图书馆网站起一个名字——LocalLibrary，这个名字将始终伴随本教程。顾名思义，此网站是为一家小型本地图书馆提供线上图书编目而建，用户可以能够浏览馆藏书目，还能管理自己的帐号。

本示例是精心挑选的，它规模灵活，可以根据我们的需求进行自由调整。还能演示绝大多数 Express 特性。更重要的是，这里提供的指引对所有网站都适用：

* 教程前几节中我们将定义一个简单的、只能浏览的图书馆，会员可以在网站找书。通过这几节我们来学习大多数网站都会涉及的一项操作：从数据库读取并呈现内容。
* 随着教程的进展，图书馆的示例子会逐步扩充，以演示更高级的网站特征。比如我们会加入新增书目的功能，以此来演示表单和用户授权的用法。

尽管这个示例具备相当可观的扩展度，但依然有理由把它叫做**本地**图书馆（**Local**Library）。我们希望呈现给你最少的信息，从而帮助你尽快上手并运行 Express。因此，我们只保留书名、本数、作者以及其他关键信息。我们会省略掉其他可能用到的信息，也不会提供多图书馆架构或“大型图书馆"等特性的支持。

我被难住了，哪里有源代码？
-------------

本教程进行过程中，我们将在每个知识点为你提供适当的代码片段，其中一些内容我们希望你能（在一定指引下）自己填充。

别总是复制粘贴这些片段，试着独立完成，长期来看这样做是有好处的，你下次编写类似代码时将更熟练。

如果实在进行不下去，可以参考 Github 上的完整版本。

**备注：** 本教程中的代码，已在特定版本（项目的 package.json 所列版本）的 node、Express 及其他模组的环境下通过测试。

总结
--

现在，你对 LocalLibrary 网站和即将学习的东西又多了解了一点，下面，我们开始创建一个用于存放它的 框架 吧！

* 上一页
* Overview: Express Nodejs
* 下一页
Express 教程 5: 呈现图书馆数据
=====================

* 上一页
* Overview: Express Nodejs
* 下一页

我们现在准备好要新增网页，以显示本地图书馆网站的书本与其他资料。这些网页将包含一个主页，显示我们拥有的每个模型的记录数，以及所有模型的清单和详细信息页面。借此，我们将获得从数据库获取记录、以及使用模板的实战经验。

|  |  |
| --- | --- |
| 前置条件： | 
 完成先前教程主题 (包含
 Express 教程 Part 4: 路由与控制器）。
  |
| 目标： | 
 了解如何使用异步模组与 Pug 样版语言，以及如何从我们的控制器函数中的
 URL 取得信息。
  |

概览
--

在我们先前的教程中，定义了可以用来跟资料库互动的 Mongoose models ，并创建了一些初始的图书馆记录。我们接着创建本地图书馆网站需要的所有路由 ，但仅使用"空壳控制器" 函数（这些是骨架控制器函数，当一个网页被存取时，只回传一个"未实现" 信息）。

下一步，是为这些显示图书馆信息的网页，提供适当的实现（我们将在后面的文章，聚焦网页表单的实现，像是创建、更新、删除信息）。这包含了更新控制器函数，以利用我们的模型获取记录，并定义模板，为用户显示这些信息。

我们在一开始，提供概述/入门主题，解释在控制器函数中，如何管理异步操作，以及如何使用 Pug 编写模板。然后我们将为每一个主要的 "只读" 页面提供实现步骤，并且在使用到任何特别的、新的特性时附上简短的解释说明。

本教程的最后，你对路由、异步函数、视图、模型如何实际运作，应该有了更好的理解。

本教程的章节
------

本教程分为下列章节，讲解了为了显示图书馆网站需求的页面而新增各种特性的过程。在进入下一个教程之前，你需要阅读并逐一实现下列章节。

1. 模版入门
2. 本地图书馆基础样版
3. 主页
4. 书本清单页面
5. 书本实例清单页面
6. 日期格式化 - 使用 moment
7. 作者清单页面、分类清单页面挑战
8. 分类详情页面
9. 书本详情页面
10. 作者详情页面
11. 书本实例详情页面挑战
总结
--

我们现在已经为我们的网站，创建了所有 "只读" 的页面：一个主页，可以显示每一个模组的实例数量，书本的列表与详细信息页面，书本的实例、作者、分类。沿着目前的学习路径，我们学到了许多基本知识，有控制器、在异步操作时管理流控制、使用 Pug 创建视图模板、使用模型查询数据库、如何从视图传送信息到模板、如何创建并扩展模板。而完成挑战的人，还会学到如何用 moment 处理日期。

在下一篇文章，我们将依据目前为止学到的知识，创建 HTML 表单以及表单管理代码，开始修改储存在网站中的资料。

参见
--

* Async 模组 (Async 模组官方文件)
* 在 Express 中使用模板引擎 (Express 官方文件)
* Pug (Pug 官方文件)
* Moment (Moment 官方文件)
* 上一页
* Overview: Express Nodejs
* 下一页
本地图书馆基础模板
=========

现在我们了解如何使用 Pug 拓展模板，让我们开始项目，创建一个基础模板。这个模板会有一个侧边栏，连结到本教程中将要创建的各个页面（例如，呈现并创建书本、种类、作者等等），以及一个主要内容区域，我们将在每个页面中进行覆写。

开启 **/views/layout.pug** ，并以下列代码置换其内容。


```pug
doctype html
html(lang='en')
  head
    title= title
    meta(charset='utf-8')
    meta(name='viewport', content='width=device-width, initial-scale=1')
    link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css')
    script(src='https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js')
    script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js')
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    div(class='container-fluid')
      div(class='row')
        div(class='col-sm-2')
          block sidebar
            ul(class='sidebar-nav')
              li
                a(href='/catalog') Home
              li
                a(href='/catalog/books') All books
              li
                a(href='/catalog/authors') All authors
              li
                a(href='/catalog/genres') All genres
              li
                a(href='/catalog/bookinstances') All book-instances
              li
                hr
              li
                a(href='/catalog/author/create') Create new author
              li
                a(href='/catalog/genre/create') Create new genre
              li
                a(href='/catalog/book/create') Create new book
              li
                a(href='/catalog/bookinstance/create') Create new book instance (copy)

        div(class='col-sm-10')
          block content
```


此模板使用（并包含）来自 Bootstrap 的 JavaScript 和 CSS，以改进 HTML 页面的布局和呈现方式。使用 Bootstrap 或其他客户端网页框架，是一种快速的方式，可以创建吸引人的网页，能够良好地适应不同的浏览器尺寸，并且允许我们处理页面的呈现，而不需要纠缠于任何不同尺寸的细节—此处我们只想专注于伺服端代码！

布局的安排应该相当明白，假如你已经阅读了之前的 模板入门。注意，使用 `block content` 当做定位符号，放到页面内容将要放置的地方。

基础模板也参考了一个本地 css 档 (**style.css**) ，此档提供了一些额外的样式。打开 **/public/stylesheets/style.css** ，并用底下的 CSS 代码，取代它的内容：


```css
.sidebar-nav {
  margin-top: 20px;
  padding: 0;
  list-style: none;
}
```


当我们开始运行网站时，我们应该看到侧边栏出现！在本教程的下个部分，我们将使用以上的布局，来定义各个页面。

下一步
---

* 回到 Express 教程 5: 呈现图书馆数据
* 继续教程 5 的下個部分：主页
书本列表页面
======

接下做我们将实作书本列表页面。这个页面需要呈现数据库中所有书本的列表，包含每本书的作者、标题，标题将成为一个超连结，连到书本详细内容页面。

控制器
---

书本列表控制器函数，需要获取数据库中所有`Book`对象的列表，然后将这些对象传给模板进行呈现。

打开 **/controllers/bookController.js**. 找到导出的 `book_list()` 控制器方法，并替换為下面的代码。


```js
// Display list of all Books.
exports.book\_list = function (req, res, next) {
  Book.find({}, "title author")
    .populate("author")
    .exec(function (err, list\_books) {
      if (err) {
        return next(err);
      }
      //Successful, so render
      res.render("book\_list", { title: "Book List", book\_list: list_books });
    });
};
```


该方法使用模型的`find()`函数返回所有`Book`对象，选择仅返回标题`title`和作者`author`，因为我们不需要其他字段（它也会返回`_id`和虚拟字段）。这里我们还调用`Book`上的`populate()` ，指定作者`author`字段 — 这将用完整的作者信息，替换存储的书本作者 id。

成功时，传递给查询的回调，将呈现 **book\_list**(.pug) 模板，将标题`title`和`book_list`（包含作者的書本列表）作为变量传递。

视图
--

创建 **/views/book\_list.pug** 并复制底下的文字。


```js
extends layout

block content
  h1= title

  ul
  each book in book_list
    li
      a(href=book.url) #{book.title}
      |  (#{book.author.name})

  else
    li There are no books.
```


這个视图扩展了 **layout.pug** 基本模板，并覆盖了名为 '**content**' 的區块 `block` 。它显示我们从控制器传入的标题`title`（通过`render()`方法），然后使用`each`-`in`-`else`语法，遍历`book_list`变量。为每本图书创建一个列表项，以显示书名，并作为书的详细信息页面的链接，后面跟着作者姓名。如果`book_list`中没有书，则执行`else`子句，并显示文字“没有书” 'There are no books.'。

**备注：** 我们使用 `book.url` ，为每本书提供详细记录链接（我们已经实现了此路由，但尚未实现此页面）。这是 `Book` 模型的一个虚拟属性，它使用模型实例的 `_id` 字段，生成唯一的 URL 路径。

在这里，我們感兴趣的是，每本书被定义为两行，第二行使用管道（上面高亮显示）。这种方法是必要的，因为如果作者姓名位于上一行，那么它将成为超链接的一部分。

它看起來像是？
-------

运行本应用 (参见 测试路由 有相关的命令) ，并打开你的浏览器，访问 http://localhost:3000/。然后选择 所有书本 连结。如果每样东西都设定正确了，你的网站看起来应该像底下的截图。

![Book List Page - Express Local Library site](/zh-CN/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Book_list_page/new_book_list.png)

下一步
---

* 回到 Express 教程 5: 呈现图书馆数据
* 继续教程 5 下个部分：书本实例列表页面
使用 moment 做日期格式化
================

我们模型的日期预设呈现很难看：*Tue Dec 06 2016 15:49:58 GMT+1100 (AUS Eastern Daylight Time)*。在本节中，我们将展示如何更新上一节中的 書本實例 BookInstance 列表页面，以更友好的格式显示`due_date`字段：December 6th, 2016。

我们将使用的方法，是在我们的`BookInstance`模型中，创建一个返回格式化日期的虚拟屬性。我们将使用moment 来做实际的格式化，这是一个轻量级 JavaScript 日期库，用于解析，验证，操作和格式化日期。

**备注：** 我们可以直接在 Pug 模板中，使用 *moment* 格式化字符串，或者可以在许多其他地方格式化字符串。使用虚拟属性，可以使我们获得格式化的日期，這与我们当前获取 `due_date` 的方式完全相同。

安装 moment
---------

在项目的根目录，输入下列命令


```bash
npm install moment
```

创建虚拟属性
------

1. 打开 **./models/bookinstance.js**.
2. 在此页面最上方，引用 moment

```js
var moment = require("moment");
```


在 url 属性后面，加入虚拟属性 `due_back_formatted` 。


```js
BookInstanceSchema.virtual("due\_back\_formatted").get(function () {
  return moment(this.due_back).format("MMMM Do, YYYY");
});
```


**备注：** 格式化方法可以使用几乎任何模式显示日期。moment 文档中，可以找到表示不同日期组件的语法。

更新视图
----

打开 **/views/bookinstance\_list.pug** ，然后用 `due_back_formatted` 取代 `due_back` 。


```js
      if val.status!='Available'
        //span (Due: #{val.due\_back} )
        span  (Due: #{val.due_back_formatted} )
```


这就是本章节的全部了。如果你访问侧边栏的 All book-instances，你应该会看到所有的归还日期都更吸引人了！

下一步
---

* 回到 Express 教程 5: 呈现图书馆数据
* 继续教程 5 下一個部分：作者列表页面、种类列表页面、与自我挑战