计划中的知识清单

版权声明:转载请注明出处 https://blog.csdn.net/sixkery/article/details/84584087

我计划自己写一个知识清单,当我有学过的东西忘记的时候我可以查看一下,本来是打算写到我的个人搭建的博客上面的,发现由于代码中有一些hexo不能识别的错误。因为写的比较多了就没有解决这个问题 就放到这里吧。
我的博客

字符串

  • split :用于分割字符串

Markdown 语法

网络地址

我的博客

图片地址

无序列表

  • 第一
  • 第二

这里是引用

表格

班级 男生 女生
一(7)班 30 25
一(8)班 25 30

Django

配置虚拟环境

虚拟环境(virtualenv 或 venv)是 Python 多版本管理的利器,可以使每个项目环境隔离起来,解决包之间的冲突。比如说一个项目用 Python 2 的版本,一个用 Python 3 的版本,这两个项目肯定不能混淆。简单来说,可以将虚拟环境看成一个隔绝的系统。

从Python3.3版本开始就自带了虚拟环境,不需要安装,配置一下就可以用了。

新建一个文件夹,用于存放项目的文件。

E:\Django>cd Django_blog

E:\Django\Django_blog>

输入配置venv的命令,其中的env为虚拟环境的放置文件。

E:\Django\Django_blog>python -m venv env

创建完成后,输入 env\Scripts\activate.bat,即可进入虚拟环境。

E:\Django\Django_blog> env\Scripts\activate.bat
(env) E:\Django\Django_blog>
  • 盘符前有(env)标识说明进入venv成功。

安装 Django

接着上面的,在虚拟环境下,输入命令:

扫描二维码关注公众号,回复: 4336388 查看本文章
(env) E:\Django\Django_blog>pip install django

'''
'''
Successfully installed django-2.1.3 pytz-2018.7

创建项目

接着上面的,在虚拟环境下,输入命令:

(env) E:\Django\Django_blog>django-admin startproject my_blog

然后看一下文件夹里的内容
发现多了一个 my_blog 的文件夹,这个就是我们的项目文件了。
接下来就可以运行看一下了,别急,还要说一下。

Django 自带一个轻量的 Web 开发服务器,叫做「runserver」。

  • 开发服务器是为了让你快速开发 Web 程序,通过它可以避开配置生产环境的服务器的繁琐环节。

  • 开发服务器会自动的检测代码的改变,并且自动加载它,因此在修改代码后不需要手动去重启服务器,非常的方便。

要运行这个 Django 服务器,首先要进入 my_blog 文件夹,即含有 manage.py 文件的那个:

(env) E:\Django\Django_blog\my_blog>python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).

You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
November 20, 2018 - 13:07:14
Django version 2.1.3, using settings 'my_blog.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

这样就开启了 django 服务啦!打开浏览器,输入 http://127.0.0.1:8000/ 就可以看到小火箭准备起飞啦!

创建 APP

在 Django 中,一个 APP 代表一个功能模块,可以将不同的功能模块放在不同的 APP 中,方便代码的复用,APP 就是一个项目的基础,所以说搭建博客的第一步就是创建一个 APP ,用来实现跟文章相关的功能模块。

在命令行进入到项目 my_blog 的目录下,输入命令:

(env) E:\Django\Django_blog>cd my_blog

(env) E:\Django\Django_blog\my_blog>python manage.py startapp article

看一下目录结构,这里是在 pycharm 中打开的:

my_blog
│  db.sqlite3
│  manage.py
│
├─article
│  │  admin.py
│  │  apps.py
│  │  models.py
│  │  tests.py
│  │  views.py
│  │  __init__.py
│  │
│  └─migrations
│          __init__.py
│
└─my_blog
    │  settings.py
    │  urls.py
    │  wsgi.py
    └─ __init__.py

其中 article 文件夹就是刚创建出来的 APP ,用来放置博客文章相关的代码。

注册 APP

创建出来 APP 之后要注册一下,跟 Django 说一下,我们新建了一个 APP 用来存放文章功能的代码。
打开 settings.py 文件,添加一行代码。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'article' # 激活创建的 APP
]

配置访问路径

然后再给APP配置访问的 url ,配置好url 之后 Django 才知道怎么定位 APP 。
在根目录的 url.py 中,添加代码:

from django.contrib import admin
# 引入include
from django.urls import path, include

# 存放映射关系的列表
urlpatterns = [
    path('admin/', admin.site.urls),
    # 配置 APP 的 url
    path('article/', include('article.urls',namespace='article')),
]
  • path 是 Django 的路由语法,参数 article/ 分配了 APP 的访问路径。
  • inclue 将路径分发给下一步处理。
  • namespace 可以保证返查到唯一的 url ,即使不同的 APP 使用了相同的 url (这个现在还不太懂,以后再说)。

现在已经通过 path 将路径 article\ 的访问都分发给 article 这个 APP ,但是APP通常有多个页面,比如说文章列表页,文章详情页等等,因此还要 APP 自己也有一个路由分发,也就是 article.urls 。

在 article 生成的时候没有这个文件,因此,我们要手动创建,然后输入:

from django.urls import path

# 正在部署的应用的名称
app_name = 'article'

urlpatterns = [
    # 目前还没有 urls
]

urlpatterns 里面现在是空的,我们要一步一步部署。

在 Django2.0 之后的版本中,urls.py 文件中,必须配置 app_name 否则会报错。

编写文章的模型(Model)

** Django 框架主要关注的问题是模型(Model)、模板(Template)和视图(Views),称为 MTV 模式。

它们各自的职责:

层次 职责
模型(Model)即数据存取层 处理与数据相关的事物:如何存取、如何验证有效性,包含哪些数据之间的关系等
模板(Template)业务逻辑层 出现与表现相关的决定:如何在页面或其他类型文档中进行显示
视图(Views)表现层 存取模型及调取恰当模板的相关逻辑。模型与模板的桥梁。

简单来说,就是 Model 存取数据,Views 决定要调取哪些数据,Template 负责把调取出来的数据以合理的方式展现出来。

在 Django 中写一个数据库驱动的 Web 应用的第一步是定义模型 Model ,也就是数据库结构设计和附加的其他元数据。

模型中包括了存储数据所必要的数据和行为。在 Django 中,只要定义了数据模型,其他的建表啦之类的不用我们自己动手操作,它会自动帮我们生成的。

所以先来写 Model。

编写 Model.py

Django 中一个模型(Model)映射一个数据库,用来处理数据相关的事务。

我们的博客网站来说最重要的就是文章了,所以建立一个存放文章的数据模型吧。

打开 article/model.py 文件,写代码:

from django.db import models
# 导入内建的 user 模型
from django.contrib.auth.models import User
# timezone 用来处理时间相关的事务
from django.utils import timezone

# 博客文章数据模型
class ArticlePost(models.Model):
    # 文章作者,参数 on_delete 用于指定删除数据的方式,避免两个关联表的数据不一致
    author = models.ForeignKey(User,on_delete=models.CASCADE)

    # 文章标题,参数 CharField 为字符串字段,用来表示较短的字符串
    title = models.CharField(max_length=100)

    # 正文内容,参数 TextField 表示较多的文本字段
    content = models.TextField()

    # 文章发表时间,参数表示默认当前时间
    created = models.DateTimeField(default=timezone.new)

    # 文章更改时间,参数表示自动写入当前时间
    updated = models.DateTimeField(auto_now=True)
    
  • 每个模型都被表示成 django.db.models.Model 类的子类,每一个模型都有一些类变量,(当然我们这里只写了一个)它们都表示模型里的一个数据库字段。
  • 每一个字段都是 Field 类的实例,比如字符串字段表示 CharField ,日期字段表示 DateTimeField 。这些告诉 Django 每个字段要处理的数据类型。
  • 使用 ForeignKey 定义一个关系。这告诉 django 每个(或多个)ArticlePost 对象都关联一个 User 对象。Django 本身具有一个完整的账号管理系统(User),足以满足一般网站的账号申请,建立,权限,群组等基本功能。

ArticlePost 类定义了一篇文章所需要的必备字段:作者,标题,文章,发表时间,更新时间。我们还可以增加一下内容,规范 ArticlePost 中数据的行为。

   # 函数 __str__ 定义当调用对象的 str() 方法时的返回值内容
    def __str__(self):
        return self.title  # 将文章标题返回回去

    # 内部类,用于给 model 定义元数据
    class Meta:
        # ordering 用于指定模块返回的数据顺序,「-craeted」表示以倒序排列
        ordering = ('-craeted',)
  • __str__ 方法定义了需要表示数据时应该显示的名称。给模型增加 __str__ 方法是很重要的,它最常见的就是在 Django 管理后台中做为对象的显示值。因此应该总是返回一个友好易读的字符串。后面会看到它的好处。
  • 内部类 Meta 中的 ordering 定义了数据的排列方式。-created 表示将以创建时间的倒序排列,保证了最新的文章总是在网页的最上方。注意ordering 是元组,括号中只含一个元素时不要忘记末尾的逗号。

ForeignKey 外键

ForeignKey 是用来处理「一对多」问题的,用于关联查询。
「一对多」,在我们的文章模型中,一篇文章只能有一个作者,但是一个作者可以有多篇文章。这就是「一对多」的关系。
因此,通过 ForeignKey 外键,将 User 和 ArticlePost 关联起来,最终的结果就是将网站的用户和文章的作者关联起来了。

有「一对多」,当然还有「一对一」(OneToOneField)和「多对多」(ManyToManyField)外键,这些到后面再理解吧。

注意这里有个小坑,Django2.0 之前的版本 on_delete 参数可以不填;Django2.0 以后 on_delete 是必填项,不写会报错。

内部类(Meta)

内部类 class Meta 用来使用类提供的模型元数据。模型元数据是「任何不是字段的东西」,例如排序选项 ordering、数据库表名 db_table、单数和复数名称 verbose_name 和 verbose_name_plural。要不要写内部类是完全可选的,当然有了它可以帮助理解并规范类的行为。

在 ArticlePost 中我们使用的元数据 ordering = (’-created’,),表明每当我需要取出文章列表,作为博客首页时,按照 -created(即文章创建时间,负号标识倒序)来排列,保证了最新文章永远在最顶部位置。


配置数据库

默认情况下,Django 使用的是 sqlite3 ,我们这里使用 MySQL 。
我这里使用的是 navicat for mysql ,是一个可视化管理 mysql 的工具。打开新建数据库 my_blog 。然后在 setting.py 文件中进行相关配置。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'my_blog',
        'USER':'root',
        'PASSWORD':'',# 这里输入密码
        'HOST':'127.0.0.1'
    }
}

配置之后,讲一下我遇到的坑,在之前创建虚拟环境之后,我用 pycharm 打开编辑。Python 的解释器用的是虚拟环境里面的 Python 解释器,但是发现并没有 Django 的安装包,当时觉得不正常,按理说应该是有的。一番查看发现,在项目里面 my_blog 里也有一个文件夹为 venv 。这也是一个虚拟环境,这里就有两个虚拟环境了,事实上这里的虚拟环境才是安装了 Django 包的虚拟环境,所以在这里安装包才起作用。

在settings.py 中配置之后,我们要安装一个连接数据库的驱动 mysqlclient 。在 Windows 系统上直接用 pip 命令是没有办法安装的,这里需要到这个网站 点这里 上下载后缀为 .whl 的文件,然后切换到上面说的虚拟环境中执行:

(venv) E:\Django\Django_blog\my_blog\venv\Scripts>pip install F:\Downloads\mysqlclient-1.3.13-cp37-cp37m-win_amd64.whl

后面的路径是你下载 .whl 文件存放的目录,这样就安装好了数据驱动。


数据迁移(Migrations)

编写好 Model 之后,就要进行数据迁移,迁移到哪呢,当然数据库里面了。

迁移是 Django 对模型所做的更改传递到数据库中的方式,所以说,每当对数据库进行了增加数据字段,删除字段,修改字段,删除字段等操作都要进行迁移。

Django 的迁移代码是由你的模型文件自动生成的,它本质上只是个历史记录,Django 可以用它来进行数据库的滚动更新,通过这种方式使其能够和当前的模型匹配。

在 pycharm 中,菜单栏上点击 Tools 然后点击 Run manage.py Task 。下方控制台输入:

manage.py@my_blog > makemigrations article

通过运行 makemigrations 命令,Django 会检测你对模型文件的修改,并且把修改的部分储存为一次迁移。

然后输入 migrate,应用迁移到数据库中:

manage.py@my_blog > migrate 
Running migrations:
  Applying contenttypes.0001_initial... OK
  ...
  ...

  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying sessions.0001_initial... OK

migrate 命令选中所有还没有被执行过的迁移,并应用在数据库上。也就是将模型的更改同步到数据库结构上。

迁移是非常强大的功能,它能让你在开发过程中持续的改变数据库结构,但是,不需要重新删除和创建表。它专注于使数据库平滑升级而不会丢失数据。

在迁移之后,对Model的编写就算完成了。

View 视图

Django 中的视图的概念是「一类具有相同功能和模板的网页集合」。比如说一个博客应用可能需要创建以下几个视图:

  • 博客首页:用来展示文章的的大概内容
  • 文章详情页面:用来展示具体文章的页面
  • 评论页面:查看文章的评论
    这些页面都要由 视图(View)来完成。

简单的视图(View)函数

写一个最简单的视图函数,在浏览器中打印 this is my blog

打开 article/views.py 文件,写以下代码:

# 导入 HttpResponse 模块
from django.http import HttpResponse

# 简单的视图函数
def article_list(request):
    return HttpResponse('This is my blog')

在 Django 中,网页都是从视图派生而来。每一个视图表现为一个简单的 Python 函数,它必须要做的只有两件事:返回一个包含被请求页面内容的 HttpResponse 对象,或者抛出一个异常,比如 Http404 。至于你还想干些什么,随便你。

视图函数中的 request 与网页发来的请求有关,里面包含 get 或 post 的内容、用户浏览器、系统等信息。Django 调用 article_list 函数时会返回一个含字符串的 HttpResponse 对象。

有了视图函数,还需要配置 URLconfs,将用户请求的URL链接关联起来。换句话说,URLconfs 的作用是将 URL 映射到视图中。

修改之前添加的article/urls.py就可以。添加以下代码:

from . import views

urlpatterns = [
    # path 函数将 url 映射到视图函数中
    path('article_list/',views.article_list,name='article_list'),
]

Django 将会根据用户请求的 URL 来选择使用哪个视图。本例中当用户请求 article/article-list 链接时,会调用 views.py 中的article_list 函数,并返回渲染后的对象。参数 name 用于反查 url 地址,相当于给 url 起了个名字,以后会用到。

测试一下刚才敲的代码是否工作正常。运行项目。

成功运行后,打开浏览器,输入 url 地址 http://127.0.0.1:8000/article/article_list/ ,其中127.0.0.1:8000 是调试服务器的本地地址,article 是项目路由my_blog\urls.py 分发的地址,article_list 是刚才配置的article\urls.py 应用分发的地址。

运气好的话,浏览器中会打印出This is my blog字符串。

准备工作

之前虽然编写了 Model 模型,映射到了数据库中,但是这些表中没有字段,是空的,不妨表展示 View 调取的结果,所以在写 View 之前,需要往数据库中增加些数据。

网站后台

网站后台,也叫网站管理后台,是指用于管理网站的一系列操作,像数据的增删改查,在项目开发的初期,因为没有真实的用户数据和测试环境,会频繁的使用网站后台修改测试数据。

Django 内置了一个非常强大的后台管理系统,只需要少量的代码就可以完成强大的功能。

创建管理员账号(Superuser)

管理员账号(Superuser)可以进入后台管理系统,对数据进行修改维护,具有很高的权限,创建一个账号,为后续测试数据使用。

这次不用命令行执行代码了,使用 pycharm 来执行,在菜单栏上点击 Tools 然后点击 Run manage.py Task 。下方控制台输入 createsuperuser

manage.py@my_blog > createsuperuser
"D:\pycharm\PyCharm 2018.2\bin\runnerw.exe" E:\Django\Django_blog\my_blog\venv\Scripts\python.exe "D:\pycharm\PyCharm 2018.2\helpers\pycharm\django_manage.py" createsuperuser E:/Django/Django_blog/my_blog
Tracking file by folder pattern:  migrations
Username (leave blank to use '19244'):  sixkery
Email address:  sixkery@163.com
Warning: Password input may be echoed.
Password:  
Warning: Password input may be echoed.
Password (again):  
Superuser created successfully.

指令会提示你输入账号名字、邮箱和密码,根据喜好填入即可创建成功。

将 ArticlePost 注册到后台

接下来告诉 Django ,后台中需要添加 ArticlePost 这个数据表供管理。
打开 article/admin.py ,写入以下代码:

# 导入 ArticlePost
from .models import ArticlePost

# 注册 ArticlePost 到 admin 中
admin.site.register(ArticlePost)

这样就可以了。

查看后台管理系统

细心的同学可能已经发现,Django 项目生成的时候就自动配置好了后台的settings 和 url,因此不需要我们再操心了。

启动 server,在浏览器中输入 http://127.0.0.1:8000/admin/ ,就可以看见后台界面了。

接着新建两篇文章看看。

切换到 navicat for mysql 中就可以查看到数据在 article_articlepost 表中。

这里没有截图,尽可能的可不放截图,遇到问题多思考,问谷歌就好。

改写视图函数(View)

之前写了一个视图函数,在浏览器上打印一句话,没有调用数据库里的数据,没有发挥视图函数的作用。现在改写一下:

# 导入数据模型
from .models import ArticlePost

# 简单的视图函数
def article_list(request):
    # 取出文章中的所有对象
    articles = ArticlePost.objects.all()
    # 需要传递给模板
    context = {'articles':articles}
    # render 函数,载入模板,并返回 context 对象
    return render(request,'article/list.html',context)

  • .models 表示从当前文件夹 models.py 中导入类 ArticlePost
  • ArticlePost.objects.all()从ArticlePost数据类获得所有的对象(即博客文章),并传递给articles变量
  • context定义了需要传递给模板的对象,即articles
  • 返回的render 函数
    • 第一个变量是固定的
    • 第二个变量定义了模板文件的位置
    • 第三个变量是传递的参数

完成收工。继续写模板函数

编写模板(Template)

还记得 MTV 模式吗,复习一下:

简单来说,就是 Model 存取数据,Views 决定要调取哪些数据,Template 负责把调取出来的数据以合理的方式展现出来。

合理的方式呈现出来。首先要新建模板文件(Template)。在上面的我们 render 函数定义了模板位置在 article/list.html 。在根目录下 my_blog 文件夹下新建 Templates 文件夹,在新建的 Templates 文件夹下新建 article 文件夹,然后再在新建的 article 文件夹下新建 list.html 文件。

