vlambda博客
学习文章列表

Django2.2架构+ubuntu16(华为云)+python3.6架设“文学天地”个人网站

项目简介

  • 项目是基于Django2.2+ubuntu16(HuaWei cloud)+python3.6开发的初学者博客网站项目

  • 网站上线使用Apache2 Web服务 (后续更新)

  • 若手机观看不便,可点击下面的阅读全文,转到CSDN文章在浏览器打开,复制链接到PC端,方便阅读!

  • 效果图如下图所示:

目录


文章目录

    • 项目简介

    • 目录

    • 项目搭建过程

      • 环境搭建

    • 从零开始搭建

      • 1. 进入虚拟环境

      • 2. pip安装django2.2

      • 3. 创建一个空白项目

      • 4. 测试空项目

      • 5. 创建个人博客

        • 1) 修改settings.py

        • 2) 建立数据库

        • 3) 启用admin界面

        • 4) 读取数据库内容

        • 5) 建立网页输出模板template


项目搭建过程

环境搭建

  1. ubuntu16安装python3.6

  2. 安装git

  3. 安装python3.6

  4. 安装pip3+virtualenv

  5. clone repositories

  6. 安装python库

  7. python manage.py runserver 0.0.0.0:8000

从零开始搭建

1. 进入虚拟环境

执行环境搭建到第4后,进入虚拟环境:

source venvpy3/bin/activate

2. pip安装django2.2

pip install django==2.2

检查是否安装到虚拟环境中
pip list
如果没有安装到虚拟环境中安装到了全局中,可以指定pip库
此时可以通过 venv\scripts\python -m pip -V 或 venv\scripts\pip -V 指定pip命令的路径。
下载时同样通过venv\scripts\python -m pip install 进行下载。
检查是否安装到虚拟环境中
pip list
如果没有安装到虚拟环境中安装到了全局中,可以指定pip库
此时可以通过 venv\scripts\python -m pip -V 或 venv\scripts\pip -V 指定pip命令的路径。
下载时同样通过venv\scripts\python -m pip install 进行下载。

3. 创建一个空白项目

	django-admin startproject myblog
cd myblog
python manage.py startapp mainsite
cd ..
tree myblog

myblog/
├── mainsite
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── manage.py
└── myblog
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-36.pyc
│ └── settings.cpython-36.pyc
├── settings.py
├── urls.py
└── wsgi.py

4. 测试空项目

创建之前需要migrate一下

	(venvpy3)test/myblog$ python manage.py migrate
(venvpy3) lhw@ecs:~/literaryworld/test/myblog$ python manage.py runserver 0.0.0.0:9000

网页登录你的公网ip:9000,报错,提示该ip被拒绝访问,修改~/test/myblog/myblog/setting.py

建议使用Notepad++修改

将上述文档修改成下面:

	ALLOWED_HOSTS = []  #原数组
ALLOWED_HOSTS = ['*',]#修改后,'*'表示允许所有ip访问该网页,也可填写具体ip

修改后保存再执行

	(venvpy3) lhw@ecs:~/literaryworld/test/myblog$ python manage.py runserver 0.0.0.0:9000

刷新界面,表示成功!

Django2.2架构+ubuntu16(华为云)+python3.6架设“文学天地”个人网站

5. 创建个人博客

1) 修改settings.py

settings.py是此网站的系统设计所在位置,新建立的网站都要先开放此档案,做些编辑设定工作。而真正网站所有的运作的逻辑,则是在使用startapp mainsite建立出来的APP文件夹中。使用这种方式,主要目的是让网站的每一个主要功能都成为一个单独的模组,方便网站的开发者可以在不同的网站中重复使用,也就是复用。

首先,我们将之前建立的APP模组mainsite加进去:(在settings.py的INSTALLED_APPS列表中)

# Application definition

INSTALLED_APPS = [
'django.contrib.admin', #内置后台管理系统
'django.contrib.auth', #内置的用户认证系统
'django.contrib.contenttypes', #记录项目中所有的model元数据(Django的orm框架)
'django.contrib.sessions', #会话功能,用于标识当前访问网站的用户身份,记录相关的用户信息
'django.contrib.messages', #消息提示功能
'django.contrib.staticfiles', #查找静态资源路径
'mainsite', #项目创建的mainsite app
'markdown_deux', #markdown支持
]

将系统默认时区改为中国时区:

LANGUAGE_CODE = 'zh-Hans' #2.0改版后zh_Hans改为zh-Hans

TIME_ZONE = 'Asia/Shanghai'

另外,在预设的情景下,Django会使用SQLite来储存资料库内容,在使用以下命令时,会产生叫做db.sqlite3的文档

(venvpy3) lhw@ecs:~/literaryworld/test/myblog$ python manage.py makemigrations
(venvpy3) lhw@ecs:~/literaryworld/test/myblog$ python manage.py migrate

之后,所有在此网站中新增到数据库的数据,都会被放在db.sqlite3这个文件中,这是一个简化过的文件型SQL开放式数据库系统,如果网站要搬移,一定带上这个文件。

2) 建立数据库

在预设的情况下,Django的数据库是以Model的方式来操作,也就是不直接操作数据库及数据表,而是以class类的方式建立出Model,然后再透过对Model的操作,连接到数据库的目的。

因此,在Django要使用数据库,有以下步骤:

  1. 在models.py中定义所需要使用的类别(继承自models.Model)

  2. 详细地设定每一个在类中的变量

  3. 使用python manage.py makemigration mainsite建立数据库和Django间的中间档案

  4. 使用python manage.py migrate同步更新数据库的内容

  5. 在程序中使用python的语法操作所定义的数据类别,等于是在操作数据库中的数据表

建立博客,需要一个用来存储文章的数据表,所以,就需要修改mainsite/models.py的内容。一开始,models.py的内容如下:

from django.db import models

# Create your models here.

修改为如下内容:

from django.db import models
from django.utils import timezone
# Create your models here.

class Post(models.Model):
title = models.CharField(max_length=200) #文章标题
slug = models.CharField(max_length=200) #文章网址
body = models.TextField() #文章内容
pub_date = models.DateTimeField(default=timezone.now) #发表日期

class Meta:
ordering = ('-pub_date',) #根据发表日期排序

#提供此类别所产生的资料项目,以文章标题当做是显示的内容,Unicode标题可以支持中文标题(在python3中使用str)
def __str__(self):
return self.title

在这里主要建立一个叫做Post的类别(会在数据库中会有一个对应的数据表),在此类中包括几个项目,title是用来表示文章标题,而slug则是文章的网址,body则是文章的内容,最后pub_date则是本文发表的时间。至于class Meta内的设定,则是指文章要显示的顺序是以pub_date为依据,最后 __ str __ 则是提供此类别所产生的数据项目,以文章标题作为显示内容,增加操作过程的可读性。要提醒的是在django 2.0以后,使用str才能正常支持中文,在之前版本可能需要使用__ unicode __。

pub_date是以timezone.now的方式让它自动产生,这需要一个pytz模组才行。

此时即可在程序中直接操作此数据库了。但是为了方便,需要启用django提供的admin界面来操作,会更加方便。

3) 启用admin界面

admin是Django预设的数据库内容管理界面,在使用之前,有几个步骤,第一步,是建立一个管理者的账号及密码,如下所示:

(venvpy3) lhw@ecs-sn3-medium-2-linux-20200115102149:~/literaryworld/test/myblog$ python manage.py createsuperuser
用户名 (leave blank to use 'lhw'): admin
电子邮件地址:
Password:
Password (again):
Superuser created successfully.

接着,将上一步定义的Post纳入管理,需要修改mainsite/admin.py,原本是如下所示的内容:

from django.contrib import admin

# Register your models here.

修改为如下内容:

from django.contrib import admin
from .models import Post
# Register your models here.
#先引入Post类别,然后再透过admin.site.register注册即可。
#然后通过http://host:8000/admin,即可登录
class PostAdmin(admin.ModelAdmin):
list_display=('title','slug','pub_date')
admin.site.register(Post,PostAdmin)

先引入我们的Post类别,通过admin.site.register注册即可。完成设定之后再次启用此网站,然后通过浏览器连接到http://localhost:9000/admin,就可以看到下面所示界面

此时在admin.py中加入PostAdmin类的代码(自订Post显示的方式类别,继承自admin.ModelAdmin),让文章在显示的时候,除了title之外,还可以再加上张贴的日期和时间等内容

Django2.2架构+ubuntu16(华为云)+python3.6架设“文学天地”个人网站

Django预设的admin管理界面之登录界面

在输入之前设定的账号和密码之后,即可看到数据库管理界面,如下图所示

Django2.2架构+ubuntu16(华为云)+python3.6架设“文学天地”个人网站

在Posts类增加数据表,增添完文章后点击右下角保存,

Django2.2架构+ubuntu16(华为云)+python3.6架设“文学天地”个人网站

新增文章的界面

若点击保存后出现错误,提示`no such table: mainsite_post`,说明数据库文件出现问题,可执行`python manage.py migrate`

保存四五篇诗文之后,内容中英文皆可,但是slug要使用英文或数字,而且中间不要使用任何符号以及空白字元,显示如下:

Django2.2架构+ubuntu16(华为云)+python3.6架设“文学天地”个人网站

admin界面输入的文章

4) 读取数据库内容

资料库中有了文章内容之后,接下来就是读取这些资料,然后在网站的首页中把它们显示出来。

MTV:
M model -> models.py; T template -> template文件夹; V view -> views.py;
models.py负责定义要存取的资料类型,以class类别方式定义,后端Django自动把 设定对应到资料库系统中
如果将资料拿出来,或者如何存进去的这些程式逻辑,则在views.py中处理
如何把这些取到的资料用美观有弹性的方式输出,则是在Template中加以处理

因此,先打开mainsite/view.py,一开始的内容如下:

from django.shortcuts import render
# Create your views here.

改成下列内容:

#from django.shortcuts import render
from django.http import HttpResponse
from .models import Post
from django.template.loader import get_template
from datetime import datetime
from django.shortcuts import redirect
# Create your views here.

#考虑到有可能会有自行输入错误网址以至于找不到文章,除了在Post.objects.get(slug=slug)搜索文章时加上例外处理,
#也在发生例外的时候以redirect('/')方式直接返回首页


'''
# 将models.py中自定义的model引入,然后使用Post.objects.all()取得所有的资料项目,然后用for遍历所有内容
#透过HttpResponse输出到网页中
##
#再次理中建立homepage函数获取所有文章,并通过遍历把内容存储到一个变量post_lists中,再使用
#return HttpResponse(post_lists)输出到网页上
#
#设置完函数后,透过urls.py来负责网址和程序间的对应工作。开放urls.py,分别引入来自于views.py的
#homepage函数并以url对应之
def homepage(request):
posts = Post.objects.all()
post_lists = list()
for count,post in enumerate(posts):
post_lists.append("No.{}:".format(str(count))+str(post)+"<hr>")
post_lists.append("<small>"+str(post.body)+"</small><br><br>")
return HttpResponse(post_lists)
'''


def homepage(request): #主页面
template = get_template('index.html')
posts = Post.objects.all()
now = datetime.now()
html = template.render(locals())
return HttpResponse(html)

def showpost(request,slug): #诗歌界面
template = get_template('post.html')
try:
post = Post.objects.get(slug=slug) #匹配传入参数与资料库中的slug
if post!= None:
html = template.render(locals())
return HttpResponse(html)
except:
return redirect('/') #错误直接返回首页

