Django之博客系統搭建一


前面已經介紹了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屬性指定了從UserPost的反向關系名

body:這是帖子的主體。它是TextField,在SQL數據庫中被轉化成TEXT

publish:這個日期表明帖子什么時間發布。我們使用Djnagotimezonenow方法來設定默認值

created:這個日期表明帖子什么時間創建。因為我們在這兒使用了auto_now_add,當一個對象被創建的時候這個字段會自動保存當前日期。

updated:這個日期表明帖子什么時候更新。因為我們在這兒使用了auto_now,當我們更新保存一個對象的時候這個字段將會自動更新到當前日期

status:這個字段表示當前帖子的展示狀態。我們使用了一個choices參數,這樣這個字段的值只能是給予的選擇參數中的某一個值

 

verbose_name 是給各個字段起了一個別名,便於識別

 

模型設置后好,通過python manage.py makemigrations blogpython 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.pysetting.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.htmldetail.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)。然后我們在titlecontent區塊(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的博客對象.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM