用Django2.0搭建一个博客
2018-03-13 | Tags: 博客搭建
缘起
近来觉得想记录一下平时学习的东西,又苦于写了笔记自己常常不会去看,时间久了又都淡忘了,正好手上有一台服务器,干脆自己搭个博客,有空的时候记录一下,也方便常常浏览。
工具选择
一般最常见的选择是WordPress,提供了前后台一站式博客搭建功能,还有大量的模版和插件可以用,不过WordPress的后台基于PHP,没有什么开发经验,而且WordPress相对有些臃肿,修改不方便,这次就不选择了。
还有一些基于Github生成静态站点的工具,如hexo, Jekyll等,这些工具的特点是非常轻量级,不需要后台服务器,可以托管在Github上,免去了搭建和配置服务器的麻烦。但是静态站点因为没有后台服务支持,有些动态功能比如搜索、评论等比较难以实现。
基于简单易开发和高扩展的考虑,这里选择了使用Django开发了几个简单的页面,完全满足当前的需求,并且有足够的自由度进行各种功能的开发。
环境配置
搭建python环境一般使用virtualenv,可以创建一个独立的Python运行环境,和其他环境隔离开,保证独立配置不会被干扰。
首先安装virtualenv:
[sudo] pip install virtualenv
然后选择安装 virtualenvwrapper ,它提供了一系列命令,帮助便捷的管理虚拟环境。
安装virtualenvwrapper:
[sudo] pip install virtualenvwrapper
在当前shell窗口启用virtualenvwrapper:
export WORKON_HOME=~/Envs
source /usr/local/bin/virtualenvwrapper.sh
这里的WORKON_HOME
表示统一存放虚拟环境的位置在~/Envs
,这里可以自己定义。
如果virtualenvwrapper.sh
脚本不在/usr/local/bin
下的话,可以到/usr/bin
下寻找或使用which virtualenvwrapper.sh
查看具体位置。
如果要使virtualenvwrapper一直有效的话,把上面两行启用命令写入shell启动脚本中(一般是~/.bashrc
,或~/.profile
)
配置好virtualenvwrapper之后就可以建一个新的虚拟环境作为之后的开发环境,这边使用python3作为基础python版本,并安装最新的Django2.0。
mkvirtualenv --python=python3 blogenv
mkvirtualenv
之后会自动进入到blogenv
环境中,之后可以通过deactivate
和workon blogenv
退出和进入blogenv
环境。
进入python验证一下当前环境的python版本:
(blogenv) ~ python
Python 3.6.3 (default, Oct 9 2017, 12:11:29)
[GCC 7.2.1 20170915 (Red Hat 7.2.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information
安装最新版本的Django
pip install django
Django2.0和1.x相比,增加了一些特性方便进行网站的开发,What’s new in Django2.0 文档中一共列出了三个新的特性:
- 更简单的URL路由语法 (Simplified URL routing syntax)
- admin应用的针对移动设备的优化改进(Mobile-friendly contrib.admin)
- 支持SQL开窗表达式(Window expressions)
到这里Django的基本环境就配置好了
博客搭建
Django的运行简介
简单来说,Django运行主要主要基于mvt模型,分别是model layer,view layer, template layer。
- model layer主要是抽象了一个通用方法层用于组织和操作网站中用到的数据。
- view layer主要用于响应用户的访问请求并返回结果。
- template layer主要用于渲染展示给用户的页面,可以方便的插入python传递过来的数据。
建立Django项目
进入blogenv环境,之后默认操作都在blogenv环境下。
workon blogenv
通过django-admin新建一个名为blog的目录,并在blog目录建立一个为main的app目录
django-admin startproject blog
cd blog
python manage.py startapp main
此时的目录结构是这样的
.
├── blog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ └── settings.cpython-36.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── main
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
这里需要在blog/settings.py的INSTALLED_APPS 列表中加入对main的支持
INSTALLED_APPS = [
# [...]
'main',
]
接下来就可以开始在main目录下开发博客相关的功能了。
编辑model layer
model layer主要用于处理网站中用到的数据,并抽象和统一化对数据库对操作,在博客中自然主要就是文章的数据了。首先确认在blog/settings.py
中对数据库后台的设定,这边方便起见使用python自带的sqlite
,如果要使用其他的数据库修改为相应的配置即可。
DATABASES = {
'default': {
¦ 'ENGINE': 'django.db.backends.sqlite3',
¦ 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
然后打开main/models.py
,添加如下代码
class Article(models.Model):
¦ title = models.CharField(max_length=30)
¦ content = models.TextField()
¦ date = models.DateTimeField()
这里表示会在数据库中建立一个名为Atricle的model,一共有title,content,date三个字段,即文章的标题,内容和日期这三项最基本的内容。一个model是一个对网站数据的定义,包括了各项基本字段和数据的各种行为。每个model都会最终操作数据库中的所相对应的数据表。
然后我们可以利用强大的Django Admin后台,作为我们博客的后台编辑页面。打开main/admin.py
,添加如下代码:
from main.models import Article
admin.site.register(Article)
这里将之前定义的Article注册到Admin后台中。
然后需要建立Article和Admin所需要的数据表,并建立一个在项目的根目录shell中执行:
(blogenv) python manage.py makemigrations
(blogenv) python manage.py migrate
(blogenv) python manage.py createsuperuser
然后将网站服务运行起来,就可以访问Admin后台了:
(blogenv) python manage.py runserver
这里默认将服务起到本机的8000端口,如果被占用了可以在命令最后添加其他端口号,如果成功启动就可以访问http://127.0.0.1:8008/admin/
进入Admin后台界面了。
登入之后的界面如下:
点击Article之后的Add就可以添加新的博客文章了:
点击Article可以进入文章列表,添加或者修改文章:
这里的Article Object是我们之前在main/models.py
中定义的Article类的默认名称,为了可以在Article类中添加__str__
方法定义显示的名称,修改后的代码如下:
class Article(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
date = models.DateTimeField()
def __str__(self):
return self.title
使用使用view layer建立url映射
后台现在已经有了文章之后我们怎么把它显示出来呢?
我们要有不同的url路径来对不同页面进行访问,我们首先建立一个index页面显示所有文章的列表,然后用article+文章编号的页面来访问不同的文章,这边我们可以编辑blog/urls.py
加入这两个页面的URL访问规则:
from main import views as main_views
urlpatterns = [
path('admin/', admin.site.urls),
path('', main_views.index),
path('article/<int:article_id>', main_views.article_id),
]
在Django2中,这里path
的第一个参数表示url的路由规则, 第二个参数表示需要调用对应的函数,这里添加的两个规则分别表示将对/
的url路径访问调用main_views.index()
函数和对/article/id
的url路径访问调用main_views.article_id(id)
函数,其中id是一个可以被捕获的int值,这样就起到了访问不同id的文章的功能。
其中main_views.index()和main_views.article_id(id)的实现如下
def index(request):
articles = Article.objects.filter(is_show=True).order_by('-date')
context = {
'articles': articles,
}
return render(request, 'main/index.html', context)
def article_id(request, article_id):
try:
article = Article.objects.get(id=article_id)
except Exception as e:
print(e.with_traceback, e)
if article is not None:
return render(request, 'main/article.html', {
'article':article,
'date': article.date.strftime("%Y-%m-%d"),
'content': markdown.markdown(article.content),
})
根据请求在model Article中查找对应的文摘,并传到对应的template中进行渲染,就可以生成最后返回给用户的网页了。
建立template layer
django template是一个类似于html语法的文件,但是其中可以额外插入django传入的实时数据,达成动态生成页面的能力。
template 文件通常放在当前django app的template·目录下,如上文中return render(request, 'main/index.html', context)
的main/index.html
,django会自动查找main/template/main/index.html,其实现如下
{% extends "main/base.html" %}
{% load staticfiles %}
{% load i18n %}
{% block content %}
<div class='mtb-15'>
<div class='container'>
<div class='row main-title' >
<p><b>文章</b></p>
<hr>
</div>
<div class='row'>
{% for article in articles %}
<div class='article-title'>
<p><span>{{ article.date|date:"Y-m-d" }} <span>
<a href="blog/{{ article.id }}">{{ article.title }}</a></p>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock %}
其中extends "main/base.html"
表示本文件继承了main/base.html,是base.html的扩展。在base.html`中可以实现一些页面的公共部分,比如<head>,<footer>,网页标头等等。
load staticfiles
和 load i18n
表示加载了静态文件和多语言的功能模块
block content
表示将里面的内容填充到base.html对应标示block content的部分,其中block是关键字,content是要填充内容的标识,可以自己定义多种标识来进行对应的填充。
在block content
内部, {% for article in articles %}
中的articles对应了main_views.index()
传入的字典中的articles字段,这里可以我们将articles进行遍历,并将内部所有的article的data,id和title渲染到页面中,形成了整个主页的内容。
结束
到这里,我们的blog基本成型了,可以通过127.0.0.1:8000/访问主页,通过127.0.0.1:8000/blog/<id>访问对应的文章。然后就可以发挥我们的聪明才智,在这个基础上不断添加新的有趣的功能,搭建我们自己心中完美的blog了。
本站整体代码可以访问我的github,供参考。