这里有点多,慢慢理解。这是目录结构。

my_blog
│  ...
├─article
│  ...
└─my_blog
│  ...
└─templates
    └─ article
        └─ list.html

创建的是 HTML 文件,是一种创建网页的标记语言,它被用来结构化信息,区分从 models 中传递的信息,那些是标题,那些正文,并合理的呈现出来。也可以简单理解为「给数据排版」的文件,跟你写文章用的 Markdown 是一样的。

在 list.html 文件中写入:

    {% for article in articles %}
        <p>{{ article.title }}</p>
    {% endfor %}

作为一个 Web框架,Django 通过模板来动态生成 HTML ,其中就包含描述动态内容的一些特殊语法:

  • {% for article in articles %}:articles为视图函数的 context 传递过来的对象,即所有文章的集合。{% for %} 循坏表示依次取出 articles 中的元素,命名为 article ,并分别执行接下来操作。末尾用 {% endfor %} 告诉Django 循环结束的位置。

  • 使用 「.」 符号来访问变量的属性。这里的 article 为模型中的某一条文章;我们在前面的 ArticlePost 中定义了文章的标题叫 title ,因此这里可以用 article.title 来访问文章的标题。

  • <p>...</p> 即为 HTML 语言,中间包裹了一个段落的文字。

写完模板文件就可以运行了吗,可以试试。输入 http://127.0.0.1:8000/article/article_list/ 完了之后会报错。
这里是因为没有让 Django 知道我们创建的模板文件,所以需要在设置里配置。

打开 settings.py 文件,更改代码:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # 更改这里
        'APP_DIRS': True,
        '''
        '''

这样就「告诉」Django 模板的位置。

到这里,已经完全走通了 MTV(model、template、view)整个环路。

这是最基本的网站搭建流程,以后还会有更加复杂的逻辑加进来。

配置模板文件

之前说过,Template 模块需要把数据以合理的方式呈现出来,所以就需要用 HTML css js 等这些前端手段进行加工,咱一个后端工作者,这些东西没有接触过,是不会写的,不过没关系,我们从网上拿一些开源的来用就好了,那天心血来潮了在研究一下这些前端的知识。

配置 Bootstrap 4

Bootstrap 是用于网站开发的开源前端框架(「前端」指的是展现给最终用户的界面),它提供字体排印、窗体、按钮、导航及其他各种组件,旨在使动态网页和 Web 应用的开发更加容易。

Bootstrap 有几个版本都比较流行,我们选择最新版本的 Bootstrap 4:下载地址,并解压。

然后在项目根目录下新建目录 static/bootsrap/ ,用于存放 Bootstrap 静态文件。静态文件通常指那些不会改变的文件。Bootstrap 中的 css、js 文件,就是静态文件。

把刚才解压出来的 css 和 js 两个文件夹复制进去。

因为 bootstrap.js 依赖 jquery.js 和 popper.js 才能正常运行,因此这两个文件我们也需要一并下载保存。

至于怎么下载,看好了。

  • jquery.js 文件需要点击这个 链接 ,然后复制里面的内容,在 bootsrap 同级目录下新建文件夹命名为 jquery 。在文件夹里新建 jquery.js 文件,把复制的内容粘贴进去。完成。
  • popper.js 同理。点击这个链接 , 然后复制里面的内容,在 bootsrap 同级目录下新建文件夹命名为 popper 。在文件夹里新建 popper.js 文件,把复制的内容粘贴进去。完成。

现在的目录结构应该是这样的:

my_blog
│
├─article
└─my_blog
│ ...
└─static
    └─bootstrap
    │   ├─css # 文件夹
    │   └─js # 文件夹
    └─jquery
    │   └─jquery.js # 文件
    └─popper
        └─popper.js # 文件

因为在 Django 中需要指定静态文件的存放位置,才能够在模板中正确引用它们。因此在 settings.py 的末尾加上:

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

编写模板

在根目录下的 templates/ 中,新建三个文件:

  • base.html 是整个项目的模板基础,所有的网页都从它继承;
  • header.html 是网页顶部的导航栏;
  • footer.html 是网页底部的注脚。

这三个文件在每个页面中通常都是不变的,独立出来可以避免重复写同样的代码,提高维护性。

现在 templates\ 的结构像下面这个样子:

templates
│
├─base.html
├─header.html
├─footer.html
└─article
    └─list.html # 之前创建的

加上之前的 list.html ,我们要重新写这四个文件了。

因为前端知识非常博大精深,并且也不是 Django 学习的重点,所以这里直接写吧。

官网是最权威的文档。你可以在官方网站上进行系统的学习:

传送门

你可以试着改写其中的某段代码,看看会对页面产生什么样的影响;遇到不懂的就在Bootstrap官方文档找答案。慢慢就会明白它的运行机制,毕竟Bootstrap真的是非常简单易用的工具。

通篇去看 Bootstrap 文档会非常枯燥的,因此建议你可以像查字典一样的,需要用哪个模块,就到官网上找相关的代码,修改一下拷贝到你的项目中就可以了。用多了自然会明白每个字段的作用。

来吧,base.html

<!--载入静态文件-->
{% load staticfiles %}

<!DOCTYPE html>
<!--网站主语言-->
<html lang="en">
<head>
    <!--采用的编码-->
    <meta charset="UTF-8">
    <!--预留网站标题的位置-->
    <title>{% block title %}{% endblock %}</title>
    <!--引入 bootstrap 中的 css 文件-->
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
</head>
<body>
    <!--引入导航栏-->
    {% include 'header.html' %}
    <!--预留具体页面的位置-->
    {% block content %}{% endblock %}
    <!--引入注脚-->
    {% include 'footer.html' %}
   <!-- bootstrap.js 依赖 jquery.js 和popper.js,因此在这里引入 -->
    <script src="{% static 'jquery/jquery-3.3.1.js' %}"></script>
    <script src="{% static 'popper/popper-1.14.4.js' %}"></script>
    <!-- 引入bootstrap的js文件 -->
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</body>
</html>
  • 模板中要加上 {% load staticfiles %} 之后,才可使用 {% static ‘path’ %} 引用静态文件。
  • HTML语法中,所有的内容都被标签包裹;标签及标签中的属性可以对内容进行排印、解释说明等作用。
  • <head></head>标签内包含网页的元数据,是不会在页面内显示出来的。标签内才是网页会显示的内容。
  • 留意Bootstrap的css、js文件分别是如何引入的
  • jquery.js 和 popper.js 要在 bootstrap.js 前引入。

然后是header.html:

<!-- 定义导航栏 -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <div class="container">
    <!-- 导航栏商标 -->
    <a class="navbar-brand" href="#">我的博客</a>
    <!-- 导航入口 -->
    <div>
      <ul class="navbar-nav">
        <!-- 条目 -->
        <li class="nav-item">
          <a class="nav-link" href="#">文章</a>
        </li>
      </ul>
    </div>
  </div>
</nav>

标签内的 class 属性是 Bootstrap 样式的定义方法。试着改写或删除其中一些内容,观察页面的变化。

然后改写之前的 list.html:

<!-- extends表明此页面继承自 base.html 文件 -->
{% extends "base.html" %}
{% load staticfiles %}
<!-- 写入 base.html 中定义的 title -->
{% block title %}
    首页
{% endblock title %}
<!-- 写入 base.html 中定义的 content -->
{% block content %}
<!-- 定义放置文章标题的div容器 -->
<div class="container">
    <div class="row mt-2">
        {% for article in articles %}
        <!-- 文章内容 -->
        <div class="col-4 mb-4">
        <!-- 卡片容器 -->
            <div class="card h-100">
                <!-- 标题 -->
                <h4 class="card-header">{{ article.title }}</h4>
                <!-- 摘要 -->
                <div class="card-body">
                    <p class="card-text">{{ article.body|slice:'100' }}...</p>
                </div>
                <!-- 注脚 -->
                <div class="card-footer">
                    <a href="#" class="btn btn-primary">阅读本文</a>
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
</div>
{% endblock content %}
  • 留意 {% block title %} 和 {% block content %} 是如何与base.html 中相对应起来的。
    摘要中的 {{ article.body|slice:‘100’ }} 取出了文章的正文;其中的 「|slice:‘100’」 是 Django 的过滤器语法,表示取出正文的前 100 个字符,避免摘要太长。

最后写入footer.html:


{% load staticfiles %}
<!-- Footer -->
<div>
    <br><br><br>
</div>
<footer class="py-3 bg-dark fixed-bottom">
    <div class="container">
        <p class="m-0 text-center text-white">Copyright &copy; sixkery 2018</p>
    </div>
</footer>

让我们来捋一捋发生了什么:

  • 当我们通过 url 访问 list.html 时,顶部的 {% extends “base.html” %} 告诉 Django :“这个文件是继承 base.html 的,你去调用它吧。”

  • 于是 Django 就老老实实去渲染 base.html 文件:

    • 其中的 {% include ‘header.html’ %} 表明这里需要加入 header.html 的内容
    • {% include ‘footer.html’ %} 加入 footer.html 的内容
    • {% block content %}{% endblock content %} 表明这里应该加入 list.html 中的对应块的内容

好运的话,就会看到不那么丑的博客了。


继续编写视图函数

前面写了一个文章列表的视图函数,这里添加一个文章详情页的函数。

打开 article/views.py 文件,添加文章详情页函数

