一、準備工作
安裝Python和Django,我這裡使用的是Python 2.7.11 和Django 1.9.8。
安裝完之後就可以開始啦!
開啟新的項目
$ django-admin startproject blogsite(網站工程名稱)
成功以後生成項目檔案夾,結構如下
blogsite /
manage.py
blogsite /
__init__.py
settings.py
urls.py
wsgi.py
此時運作伺服器
$ python manage.py runserver
在控制台看到如下資訊
Performing system checks...
System check identified no issues (0silenced).
You have unapplied migrations; your app maynot work properly until they are applied.
Run `python manage.py migrate' to applythem.
July 25, 2016 - 15:50:53
Django version 1.9, using settings ` blogsite.settings'
Starting development server athttp://127.0.0.1:8000/
Quit the server with CONTROL-C.
此時打開浏覽器,輸入http://127.0.0.1:8000/,你将看到這樣的資訊

你也可以修改/blogsite/setting.py來更改語言和時區
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
再運作一遍伺服器,重新整理一下頁面
然後我們建立一個app
$ python manage.py startapp blog
建立了一個檔案夾blog,其内部結構如下
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
注冊app
/blogsite/setting.py
# Application definition
INSTALLED_APPS = [
'blog.apps.BlogConfig',
……
]
……
二、模型的搭建
部落格需要那些模型?
博文、博文分類、标簽
根據你設計的類來修改
/blog/models.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
# Create your models here.
@python_2_unicode_compatible #如果要求python2支援utf-8則需要加上此句
class Category(models.Model):
name = models.CharField(u'名稱', max_length = 20)
def __str__(self):
return self.name;
@python_2_unicode_compatible
class Tag(models.Model):
name = models.CharField(u'名稱', max_length = 20)
def __str__(self):
return self.name;
@python_2_unicode_compatible
class Article(models.Model):
title = models.CharField(u'标題',max_length = 150)
body = models.TextField(u'正文')
date = models.DateTimeField(u'釋出時間')
category = models.ForeignKey(Category, verbose_name=u'分類')
tags = models.ManyToManyField(Tag, verbose_name = u'标簽', blank=True)
# models.ForeignKey表示一個Article有一個Category
# models.ManyToManyField表示一個Article有多個Tag,blank=True表示可以為空
def __str__(self):
return self.title
寫完之後要向資料庫中注冊,這裡我們使用python自帶的SQLite
先建立一個migration
$ python manage.py makemigrations blog
控制台顯示如下,并建立一個名為0001_initial.py的python檔案
0001_initial.py:
- Create model Article
- Create model Category
- Create model Tag
- Add field category to article
- Add field tags to article
然後寫入資料庫
$ python manage.py sqlmigrate blog 0001
控制台顯示如下:
BEGIN;
--
-- Create model Article
--
CREATE TABLE "blog_article"("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title"varchar(150) NOT NULL, "body" text NOT NULL, "date"datetime NOT NULL);
--
-- Create model Category
--
CREATE TABLE "blog_category"("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name"varchar(20) NOT NULL);
--
-- Create model Tag
--
CREATE TABLE "blog_tag"("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name"varchar(20) NOT NULL);
--
-- Add field category to article
--
ALTER TABLE "blog_article" RENAMETO "blog_article__old";
CREATE TABLE "blog_article"("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title"varchar(150) NOT NULL, "body" text NOT NULL, "date"datetime NOT NULL, "category_id" integer NOT NULL REFERENCES"blog_category" ("id"));
INSERT INTO "blog_article"("body", "date", "category_id", "id","title") SELECT "body", "date", NULL,"id", "title" FROM "blog_article__old";
DROP TABLE "blog_article__old";
CREATE INDEX"blog_article_b583a629" ON "blog_article"("category_id");
--
-- Add field tags to article
--
CREATE TABLE "blog_article_tags"("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,"article_id" integer NOT NULL REFERENCES "blog_article"("id"), "tag_id" integer NOT NULL REFERENCES"blog_tag" ("id"));
CREATE UNIQUE INDEX"blog_article_tags_article_id_b78a22e9_uniq" ON "blog_article_tags"("article_id", "tag_id");
CREATE INDEX"blog_article_tags_a00c1b00" ON "blog_article_tags"("article_id");
CREATE INDEX"blog_article_tags_76f094bc" ON "blog_article_tags"("tag_id");
COMMIT;
最後應用migration
$ python manage.py migrate
控制台顯示如下:
Operations to perform:
Apply all migrations: admin, blog, contenttypes, auth, sessions
Running migrations:
Rendering model states... DONE
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 blog.0001_initial... OK
Applying sessions.0001_initial... OK
我們需要一個管理者使用者來管理網站上的内容:
$ python manage.py createsuperuser
Username: admin
Email address: [email protected]
Password: **********
Password (again): *********
Superuser created successfully.
之後我們重新開機伺服器,在浏覽器上輸入http://127.0.0.1:8000/admin/
輸入之前建立管理賬戶的使用者名和密碼登陸,登陸後看到如下
什麼?沒有看到自己寫的模型?那是因為沒有在admin.py上注冊
/blog/admin.py
from django.contrib import admin
from .models import Article,Category,Tag
# Register your models here.
class ArticlePostAdmin(admin.ModelAdmin):
list_display = ('title','date','category') #list_display決定了視圖的格式
#向管理界面注冊模型
admin.site.register(Article,ArticlePostAdmin)
admin.site.register(Category)
admin.site.register(Tag)
儲存重新整理,就看到你自己寫的模型了
三、URL,視圖和模闆
模型已經建好了,接下來就是定義url、視圖和模闆了
我們先介紹一下url函數
url(regex,view,name,kwargs)
regex:正規表達式
view:位址滿足該正規表達式時調用的視圖函數
name(非必需):可以通過name來反向擷取URL
kwargs(非必需): 一個字典類型的參數
我們先修改工程下的 /urls.py
/blogsite/urls.py
"""blogsite URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.9/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
#include函數:包含 /blog/urls.py 檔案的urlpatterns
url(r'^$',include('blog.urls')), #直接跳轉至部落格目錄
url(r'^blog/',include('blog.urls')),
url(r'^admin/', admin.site.urls),
]
再前往/blog 目錄下建立urls,py檔案
/blog/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$',views.index,name='index'), #/或/blog時調用views.index函數,加載首頁
url(r'^(?P<article_id>[0-9]+)/',views.article,name='article'), #/blog/數字:調用views.article函數,加載博文
url(r'^cat=(?P<category_id>[0-9]+)',views.category,name = 'category') #/blog/cat=數字:調用views.category
]
之後編寫views.py檔案,實作剛才提到的函數
/blog/views.py
from django.core.urlresolvers import reverse
from django.http import Http404, HttpResponseRedirect, HttpResponse
from django.shortcuts import render, get_object_or_404
from django.template import loader
from .models import Article,Category,Tag
# Create your views here.
def index(request):
latest_articles_list = Article.objects.order_by('-date') #将文章按照時間順序生成清單
category_list = Category.objects.order_by('-name') #将分類按照名稱順序生成清單
template = loader.get_template('blogs/index.html') #擷取模闆html檔案,該檔案将在之後編寫
context = {
'latest_articles_list' : latest_articles_list,
'category_list' : category_list,
} #傳給模闆html的背景資料
return render(request,'blogs/index.html',context)
def article(request,article_id):
try:
article = Article.objects.get(pk=article_id) #按編号查詢文章
except Article.DoesNotExist: #如果找不到則抛出異常處理
raise Http404("Article does not exist")
return render(request, 'blogs/article.html', {'article': article})
def category(request,category_id):
cur_cat = Category.objects.get(pk = category_id)
articles = Article.objects.filter(category = cur_cat) #找到一個或多個該分類下的文章,因為可能是多個文章是以應該用filter函數
return render(request, 'blogs/category.html', {'articles': articles})
好了,現在我們要在/blog下建立一個templates檔案夾,在templates檔案夾下再建一個blogs檔案夾用于存放模闆html檔案。
模闆格式:
{% 表示邏輯的語句 %}
{{ 變量 }}
{# 注釋 #}
建立3個模闆html檔案(随手寫了3個用作示範,後期前端代碼應該重寫):
1、/blog/templates/blogs/index.html
{% if latest_articles_list %}
<h1>最近博文</h1>
<ul>
{% for article in latest_articles_list %}
<li><a href="/blog/{{article.id}}/" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >{{article.title}}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No articles are avaliable</p>
{% endif %}
{% if category_list %}
<h1>博文分類</h1>
<ul>
{% for category in category_list %}
<li><a href="/blog/cat={{category.id}}/" target="_blank" rel="external nofollow" >{{category.name}}</li>
{% endfor %}
</ul>
{% endif %}
2、/blog/templates/blogs/category.html
{% if articles %}
<ul>
{% for article in articles %}
<li><a href="/blog/{{article.id}}/" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >{{article.title}}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No articles are avaliable</p>
{% endif %}
3、/blog/templates/blogs/article.html
<h1>{{article.title}}</h1>
<h2>{{article.date}}</h2>
<p>{{article.body}}</p>
<p>{{article.category.name}}</p>
最終效果如下:
四、其他
到此一個基本的部落格架構就搭起來了,我們可以再添加一些其他功能。我寫這個架構的時候參考了這些大神的部落格。 1、添加Django評論系統 http://answ.me/post/comment-in-django-part-1/
2、添加富文本編輯器CKEditor http://python-ning.github.io/2016/04/12/python_django_blog_ckeditor/
3、添加搜尋功能:Haystack+Whoosh+Jieba
http://blog.sina.com.cn/s/blog_875a5f5f0102woix.html
http://tenlee2012.github.io/2016/04/21/Django添加全文搜尋功能入門/
4、分享功能我使用的是百度一鍵分享API。
這個架構的源碼在這: simple-django-blog 有需要改進的地方請大家賜教。