前面已經介紹了django的各種用法,從這一章開始,將實際搭建一個blog系統。
首先我們需要設計blog的模型,在models.py中添加如下內容
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import sys
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.contrib import admin
from django.db import models
#下面的部分是設置編碼,否則在輸入中文的時候會報錯
default_encoding = 'utf-8'
reload(sys)
sys.setdefaultencoding(default_encoding)
# Create your models here.
class Post(models.Model):
STATUS_CHOICES=(('draft','Draft'),('published','Published'),)
title=models.CharField(max_length=250,verbose_name=u'標題')
slug=models.SlugField(max_length=250,unique_for_date='publish')
author=models.ForeignKey(User,related_name='blog_posts',verbose_name=u'作者')
body=models.TextField(verbose_name=u'正文')
publish=models.DateTimeField(default=timezone.now,verbose_name=u'發表時間')
created=models.DateTimeField(auto_now_add=True,verbose_name=u'創建時間')
updated=models.DateTimeField(auto_now=True,verbose_name=u'更新時間')
status=models.CharField(max_length=10,choices=STATUS_CHOICES,default='draft',verbose_name=u'狀態')
class Meta:
ordering=('-publish',)
def __str__(self):
return self.title這就是給blog使用的基礎模型,來看下各個字段的定義:
title:這個字段對應帖子的標題。它是CharField,在SQL數據庫中會被轉化成VARCHAR。
slug:這個字段將會在URLs中使用。slug就是一個短標簽,該標簽只包含字母,數字,下划線或連接線
author:這是一個ForeignKey。這個字段定義了一個多對一(many-to-one)的關系。我們告訴Django一篇帖子只能由一名用戶編寫,一名用戶能編寫多篇帖子。根據這個字段,Django將會在數據庫中通過有關聯的模型(model)主鍵來創建一個外鍵。在這個場景中,我們關聯上了Django權限系統的User模型(model)。我們通過related_name屬性指定了從User到Post的反向關系名
body:這是帖子的主體。它是TextField,在SQL數據庫中被轉化成TEXT。
publish:這個日期表明帖子什么時間發布。我們使用Djnago的timezone的now方法來設定默認值
created:這個日期表明帖子什么時間創建。因為我們在這兒使用了auto_now_add,當一個對象被創建的時候這個字段會自動保存當前日期。
updated:這個日期表明帖子什么時候更新。因為我們在這兒使用了auto_now,當我們更新保存一個對象的時候這個字段將會自動更新到當前日期
status:這個字段表示當前帖子的展示狀態。我們使用了一個choices參數,這樣這個字段的值只能是給予的選擇參數中的某一個值
verbose_name 是給各個字段起了一個別名,便於識別
模型設置后好,通過python manage.py makemigrations blog和python manage.py migrate進行數據庫遷移,同步
zhf@zhf-maple:~/py_prj/mysite$ python manage.py makemigrations blog
Migrations for 'blog':
blog/migrations/0001_initial.py
- Create model Post
zhf@zhf-maple:~/py_prj/mysite$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
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 auth.0008_alter_user_username_max_length... OK
Applying blog.0001_initial... OK
Applying sessions.0001_initial... OK
同時在models.py中添加Post的管理設置
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'author', 'publish',
'status')
list_filter = ('status', 'created', 'publish', 'author')
search_fields = ('title', 'body')
prepopulated_fields = {'slug': ('title',)}
raw_id_fields = ('author',)
date_hierarchy = 'publish'
ordering = ['status', 'publish']
並在admin.py中
接下來我們將要創建一個超級用戶對我們的博客系統進行管理。這個超級用戶主要是進入后台admin的時候使用。關於后台admin的使用參考之前的帖子
www.cnblogs.com/zhanghongfeng/p/8018415.html
zhf@zhf-maple:~/py_prj/mysite$ python manage.py createsuperuser
Username (leave blank to use 'zhf'): root
Email address: maple412@163.com
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
Password:
Password (again):
Superuser created successfully.
運行程序,並在瀏覽器中輸入http://127.0.0.1:8000/admin/, 用剛才創建的超級賬戶登錄便可以看到后台的信息
界面是英文版的,且標題也是默認的.如果想修改界面和標題.需要在admin.py和setting.py中進行修改
admin.py中增加修改標題和title
admin.site.site_header=u"張紅楓的博客"
admin.site.site_title=u"張紅楓的博客"
setting.py中增加django.middleware.locale.LocaleMiddleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]ting.py中增加
這樣就能看到一個中文版的界面
點擊新增Post就可以看到定義的字段
我們增加一個后就可以顯示出來
模型定義后好,接下來定義個視圖的測試文件,在views.py中定義個test函數來顯示所有的博客
from django.shortcuts import HttpResponse
from .models import Post
# Create your views here.
def test(request):
posts=Post.objects.all()
return HttpResponse(posts)
接下里就需要為試圖添加URL模式,也就是路由了.在blog應用下添加一個urls.py文件
from django.conf.urls import url
from . import views
urlpatterns = [
# post views
url(r'^$', views.test, name='post_list'),
]
現在你需要將你blog中的URL模式包含到項目的主URL模式中。編輯你的項目中的mysite文件夾中的urls.py文件,如下所示:
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog/',include('blog.urls',namespace='blog',app_name='blog')),
]
通過include(‘blog.urls’)的方式就將blog應用下的url和主url拼接了起來.在瀏覽器中輸入http://127.0.0.1:8000/blog/的時候將會跳轉到去執行視圖函數test
views.py中的test函數是通過Httpresponse的方式直接進行反饋.接下來我們要為視圖創建模板:template. 在template中創建如下的文檔結構.base.html文件將會包含站點主要的HTML結構以及分割內容區域和一個導航欄。list.html和detail.html文件會繼承base.html文件來渲染各自的blog帖子列和詳情視圖(view)。
在base.html中添加如下代碼:
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<link href="{% static "css/blog.css" %}" rel="stylesheet">
</head>
<body>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>
你可以看到有兩個{% block %}標簽(tags)。這些是用來告訴Django我們想在這個區域中定義一個區塊(block)。繼承這個模板(template)的其他模板(templates)可以使用自定義的內容來填充區塊(block)。我們定義了一個區塊(block)叫做title,另一個區塊(block)叫做content。
在post/list.html中添加如下代碼:
{% extends "blog/base.html" %}
{% block title %}My Blog{% endblock %}
{% block content %}
<h1>My Blog</h1>
{% for post in posts %}
<h2>
<a href="{{ post.get_absolute_url }}">
{{ post.title }}
</a>
</h2>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% endfor %}
{% endblock %}
通過{% extends %}模板標簽(template tag),我們告訴Django需要繼承blog/base.html 模板(template)。然后我們在title和content區塊(blocks)中填充內容。我們通過循環迭代帖子來展示它們的標題,日期,作者和內容
在views.py中添加post_list函數
def post_list(request):
posts=Post.objects.all()
return render(request,'post/list.html',{'posts':posts}
在blog中的urls.py添加對應的路由:
urlpatterns = [
# post views
url(r'^$', views.post_list, name='post_list'),
]
在瀏覽器中輸入http://127.0.0.1:8000/blog/后可以顯示所有的博客內容
在這個頁面中我們顯示了所有的博客內容,如果我們不想在一個頁面中顯示所有的內容,需要采取分頁的方法,比如一頁只顯示一個.這就需要采集分頁的方法django有一個內置的Paginator類允許你方便的管理分頁。編輯blog應用下的views.py文件導入Django的頁碼類修改post_list如下所示:
def post_list_page(request):
object_list = Post.objects.all()
paginator = Paginator(object_list, 1) # 1 posts in each page
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
return render(request,
'post/list.html',
{'page': page,
'posts': posts,
})
那么這個Paginator是如何工作的呢,
1 首先創建一個Paginator實例類並且傳入查詢到的所有對象
2 獲取到page GET參數來指明頁數
3 通過調用Paginator的 page()方法在期望的頁面中獲得了對象
4 如果page參數不是一個整數,我們就返回第一頁的結果。如果這個參數數字超出了最大的頁數,我們就展示最后一頁的結果
5 傳遞頁數並且獲取對象給這個模板(template)
現在,我們必須創建一個模板(template)來展示分頁處理,它可以被任意的模板(template)包含來使用分頁。在blog應用的templates文件夾下創建一個新文件命名為pagination.html。在該文件中添加如下HTML代碼
<div class="pagination">
<span class="step-links">
{% if page.has_previous %}
<a href="?page={{ page.previous_page_number }}">Previous</a>
{% endif %}
<span class="current">
Page {{ page.number }} of {{ page.paginator.num_pages }}.
</span>
{% if page.has_next %}
<a href="?page={{ page.next_page_number }}">Next</a>
{% endif %}
</span>
</div>
我們來看下實際的效果.輸入http://127.0.0.1:8000/blog/后顯示如下頁面.由於我們在url中並沒有輸入page參數,因此調用posts = paginator.page(1)顯示地一個博客內容對象.
當我們點擊next后,瀏覽器中的url變成了http://127.0.0.1:8000/blog/?page=2. 此時我們獲取到了page參數,因此通過posts = paginator.page(page) 獲取對應page的博客對象.