在此,我们使用homepage来做为我们网站的主界面,template = get_template('index.html')获取模板index.html的信息,并通过Post.objects.all()获取数据库中所有项目,通过locals()将所有变量打包成键值对,通过template.render(locals())将变量自动填充到html模板中,然后通过return HttpResponse(html),输出到客户端的浏览器界面中。

其中showpost类似,只是仅匹配request对应文章slug对应的文章内容,并填充到对应的post.html模板中去显示文章。(模板我们后面介绍)

有了这些函数,需要透过urls.py来负责网址和程序间的对应工作,否则,无法匹配到对应的函数。打开urls.py,分别引入来自views.py的homepage和showpost函数,如下所示:

from django.contrib import admin
from django.urls import path
from django.conf.urls import include,url
from mainsite.views import homepage,showpost


#其中,url(r'^$',homepage)这一行中,^表示字符串开始处,$表示字符串结尾处,
#两者接在一起就是,当有使用者浏览了网址而没加上任何字符串的时候即(根网址)
#就去呼叫homepage这个函数
#
urlpatterns = [
url(r'^$',homepage),
url(r'^post/(\w+)$',showpost),
#通过r'^post/(\w+)$'将post/后面的字符找出来并将作为第二个参数传递给showpost,第一个参数是request
path('admin/', admin.site.urls),
]

其中,url(r'^$' ,homepage)这一行中,^ 表示字符串开始处,$表示字符串结尾处,两者接在一起就是,当有使用者浏览了网址而没加上任何字符串的时候即(根网址)就去呼叫homepage这个函数,showpost类似。

5) 建立网页输出模板template

每一个输出的网页都可以变为一个或一个以上对应的模板,而这些模板是以.html的文件形式储存在指定文件夹中(一般命名为templates),当网站有资料需要输出的时候,再通过渲染函数(render)把资料放到模板指定位置中,得到结果 再交给HttpResponse输出给浏览器。步骤如下所示:

  • 在setting.py中设定模板资料夹的位置

  • 在urls.py建立网址和views.py中函数对应的关系

  • 建立.html档案(例如index.html),做好排版并安排资料要放的位置

  • 执行程序,以objects.all()views.py取得资料,并放入变量中,例如posts

  • 以render函数,把资料(例如posts)送到指定模板文件(如index.html)中

a. 首先在~/test/myblog文件夹中创建templatesstatic文件,templates文件夹用来存放基础html模板如header.html、footer.html、base.html等基础模板,static文件夹用来存放静态加载文件,如images等;

b. 在~/test/myblog/mainsite文件夹中创建templates作为项目APP mainsite的专属html模板

建立文件夹后文件结构如下所示:

(venvpy3) lhw@ecs-sn3-medium-2-linux-20200115102149:~/literaryworld/test$ tree myblog/
myblog/
├── db.sqlite3
├── mainsite
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── 0001_initial.cpython-36.pyc
│ │ └── __init__.cpython-36.pyc
│ ├── models.py
│ ├── __pycache__
│ │ ├── admin.cpython-36.pyc
│ │ ├── __init__.cpython-36.pyc
│ │ ├── models.cpython-36.pyc
│ │ └── views.cpython-36.pyc
│ ├── templates
│ ├── tests.py
│ └── views.py
├── manage.py
├── myblog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ ├── settings.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ └── wsgi.cpython-36.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── static
└── templates

9 directories, 24 files

 Templates

然后将此文件夹加到settings.py的TEMPLATES数组里面,如下所示:

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',
],
},
},
]

 静态文件

而在布局网站的时候不可避免加载一些图片或者.css或者是.js文件。一般,图形文件放在images文件夹下,而.css和.js文件会被放在css和js文件夹下。传统网站系统,只要指定这些文件夹在网址上,就可以顺利存取。但是对.py文件来说是属于不需要被另外处理的静态文件,为了网站运作效率,Django将这一类型的文档统称为static file(静态文件),另外加以安排。因此为了能够在网站中顺利存取这些文件,首先在setting.py中特别指定静态文件要放置的位置。我们将这些文档(.js, .css, .jpg, .png等)都放在static文件夹下,图片文件放到images子目录,.css放到css子目录等。在settings.py加入以下代码:

STATIC_URL = '/static/'
STATICFILES_DIRS=[
os.path.join(BASE_DIR,'static'),
]

 共用模板

每一个网站在每一页都会有一些共同的元素加以强调风格,如果将共同的部分独立出来成为另外一个文档,在使用时加以调用将使建站更加快速有效。

而在本次网站,采用以下.html文件:

文件名称 文件说明
base.html 网站的基础模板,提供网站的主要设计外观风格
header.htm 网站中每一个网页共用的标题元素,通常是放置网站logo的地方
footer.html 网站中每一个网页的共用页尾,用来放置版权声明或是其他参考咨询
index.html 此范例网站的首页
post.html 此范例网站用来显示单篇文章的网页

base.html

 base.html主要功能是构建网页的基础框架和外观风格。base.html的内容如下:

<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>
{% block title %}{% endblock %}
</title>
<!--
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
-->

<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>

<body>
<!--在bootstrap中,规定了每一行都被分为了固定的12个栅栏,每一个栅栏都有自己的宽度。如果你的div用了container的样式,
那么它的宽度最大也大不过12个栅栏总共的最大宽度。而,当你的div用了container-fluid的样式,它会无视12个栅栏的规定,根据屏幕自动适应自动填充。
(当然,宽度要设置为width:100%)。
-->

<div class='container-fluid'>
{% include 'header.html' %}
<div class='row'>
<div class='col-sm-4 col-md-4'> <!--行分为12列.col-md-xx 数字所占列数-->
<div class='panel panel-default'>
<div class='panel-heading'> <!--带 title 的面板标题-->
<h3>MENU</h3>
</div>
<div class='panel-body'>
<!--在任何面板中包含列表组,通过在 <div> 元素中添加 .panel 和 .panel-default 类来创建面板,并在面板中添加列表组-->
<div class='list-group'>
<a href='/' class='list-group-item'>HOME</a>
<a href='https://www.baidu.com/' class='list-group-item' target='_blank'>百度</a>
<a href='http://www.nlc.cn/' class='list-group-item' target='_blank'>国家图书馆</a>
<a href='https://github.com/liu6010/myblog' class='list-group-item' target='_blank'>github</a>
</div>
</div>
</div>
</div>
<div class='col-sm-8 col-md-8'> <!--行分为12列.col-md-xx 数字所占列数-->
<div class='panel panel-default'>
<div class='panel-heading'> <!--带 title 的面板标题-->
{% block headmessage %}{% endblock %}
</div>
<div class='panel-body'>
{% block content %}{% endblock %}
</div>
<!--在面板中添加脚注,只需要把按钮或者副文本放在带有 class .panel-footer 的 <div> 中即可。-->
<div class='panel-footer'>
{% include 'footer.html' %}
</div>
</div>
</div>
</div>
</div>
</body>
</html>

在此例中,就是一般的html文件,再加上{% block title %}的模板命令,在这些模板指令中,没有意外,使用include 'base.html'(此例引入base模块)即可引入指定的模板文件,在base.html中的<body></body>中引入了{% include 'header.html' %}{% include 'footer.html' %}。此外通过block指令可以在后面加上此block的名称,也就是到时候在index.html中要填入内容的位置。在此base.html中,分别在适当的地点指定了titleheadmessagecontent。因为在base.html指定了这3个区块,所以接下来继承此base.html的任何文档都要提供这三个区块的内容才行。

同时随着HTML5和CSS3和Javascript的功能日益复杂,一个网站不可能一点一点自己设计,大部分使用一些现成的网页框架,直接套用并修改后完成。免费的网页框架不少,但是Bootstrap最受欢迎,可以直接下载到本地端加以连接执行,也可以直接利用CDN连接方式套用。在</head>前添加一下代码:

<link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>

关于bootstrap栅栏系统css中的理解:

<div class="container">
<div class="row">
<div class="col-md-4">col-md-4</div>
<div class="col-md-4">col-md-4</div>
<div class="col-md-4">col-md-4</div>
<!-- 说明:每row行共12列,分个3div,每个div平占4列,即3个*4列=12列 -->
</div>
<div class="row">
<div class="col-md-4">col-md-4</div>
<div class="col-md-8">col-md-8</div>
<!-- 说明:每row行共12列,分个2div,第1个div占4列,第2个div则占8列,即4列+8列=12列 -->
</div>
<div class="row">
<div class="col-md-3">col-md-3</div>
<div class="col-md-6">col-md-6</div>
<div class="col-md-3">col-md-3</div>
<!-- 说明:每row行共12列,分个3div,每1,3个div占3列,第2个div则占6列,即3列+6列+3列=12列 -->
</div>
</div>
<!--
混用
<div class="col-xs-12 col-sm-9 col-md-6 col-lg-3">测试</div>
-->

Bootstrap参数 含义
col-sm-** 平板 - 屏幕宽度等于或大于 576px
col-md-** 桌面显示器 - 屏幕宽度等于或大于 768px
col-lg- ** 大桌面显示器 - 屏幕宽度等于或大于 992px
col-xl- ** 超大桌面显示器 - 屏幕宽度等于或大于 1200px
container-fluid 无视12个栅栏的规定,根据屏幕自动适应自动填充。
container 它的宽度最大也大不过12个栅栏总共的最大宽度
row 行,每一行可划分为12列
panel panel-default 创建一个基本的面板,只需要向

元素添加 class .panel-default 即可

panel-heading 带标题的面板(panels)
panel-body 面板内容
panel-footer 面板脚注
list-group 面板中添加列表组
list-group-item 在列表组list-group

标签中通过class = "list-group-item"创建列表

 index.html

接下来看看index.html的内容,主要功能是显示网站的主页面,并显示文章的标题、摘要和发表日期:

<!-- index.html 主页面文件-->
{% extends 'base.html' %}
{% block title %}欢迎来到文学天地{% endblock %}
{% block headmessage %}
<h3 style='font-family:楷体;'>本站文章列表</h3>
{% endblock %}
{% block content %}
{% for post in posts %}
<div class='panel panel-default'>
<div class='panel-heading'>
<p style='font-family:宋体;font-size:pt;font-weight:bold;'>
<a href='/post/{{post.slug}}'>{{post.title}}</a>
</p>
</div>
<div class='panel-body' style='background-color:#ffffdd'>
<p>
{{post.body|truncatechars:40}} <!--主页面显示文章摘要,取文章前40个字符(过滤器)-->
</p>
</div>
<div class='panel-footer' style='background-color:#efefef'>
<p>
发布时间:{{post.pub_date|date:"Y-m-d, h:m:s"}} <!--现在时刻-->
</p>
</div>
</div>
<br>
{% endfor %}
{% endblock %}

如上所述,文件开头以{% extends 'base.html' %}指定要继承的文件为base.html,然后下方就以

