Django 學習小組:博客開發實戰第一週教程 —— 編寫博客的 Model 與主頁面

本教程內容已過期,更新版教程請訪問: django 博客開發入門教程html

本節是 Django Blog 項目的開篇,是 Django 學習小組的集體學習成果。Django 學習小組是由我發起的一個促進 Django 新手互相學習、互相幫助的組織。小組在一邊學習 Django 的同時將一塊兒完成三個項目:python

  • 一個簡單 Django Blog,用於發佈小組每週的學習和開發文檔git

  • Django 中國社區,爲國內的 Django 開發者們提供一個長期維護的 Django 社區,彙集全國的 Django 開發者到這個社區上來github

  • Django 問答社區, 相似於 segmentfault 和 stackoverflow 但更加專一(只專一於 Django 開發的問題)的問答社區數據庫

目前小組正在完成第一個項目,本文便是該項目第一週的相關文檔。django

更多的信息請關注咱們的 github 組織首頁,本教程項目的相關源代碼也已上傳到 github 上。
同時,你也能夠加入咱們的郵件列表 django_study@groups.163.com ,隨時關注咱們的動態,咱們會將每週的詳細開發文檔和代碼經過郵件列表發出。
若有任何建議,歡迎提 Issue,歡迎fork,pull requests,固然也別忘了 Star 哦!
每週更新,敬請關注segmentfault

Django 開發環境的搭建和建立 Blog 工程

django 的開發環境搭建以及如何建立工程在網上有大量的博客和教程介紹,在此再也不重複說明。但我建議最好的參考資料仍是Django官方的入門 Tutorials ,即官方文檔First steps 部分的六個 Parts。固然若是你不喜歡英文,能夠看咱們的中文翻譯版本:Django 入門教程中文翻譯版瀏覽器

要開始 Django 開發,你須要從中掌握如下知識:markdown

  • 如何建立 Django 工程,並瞭解 Django 默認的工程目錄結構函數

  • 如何建立 Django APP

  • 理解 Django 的MTV 模式,學會編寫 Model、View、Template

  • Django 如何處理靜態文件,即各類 CSS,JS,以及圖片文件等

咱們強烈建議你在閱讀完上面的教程以掌握 Django 開發所需的最基本概念後開始本項目的學習

Django應用是如何工做的?

先看一張流程圖,再來逐步講解其過程:

Django 工做流

1:用戶經過瀏覽器輸入相應的 URL 發起 HTTP 請求(通常是 GET/POST)

2:Django 接受到請求,檢測 urls.py 文件,找到和用戶輸入的 URL 相匹配的項,並調用該 URL 對應的視圖函數(view),例如,一般來講 urls.py 文件裏的代碼是這樣的:

url(r'^homepage/$', views.home_page)

則當用戶輸入的 URL 爲 www.某個網址.com/homepage 時,django 檢測到該 URL 與上面的代碼 匹配,因而調用後面的 views.home_page 視圖函數,把相應的請求交給該視圖函數處理。

3:視圖函數被調用後,可能會訪問數據庫(Model)去查詢用戶想要請求的數據,並加載模板文件(Template),渲染完數據後打包成 HttpResponse 返回給瀏覽器(Http協議)

大體工做流程就是這樣,從流程能夠看出,咱們須要作的就是:

  • 編寫相應的 url

  • 編寫數據庫(Model)

  • 編寫處理 Http 請求的視圖函數(View)

  • 編寫須要渲染的模板(Template)

這就是 Django 開發的最主要工做,下面遵循這樣的開發流程開始編寫咱們的 Blog程序吧。

編寫 Model

Model 對應數據庫,咱們編寫的是一個 Blog 應用,所以數據庫中應該存放 Blog 下的文章(Aticle),文章由標題(title)、正文(body)、發佈時間(publised_time)等組成。先看 django 是如何定義數據庫的,以後再逐行解釋代碼(假設你已經對 django 的工程目錄結構瞭解了,咱們通常把 Model 定義在 models.py 文件中):

models.py

from django.db import models

class Article(models.Model):
    STATUS_CHOICES = (
        ('d', 'Draft'),
        ('p', 'Published'),
    )

    title = models.CharField('標題', max_length=70)
    body = models.TextField('正文')
    created_time = models.DateTimeField('建立時間', auto_now_add=True)
    last_modified_time = models.DateTimeField('修改時間', auto_now=True)
    status = models.CharField('文章狀態', max_length=1, choices=STATUS_CHOICES)
    abstract = models.CharField('摘要', max_length=54, blank=True, null=True, 
                                help_text="可選,如若爲空將摘取正文的前54個字符")
    views = models.PositiveIntegerField('瀏覽量', default=0)
    likes = models.PositiveIntegerField('點贊數', default=0)
    topped = models.BooleanField('置頂', default=False)

    category = models.ForeignKey('Category', verbose_name='分類', 
                                 null=True, 
                                 on_delete=models.SET_NULL)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-last_modified_time']