def article_detail(request,id):
    # 取出相应的文章
    article = ArticlePost.objects.get(id=id)
    # 需要传递给模板的对象
    context = {'article':article}
    # 载入模板,并返回 context 对象
    return render(request,'article/detail.html',context)
  • article_detail(request, id) 函数中多了 id 这个参数。注意我们在写 model 的时候并没有写叫做 id 的字段,这是 Django 自动生成的用于索引数据表的主键(Primary Key,即pk)。有了它才有办法知道到底应该取出哪篇文章。
  • ArticlePost.objects.get(id=id) 意思是在所有文章中,取出 id 值相符合的唯一的一篇文章。

然后编写 article/urls.py ,配置文章详情页的路由。

    # 文章详情页的视图
    path('article_detail/<int:id>',views.article_detail,name='article_detail'),
  • <int:id> :Django2.0 的 path 新语法用尖括号「<>」定义需要传递的参数。这里需要传递的参数是 id 的整数到视图函数中去。

注意在老的 Django 版本中,没有 path 这种语法的

编写文章详情页的模板

在 template/article 文件夹中新建 detail.html 文件。

<!--extends 表明此页面继承自 base.html-->
{% extends 'base.html' %}
{% load staticfiles %}

<!--写入 base.html 中定义的 title-->
{% block title %}
    文章详情
{% endblock title %}
<!--写入 base.html 中定义的 content-->
{% block content %}

<!--文章详情-->
<div class="container">
    <div class="row">
        <!--标题及作者-->
        <h1 class="col-12 mt-4">{{ article.title }}</h1>
        <div class="col-12 alert alert-success">作者:{{ article.author }}</div>
        <!--文章正文-->
        <div class="col-12">
            <p>{{ article.content }}</p>
        </div>
    </div>
</div>

{% endblock content %}

这里我们用 {{ article.xxx }} 取出了文章标题、作者以及正文。

前面我们已经通过后台创建了几篇文章,这里将取出id为1的一篇文章测试效果。

运行开发服务器后,在浏览器中输入
http://127.0.0.1:8000/article/article_detail/1/ 就可以看到文章详情页的内容了。

优化网页入口

我们手写 url 有点不太人性化,改一下,可以通过 导航栏右侧的文章进入首页。

改写 header.html :

  <li class="nav-item">
            <!-- 改写了这里的 href -->
          <a class="nav-link" href="{% url 'article:article_list' %}">文章</a>
        </li>

注意这里的 href 是如何改写的:

  • href 定义了链接跳转的地址
  • {% url … %} 是 Django 规定的模板解耦语法,用它可以根据我们在 urls.py 中设置的名字,反向解析对应的 url 中去。
  • 关于 article:article_list 的解释:
    • article 表示在项目根目录下 url.py 中定义的 APP 名称
    • article_list 表示在 APP 中 urls.py 中定义的具体的路由地址

通过这样的方法就将链接跳转的指向给配置好了,只要对应 url 的名称不变,url 本身无论怎么变化,Django 都可以解析到正确的地址,很灵活。

当然你也可以直接在 href 中写入 url 的地址,但是一旦 url 有变化,所有相关的链接都会失效,维护性不好。

然后再改写 list.html,让用户可 点击阅读本文 按钮进入文章详情:

<!-- 同样改写 href -->
<a href="{% url 'article:article_detail' article.id %}" class="btn btn-primary">阅读本文</a>

注意文章的 id 是如何传递的:

  • 在 list.html 中,通过 href="{% url ‘article:article_detail’ article.id %}" ,将 id 传递给article/urls.py
  • 在article/urls.py中,通过int:id传递给视图函数article_detail()
  • 在视图函数article_detail()中,通过形参id取得了文章的id值,并进行处理,最终定位了需要获取的文章对象

现在我们可以通过链接访问网站上的不同页面了,而不需要手动输入url。当然这也是现代网站的基础。

使用 Markdown 语法书写文章

自从我知道这种轻量级的标记语言后,基本上写的东西没有不是用它写的。简直太好用了,包括后来使用 sublime Text3 ,发现插件对 Markdown 支持不好,果断卸载,安装 vs code 。我的觉得这是程序员写技术文章的必备。

安装 Markdown

这里在介绍一下,Markdown 是一种轻量级的标记语言,它允许人们“使用易读易写的纯文本格式编写文档,然后转换成有效的或者 HTML 文档。建议读者一定要花五分钟时间熟悉一下 Markdown 的语法,熟练后码字效率一定会大幅提高。

关于 Markdown 语法看这里:Markdown 语法介绍

安装markdown也很简单:进入虚拟环境,输入指令pip install markdown即可。

使用 Markdown

为了将 Markdown 语法书写的文章渲染成 HTML 文本,首先要修改 article/views.py 文件的 article_detail 函数

    # 将 Markdown 语法渲染成 HTML 格式
    article.content = markdown.markdown(article.content,
        exts=[
            # 包含表格,标题,无序等常用扩展
            'markdown.extensions.extra',
            # 语法高亮扩展
            'markdown.extensions.codehilite',
        ])
    # 需要传递给模板的对象
    context = {'article':article}