{% block title %}{% endblock %}分别指出3个区块要填写的内容;其中代码中posts参数由 [4) 读取数据库内容](#4 读取数据库内容) 中的views.pydef homepage(request)导入:

def	homepage(request):
template = get_template('index.html')
posts = Post.objects.all()
now = datetime.now()
html = template.render(locals())
return HttpResponse(html)

通过<a herf>这个标签取出post.slug建立为连接网址,并放在post/之下,如拼接成http://121.36.56.144:9000/post/baigui01;通过点击文章标题,发送POST请求,前往urls.py利用正则表达式将请求链接中的post.slug(如,baigui01)找出来并将作为第二个参数传递给views.py中的def showpost(request,slug)的slug参数,匹配参数后渲染相关的.html文件,即post.html

def showpost(request,slug):
template = get_template('post.html')
try:
post = Post.objects.get(slug=slug) #匹配传入参数与资料库中的slug
if post!= None:
html = template.render(locals())
return HttpResponse(html)
except:
return redirect('/') #错误直接返回首页

显示文章摘要和特定的日期显示格式,这就需要Django中的filter过滤器,指定过滤器的方式在变量之后加上"|"即可,如index.html中的{{post.body|truncatechars:40}}显示文章摘要,下列给出几个常用的过滤器:

名称 用途 示例
capfirst 把第一个字母改为大写 {{value|capfirst}}
center 把字符串内容置中 {{value|center:“12”}}
cut 把字符串中指定的字元移除 {{value|cut:""}}
date 指定日期时间的输出格式 {{value|date:“d M Y”}}
linebreaksbr 置换"\n"为<br/> {{value|linebreaksbr}}
linenumber 为每一行字符串上加上行号 {{value|linenumber}}
lower 把字符串转换为小写 {{value|lower}}
random 把前面的串列元素使用随机的方式任意一个输出 {{value|random}}
striptags 把所有的HTML标记全部移除 {{value|striptags}}
upper 把字符串转为大写 {{value|upper}}
wordcount 计算字数 {{value|wordcount}}
truncatechars 截取指定字数的字元 {{value|truncatechars:40}}
safe 加入safe后可是使文章内的所有html语言可以解读出来 {{value|safe}}

 post.html

 post.html,功能是详细显示文章内容。代码如下:

<!-- post.html 文章显示-->
{% extends 'base.html' %}
{% block title %}{{post.title}} - 文学天地{% endblock %}
{% block headmessage %}
<h3 style='font-family:楷体;'>{{post.title}}</h3>
{% endblock %}
{% block content %}
<p style='font-family:宋体;font-size:12pt;letter-spacing:2pt;'>
{{post.body|safe}}<!--加入|safe后可是使文章内的所有html语言可以解读出来-->
</p>
{% endblock %}

理论相同,通过def showpost(request,slug)函数将变量导入到post.html中,并将文章的标题和内容显示出来。

 header.htmlfooter.html

 header.html代码如下:

<!-- header.html -->
{% load staticfiles %}
<div class='well'>
<img src="{% static 'images/literary_world.jpg' %}" width="100" height="100">
<span style='font-family:宋体;font-size:40pt;font-weight:700;'>欢迎来到文学天地</span>
<!--Well 是一种会引起内容凹陷显示或插图效果的容器 -->
</div>

此文档需要留意的地方就是第二行{% load staticfiles %}只需要使用一次,提醒Django去载入所有的静态文件,这一行指令在同一个文件里只要使用一次即可。而在真正引入图片的地方使用{% load staticfiles %}这个模板语言,Django会依照当时的执行环境把此文件的可存取网路位址传给浏览器。

 footer.html代码如下:

<!-- footer.html -->
{% block footer %}
{% if now %}
<p style='font-family:宋体;'>时间:{{now}}</p>
{% else %}
<a style='font-family:楷体;' href='/'>回首页</a>
<p style='font-family:宋体;'>本文取自网络,如有侵权请来信通知下架...</p>
{% endif %}
{% endblock %}

footer.html中我们使用了一个模板技巧{% if now %},它是用来判断now这个变量是否有内容的指令,如果有就显示现在时刻,如果没有就显示版权声明。主要原因是,在index.html中设计有在页尾显示现在时刻,而在显示单篇文章的post.html则不显示现在时刻,因此就需要if指令以提供此功能。使用共同模板功能得网站,如下图所示:

Django2.2架构+ubuntu16(华为云)+python3.6架设“文学天地”个人网站


若有问题可留言回~,定知无不言,言无不尽!