class Category(models.Model):
    name = models.CharField('類名', max_length=20)
    created_time = models.DateTimeField('建立時間', auto_now_add=True)
    last_modified_time = models.DateTimeField('修改時間', auto_now=True)

    def __str__(self):
        return self.name

逐行解釋:

from django.db import models
# 和 model 相關的一些API定義在 django.db.models 模塊中

class Article(models.Model):
    """
    全部的 model 必須繼承自django.db.models
    類 Aticle 即表示 Blog 的文章,一個類被 diango 映射成數據庫中對應的一個表,表名即類名
    類的屬性(field),好比下面的 title、body 等對應着數據庫表的屬性列
    """
    STATUS_CHOICES = (
        ('d', 'Draft'),
        ('p', 'Published'),
    )
    # 在 status 時說明

    title = models.CharField('標題', max_length=70)
    # 文章標題,CharField 表示對應數據庫中表的列是用來存字符串的,'標題'是一個位置參數     
    #(verbose_name),主要用於 django 的後臺系統,很少作介紹。max_length 表示能存儲的字符串    
    # 的最大長度
    
    body = models.TextField('正文')
    # 文章正文,TextField 用來存儲大文本字符
    
    created_time = models.DateTimeField('建立時間', auto_now_add=True)
    # 文章建立時間,DateTimeField用於存儲時間,設定auto_now_add參數爲真,則在文章被建立時會自動添加建立時間
    
    last_modified_time = models.DateTimeField('修改時間', auto_now=True)
    # 文章最後一次編輯時間,auto_now=True表示每次修改文章時自動添加修改的時間
    
    status = models.CharField('文章狀態', max_length=1, choices=STATUS_CHOICES)
    # STATUS_CHOICES,field 的 choices 參數須要的值,choices選項會使該field在被渲染成form時被渲染爲一個select組件,這裏我定義了兩個狀態,一個是Draft(草稿),一個是Published(已發佈),select組件會有兩個選項:Draft 和 Published。可是存儲在數據庫中的值分別是'd'和'p',這就是 choices的做用。
    
    abstract = models.CharField('摘要', max_length=54, blank=True, null=True, 
                                help_text="可選,如若爲空將摘取正文的前54個字符")
    # 文章摘要,help_text 在該 field 被渲染成 form 是顯示幫助信息
    
    views = models.PositiveIntegerField('瀏覽量', default=0)
    # 閱覽量,PositiveIntegerField存儲非負整數
    
    likes = models.PositiveIntegerField('點贊數', default=0)
    # 點贊數
    
    topped = models.BooleanField('置頂', default=False)
    # 是否置頂,BooleanField 存儲布爾值(True或者False),默認(default)爲False

    category = models.ForeignKey('Category', verbose_name='分類', 
                                 null=True, 
                                 on_delete=models.SET_NULL)
    # 文章的分類,ForeignKey即數據庫中的外鍵。外鍵的定義是:若是數據庫中某個表的列的值是另一個表的主鍵。外鍵定義了一個一對多的關係,這裏即一篇文章對應一個分類,而一個分類下可能有多篇    文章。詳情參考django官方文檔關於ForeinKey的說明,on_delete=models.SET_NULL表示刪除某個分類(category)後該分類下全部的Article的外鍵設爲null(空)
    
    def __str__(self):
        # 主要用於交互解釋器顯示錶示該類的字符串
        return self.title

    class Meta:
        # Meta 包含一系列選項,這裏的 ordering 表示排序,- 號表示逆序。即當從數據庫中取出文章時,其是按文章最後一次修改時間逆序排列的。
        ordering = ['-last_modified_time']


class Category(models.Model):
    """
    另一個表,存儲文章的分類信息
    """
    name = models.CharField('類名', max_length=20)
    created_time = models.DateTimeField('建立時間', auto_now_add=True)
    last_modified_time = models.DateTimeField('修改時間', auto_now=True)

    def __str__(self):
        return self.name

由上可見,設計數據庫結構就是編寫 models,數據庫中每個實體對應的表在 django 中對用着 models.py 中的一個類,類的屬性對應着數據庫表的屬性列。

model 定義完畢後,運行如下命令便可生成相應的數據庫:

python manage.py makemigrations

python manage.py migrate

你能夠打開相應的數據庫文件看看裏面生成的表結構,加深理解。

其中以上的代碼中涉及到一些 django 相關的概念,分別給出如下參考資料供學習:

編寫 View

上面已經介紹了 django 應用的工做流程,數據庫創建完畢後須要編寫視圖函數(view)來處理 Http 請求。一樣先來看 django 的 view 代碼是如何寫的,而後咱們再逐行解釋。