代码中 markdown.markdown 语法接收两个参数:

  • 第一个参数是需要渲染的文章正文 article.body
  • 第二个参数载入了常用的语法扩展,markdown.extensions.extra 中包括了缩写、表格等扩展,markdown.extensions.codehilite 则是后面要使用的代码高亮扩展。

然后,修改 templates/article/detail.html 中有关文章正文的部分:

<div class="col-12">
    <!--在 article.content 后加上 |safe 过滤器-->
    <p>{{ article.content|safe }}</p>
</div>

Django 出于安全的考虑,会将输出的 HTML 代码进行转义,这使得article.content 中渲染的 HTML 文本无法正常显示。管道符 「|」 是 Django 中过滤器的写法,而 |safe 就类似给 article.content 贴了一个标签,表示这一段字符不需要进行转义了。

这样就把 Markdown 语法配置好了。

启动服务器 http://127.0.0.1:8000/admin/ ,在后台中新录入一条用 markdown 语法书写的文章。


Markdown 这里先打住,自己配置的时候没有找到很好的方式来做。结果并没有实现效果。以后解决掉这个问题再来补充。


使用 form 表单发表文章

之前的文章是在后台录入的,那怎么样才能在网页上直接写呢。比如说普通用户也想写博客,怎么办?

forms 表单类

在 HTML 中,表单是「<form>...</from>」中的一些元素。它允许访客做一些提交信息的操作,比如说输入文本,输入账号密码,选择选项等这些,然后发送这些信息到服务端。一些表单界面元素非常简单(文本框复选框),直接嵌在 HTML 中。其他一些较为复杂,像日期选择等操作控件。

处理表单是一件复杂的事,在 admin 里面,需要把不同的数据类型显示出来,并且渲染成 HTML 。使用方便的编辑器编辑,并把它传到服务器。

Django的表单功能可以简化上述工作的大部分内容,并且也能比大多数程序员自己编写代码去实现来的更安全。

Django 表单系统的核心组件是类 form 类,它能够描述一张表单并决定它如何在页面中呈现。

实现 form 类,需要在 article/ 中创建 form.py 文件。

# 引入表单类
from django import forms
# 引入文章模型
from .models import ArticlePost

# 写文章的表单类
class ArticlePostForm(forms.ModelForm):
    class Meta:
        # 指明数据集的来源
        model = ArticlePost
        # 定义表单包含的字段
        fields = ('title','content')

  • 代码中 ArticlePostForm 类继承了 Django 的表单类 forms.ModelForm
  • 内部类的作用是规范类的数据行为。这里指明了数据集的来源以及表单中应该有哪些字段。
  • 在 ArticlePost 类中,created 和 updated 是自动生成的,不需要填入内容。anthor 字段暂定为固定值 id = 1 的管理员用户。

接下来更改 article/views.py ,添加一个视图函数以处理写文章的要求。

# 写文章的视图函数
def article_create(request):
    # 判断用户是否提交数据
    if request.method == 'POST':
        # 将提交的数据赋值到表单实例中
        article_post_form = ArticlePostForm(data=request.POST)
        # 判断提交的数据是否满足模型的要求
        if article_post_form.is_valid():
            # 保存数据,但是暂时不保存到数据库
            new_article = article_post_form.save(commit=False)
            # 指定数据库中 id = 1 的作者
            new_article_author = User.objects.get(id=1)
            # 将新文章保存到数据库中
            new_article.save()
            return redirect('article:article_list')

        else:
            return HttpResponse('表单填写有误,请重新填写')
    else:
        article_post_form = ArticlePostForm()
        context = {'article_post_form':article_post_form}
        return render(request,'article/create.html',context)

当视图函数接收到客户端传递的 request 时,根据 request.method 来判断 用户是提交数据(POST)还是获取数据(GET)

  • 如果用户是提交数据,将POST给服务器的表单数据赋于article_post_form实例。

    • 然后使用Django内置的方法.is_valid()判断提交的数据是否满足模型的要求。

      • 如果满足要求,保存表单中的数据(但是commit=False暂时不提交到数据库,因为author还未指定),并指定author为id=1的管理员用户。然后提交到数据库,并通过redirect返回文章列表。redirect可通过url地址的名字,反向解析到对应的url。

      • 如果不满足要求,则返回一个字符串“表单内容有误,请重新填写。”,告诉用户出现了什么问题。

    • 如果用户是获取数据,则返回一个空的表单类对象,提供给用户填写。

写好视图之后,就需要写模板文件了。在templates/article/中创建create.html:

猜你喜欢

转载自blog.csdn.net/sixkery/article/details/84584087