咱們如今要設計的是一個首頁的視圖函數,即用戶進入咱們的 Blog 首頁後,咱們須要把數據庫中存儲的文章的相關信息取出來展現給用戶看:

views.py

from django.views.generic.list import ListView
from blog.models import Article, Category
import markdown2

class IndexView(ListView):
    template_name = "blog/index.html"
    context_object_name = "article_list"

    def get_queryset(self):
        article_list = Article.objects.filter(status='p')
        for article in article_list:
            article.body = markdown2.markdown(article.body, )
        return article_list

    def get_context_data(self, **kwargs):
        kwargs['category_list'] = Category.objects.all().order_by('name')
        return super(IndexView, self).get_context_data(**kwargs)

逐行解釋:

from blog.models import Article
from blog.models import Category
from django.views.generic import ListView
import markdown2

class IndexView(ListView): 
    """
    首頁視圖,繼承自ListVIew,用於展現從數據庫中獲取的文章列表
    """
    
    template_name = "blog/index.html"
    # template_name屬性用於指定使用哪一個模板進行渲染
    
    context_object_name = "article_list"
    # context_object_name屬性用於給上下文變量取名(在模板中使用該名字)
    
    def get_queryset(self):
        """
        過濾數據,獲取全部已發佈文章,而且將內容轉成markdown形式
        """
        article_list = Article.objects.filter(status='p')
        # 獲取數據庫中的全部已發佈的文章,即filter(過濾)狀態爲'p'(已發佈)的文章。
        for article in article_list:
            article.body = markdown2.markdown(article.body, )
            # 將markdown標記的文本轉爲html文本
        return article_list

    def get_context_data(self, **kwargs):
            # 增長額外的數據,這裏返回一個文章分類,以字典的形式
        kwargs['category_list'] = Category.objects.all().order_by('name')
        return super(IndexView, self).get_context_data(**kwargs)

可能以爲奇怪的是既然是視圖函數爲何不是用 def 來定義,而是寫成一個類?這裏涉及到 django 的關於類的通用視圖的概念:參考類的通用視圖。咱們經過調用 as_view 方法會將該類視圖轉爲通常的視圖,這在 url 部分會介紹。

這樣,這個視圖的工做流程就是首先接受來自用戶的 Http 請求,而後從數據庫中獲取到已經發布的文章列表:article_list = Article.objects.filter(status='p'),並轉換 markdown 語法標記,再加載模板文件:template_name = "blog/index.html",將模板中的變量用相應的數據庫中的數據庫替換後返回給瀏覽器,這樣,用戶就看到了從數據庫中被取出而後被渲染後的文章列表了。

編寫 Template

template 稍微麻煩一點,由於涉及到 html 的相關知識,若是你沒有學過 html ,可能會有些看不懂,所以推薦學習一下,這裏有很棒的教程:w3school 的 html 教程供學習使用。這裏只介紹一點點本項目涉及的模板相關知識,其實 django 文檔的入門教程的六個 parts 中涵蓋的點已經足以對付此簡單的 Blog 項目了。

  • 模板標籤,用{% %} 表示,一些經常使用的有{% for %}循環標籤,{% if %}判斷標籤等。

  • 模板變量,用{{ variable }}表示,模板渲染是這些變量會被數據庫中相應的值代替,例如article_list = Article.objects.filter(status='p'),從數據庫中取出了已發佈的文章列表,賦給了 article_list 變量。若是模板文件中有以下代碼:

{% for article in article_list %}
    {{article.title}}

那麼渲染時就會循環渲染 n 篇文章,而且 {{article.title}} 也會被存儲在數據庫中文章的標題取代。

更多詳細的資料,請參考官方文檔關於 template 的介紹,或者中文文檔

編寫 URL

寫好了數據庫、視圖和模板,如今就是當用戶在瀏覽器輸入 url 訪問咱們的 Blog 時要告訴 django 哪一個 url 的請求對應哪一個視圖函數來處理,經過 urls.py 來指定:

urls.py

urlpatterns = [

    ...
    url(r'^blog/', views.IndexView.as_view()),
    # 首頁調用IndexView
    ...

]

至此,Blog 應用的首頁算是完成了,當用戶訪問咱們的主頁就能夠看到文章列表了:

Django 博客首頁

接下來作什麼?

至此,咱們完成了博客的首頁以展現文章列表的功能,接下來咱們會爲咱們的 Blog 添加詳情頁面和分類頁面功能,即用戶點擊文章標題或者閱讀原文後進入文章的詳細頁面,點擊分類則展現該分類下的所有文章列表。敬請期待咱們下一週的教程。若是你但願爲你的 Blog 添加其餘更加獨特的功能,也請隨時告訴咱們。

相關文章
相關標籤/搜索