個人博客三-首頁后臺開發(fā)

聲明:本渣渣部分代碼參考自TendCode其實(shí)有很多代碼是不需要自己一行行碼出來邢羔,生產(chǎn)力是第一位桑孩。只有研究型人才需要生產(chǎn)代碼流椒,作為一名渣渣拿來用是最高效的做法。程序員都有一個開源的精神温数,碼出來的代碼本身是希望更多的人用到蜻势,應(yīng)用到生產(chǎn)中握玛。
參考編寫博客的 Model 與首頁面
整合資源也應(yīng)該是一個碼農(nóng)的必備能力挠铲,在實(shí)際生產(chǎn)中可以更高效的工作

項(xiàng)目環(huán)境

windows10
python==3.6.6
django==1.11.1

首先本渣渣想對django項(xiàng)目結(jié)構(gòu)做一下梳理拂苹,如果有的讀者對django不太熟悉,可能閱讀有障礙浴韭。
對django基礎(chǔ)做一下簡單了解囱桨。

推薦閱讀:

Django1.10 中文文檔

大牛翻譯的django基礎(chǔ)部分

簡單了解通用視圖

開始 Django 開發(fā)之前,需要掌握以下知識:
? 創(chuàng)建 Django 工程窘面,了解 Django 默認(rèn)的工程目錄結(jié)構(gòu)
? 創(chuàng)建 Django APP
? 理解 Django 的MTV 模式财边,學(xué)會編寫 Model点骑、View黑滴、Template
? Django 如何處理靜態(tài)文件袁辈,即各種 CSS,JS媳危,以及圖片文件等

推薦閱讀:
個人博客-創(chuàng)建項(xiàng)目
Django中MVC與MVT設(shè)計(jì)模式

Django的工作流程
1待笑、 用戶通過瀏覽器輸入相應(yīng)的 URL 發(fā)起 HTTP 請求(一般是 GET/POST)
用戶在網(wǎng)站前臺做的每次操作都是一次HTTP請求的觸發(fā)莺债,通過觸發(fā)的URL齐邦,和后臺進(jìn)行交互
2:Django后臺接收到請求,檢測 urls.py 文件措拇,找到和用戶請求的URL 相匹配的項(xiàng)丐吓,然后調(diào)用該 URL 對應(yīng)的視圖函數(shù)(view)券犁,在視圖內(nèi)進(jìn)行邏輯呈現(xiàn)粘衬,然后渲染數(shù)據(jù)到模板展示給用戶。

推薦閱讀:

靜態(tài)路由和動態(tài)路由

視圖函數(shù)被調(diào)用后勘伺,可能會訪問數(shù)據(jù)庫(Model)去查詢用戶想要請求的數(shù)據(jù)褂删,并加載模板文件(Template)飞醉,渲染完數(shù)據(jù)后打包成 HttpResponse 返回給瀏覽器(Http協(xié)議)

從流程可以看出,開發(fā)者需要做的事情如下:
? 編寫相應(yīng)的 url
? 編寫數(shù)據(jù)庫(Model)
? 編寫處理 Http 請求的視圖函數(shù)(View)
? 編寫需要渲染數(shù)據(jù)的模板(Template)

下面遵循這樣的開發(fā)流程繼續(xù)進(jìn)行我們個人博客的開發(fā):

雖然博客站點(diǎn)的django項(xiàng)目已經(jīng)爛大街了屯阀,但是很多人還沒意識到個人博客的價值缅帘,有時間我們可以談?wù)勥@個問題。

第一版選擇使用Django通用視圖開發(fā)难衰,后續(xù)升級前后端分離開發(fā)(正在學(xué)習(xí)中)

推薦閱讀:

Django通用視圖

ListView 和 DetailView

在接觸到django到現(xiàn)在看到的教程大都沒有采用django的通用視圖钦无,但是為了更好的認(rèn)識django,在這里本渣渣召衔,想嘗試盡量在開發(fā)博客主體時使用通用視圖

為什么選擇使用通用視圖

1、 目前在看到的django教程中大部分都未使用通用視圖,頂多是繼承通用類趣席。這樣你就沒辦法真正了解django框架兵志,django獨(dú)特之處就在于構(gòu)建Web應(yīng)用程序的常用功能已經(jīng)在框架內(nèi),而不是單獨(dú)的庫宣肚。通用視圖是Django為解決建站過程中的常見的呈現(xiàn)模式而建立的
通用視圖使用原則
代碼越少越好
永遠(yuǎn)不要重復(fù)代碼
view應(yīng)當(dāng)只呈現(xiàn)邏輯, 不應(yīng)包含業(yè)務(wù)邏輯
保持view邏輯清晰簡單
2想罕、 鍛煉快速高效開發(fā)一類網(wǎng)站的能力
了解了通用視圖你可以快速開發(fā)一類網(wǎng)站比如博客、論壇都有相似的需求

3霉涨、 組合方便
這里本渣渣的做法是扒取崔慶才個人博客前端源碼按价,然后通過django實(shí)現(xiàn)網(wǎng)站后端開發(fā),使用django 通用視圖笙瑟,可以縮短開發(fā)周期楼镐,而且能夠具備使用django快速模仿一個網(wǎng)站的能力

下面不廢話開干

按流程來,規(guī)范的流程少出錯往枷,嚴(yán)謹(jǐn)應(yīng)該是一個碼農(nóng)的素養(yǎng)
目前項(xiàng)目文件結(jié)構(gòu)

1框产、前端
抓取崔慶才個人博客網(wǎng)站前端源碼一文中抓取的崔慶才博客前端源碼放入個人博客-創(chuàng)建項(xiàng)目一文中創(chuàng)建的項(xiàng)目中
http://www.reibang.com/p/24648705d9bd

2、配置基本信息
設(shè)置blog/settings.py
添加 apps 目錄

 sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

添加app

# Application definition
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    'storm',
]

添加模板

ROOT_URLCONF = 'blog.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],  # 設(shè)置視圖
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

連接數(shù)據(jù)庫错洁,首先要在本地?cái)?shù)據(jù)庫創(chuàng)建名為blog的數(shù)據(jù)庫
這里需要用到數(shù)據(jù)庫連接包秉宿,
請參考安裝python包到虛擬環(huán)境安裝包
Name: mysqlclient
Version: 1.4.2.post1

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': 'localhost',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': 'root',
        'NAME': 'blog',
        # 如果創(chuàng)建的數(shù)據(jù)庫是uft-8編碼,映射數(shù)據(jù)庫時出現(xiàn)警告,添加此行解決問題
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
            'charset': 'utf8mb4',
        },
    }
}

配置靜態(tài)文件路徑

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

model.py編寫

針對blog開發(fā)大體有這幾個通用的models類

文章屯碴、幻燈片描睦、文章標(biāo)簽、文章分類导而、友情鏈接

這里為了后期能夠更好的給本站做SEO優(yōu)化忱叭,這里添加了一個,文章關(guān)鍵詞嗡载,死鏈

文章窑多、幻燈片仍稀、文章標(biāo)簽洼滚、文章分類、友情鏈接技潘、關(guān)鍵詞遥巴、死鏈

由此可見,設(shè)計(jì)數(shù)據(jù)庫結(jié)構(gòu)就是編寫 models享幽,數(shù)據(jù)庫中每一個實(shí)體對應(yīng)的表在 django 中對用著 models.py 中的一個類铲掐,類的屬性對應(yīng)著數(shù)據(jù)庫表的屬性列。

# 文章關(guān)鍵詞值桩,用來作為SEO中keywords
class Keyword(models.Model):
    name = models.CharField('文章關(guān)鍵詞', max_length=20)

    class Meta:
        verbose_name = '關(guān)鍵詞'
        verbose_name_plural = verbose_name
        ordering = ['name']

    def __str__(self):
        return self.name


# 文章標(biāo)簽
class Tag(models.Model):
    name = models.CharField('文章標(biāo)簽', max_length=20)
    slug = models.SlugField(unique=True)
    description = models.TextField('描述', max_length=240, default=settings.SITE_DESCRIPTION,
                                   help_text='用來作為SEO中description,長度參考SEO標(biāo)準(zhǔn)')

    class Meta:
        verbose_name = '標(biāo)簽'
        verbose_name_plural = verbose_name
        ordering = ['id']

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('blog:tag', kwargs={'slug': self.slug})

    def get_article_list(self):
        '''返回當(dāng)前標(biāo)簽下所有發(fā)表的文章列表'''
        return Article.objects.filter(tags=self)


# 文章分類
class Category(models.Model):
    name = models.CharField('文章分類', max_length=20)
    slug = models.SlugField(unique=True)
    description = models.TextField('描述', max_length=240, default=settings.SITE_DESCRIPTION,
                                   help_text='用來作為SEO中description,長度參考SEO標(biāo)準(zhǔn)')

    class Meta:
        verbose_name = '分類'
        verbose_name_plural = verbose_name
        ordering = ['name']

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('blog:category', kwargs={'slug': self.slug})

    def get_article_list(self):
        return Article.objects.filter(category=self)


# 文章
class Article(models.Model):

    # 文章縮略圖
    IMG_LINK = '/static/img/summary.png'
    
    author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='作者')
    
    # 文章標(biāo)題摆霉,CharField 表示對應(yīng)數(shù)據(jù)庫中數(shù)據(jù)表的列的數(shù)據(jù)類型,'標(biāo)題'是一個位置參數(shù)     
    #(verbose_name),主要用于 django 的后臺系統(tǒng)携栋。max_length 表示能存儲的字符串    
    # 的最大長度
    title = models.CharField(max_length=150, verbose_name='文章標(biāo)題')
    
    # 這里填的內(nèi)容有助于后期SEO優(yōu)化
    summary = models.TextField('文章摘要', max_length=230, default='文章摘要等同于網(wǎng)頁description內(nèi)容搭盾,請務(wù)必填寫...')
    
    # 文章正文,TextField 用來存儲大文本字符
    body = models.TextField(verbose_name='文章內(nèi)容')
    
    # 文章縮略圖地址
    img_link = models.CharField('圖片地址', default=IMG_LINK, max_length=255)
    
     # 文章創(chuàng)建時間婉支,DateTimeField用于存儲時間鸯隅,設(shè)定auto_now_add參數(shù)為真,則在文章被創(chuàng)建時會自動添加創(chuàng)建時間
    create_date = models.DateTimeField(verbose_name='創(chuàng)建時間', auto_now_add=True)
    
    # 文章最后一次編輯時間向挖,auto_now=True表示每次修改文章時自動添加修改的時間
    update_date = models.DateTimeField(verbose_name='修改時間', auto_now=True)
    
    # 閱覽量蝌以,PositiveIntegerField存儲非負(fù)整數(shù)
    # views = models.PositiveIntegerField('閱覽量', default=0)
    views = models.IntegerField('閱覽量', default=0)
    
    slug = models.SlugField(unique=True)

# 文章的分類,F(xiàn)oreignKey即數(shù)據(jù)庫中的外鍵何之。外鍵的定義是:如果數(shù)據(jù)庫中某個表的列的值是另外一個表的主鍵跟畅。外鍵定義了一個一對多的關(guān)系,這里即一篇文章對應(yīng)一個分類溶推,而一個分類下可能有多篇文章碍彭。詳情參考django官方文檔關(guān)于ForeinKey的說明,on_delete=models.SET_NULL表示刪除某個分類(category)后該分類下所有的Article的外鍵設(shè)為null(空)

    category = models.ForeignKey(Category, verbose_name='文章分類',on_delete=models.SET_NULL)
    tags = models.ManyToManyField(Tag, verbose_name='標(biāo)簽')
    
    keywords = models.ManyToManyField(Keyword, verbose_name='文章關(guān)鍵詞',
                                      help_text='文章關(guān)鍵詞悼潭,用來作為SEO中keywords庇忌,最好使用長尾詞,3-4個足夠')
    
    def __str__(self):
        # 主要用于交互解釋器顯示表示該類的字符串
        return self.title

    class Meta:
        verbose_name = '文章'
        verbose_name_plural = verbose_name
        ordering = ['-create_date']


# 幻燈片
class Carousel(models.Model):
    number = models.IntegerField('編號', help_text='編號決定圖片播放的順序舰褪,圖片不要多于5張')
    title = models.CharField('標(biāo)題', max_length=20, blank=True, null=True, help_text='標(biāo)題可以為空')
    content = models.CharField('描述', max_length=80)
    img_url = models.CharField('圖片地址', max_length=200)
    url = models.CharField('跳轉(zhuǎn)鏈接', max_length=200, default='#', help_text='圖片跳轉(zhuǎn)的超鏈接皆疹,默認(rèn)#表示不跳轉(zhuǎn)')

    class Meta:
        verbose_name = '圖片輪播'
        verbose_name_plural = verbose_name
        # 編號越小越靠前,添加的時間越晚越靠前
        ordering = ['number', '-id']

    def __str__(self):
        return self.content[:25]


# 死鏈
class Silian(models.Model):
    badurl = models.CharField('死鏈地址', max_length=200, help_text='注意:地址是以http開頭的完整鏈接格式')
    remark = models.CharField('死鏈說明', max_length=50, blank=True, null=True)
    add_date = models.DateTimeField('提交日期', auto_now_add=True)

    class Meta:
        verbose_name = '死鏈'
        verbose_name_plural = verbose_name
        ordering = ['-add_date']

    def __str__(self):
        return self.badurl


class FriendLink(models.Model):
    name = models.CharField('網(wǎng)站名稱', max_length=50)
    description = models.CharField('網(wǎng)站描述', max_length=100, blank=True)
    link = models.URLField('友鏈地址', help_text='請?zhí)顚慼ttp或https開頭的完整形式地址')
    logo = models.URLField('網(wǎng)站LOGO', help_text='請?zhí)顚慼ttp或https開頭的完整形式地址', blank=True)
    create_date = models.DateTimeField('創(chuàng)建時間', auto_now_add=True)
    is_active = models.BooleanField('是否有效', default=True)
    is_show = models.BooleanField('是否首頁展示', default=False)

    class Meta:
        verbose_name = '友情鏈接'
        verbose_name_plural = verbose_name
        ordering = ['create_date']

    def __str__(self):
        return self.name

    def get_home_url(self):
        '''提取友鏈的主頁'''
        u = re.findall(r'(http|https://.*?)/.*?', self.link)
        home_url = u[0] if u else self.link
        return home_url

    def active_to_false(self):
        self.is_active = False
        self.save(update_fields=['is_active'])

    def show_to_false(self):
        self.is_show = True
        self.save(update_fields=['is_show'])

model 定義完畢后占拍,運(yùn)行以下命令即可生成相應(yīng)的數(shù)據(jù)庫表:

python manage.py makemigrations
python manage.py migrate

針對models分別給出以下參考資料供學(xué)習(xí):

Models:
官方文檔
Django1.10 中文文檔
大牛翻譯

推薦學(xué)習(xí):
自強(qiáng)學(xué)堂
Django的ORM映射機(jī)制與數(shù)據(jù)庫實(shí)戰(zhàn)
數(shù)據(jù)庫模型(Models)對象映射表ORM

field(字段選項(xiàng)):
官方文檔
個人技術(shù)博文

ForeinKey(一對多)略就、ManyToMany(多對多)、OneToOne(一對一):
官方文檔
Django的ORM映射機(jī)制與數(shù)據(jù)庫實(shí)戰(zhàn)

View編寫

上面已經(jīng)介紹了 django 應(yīng)用的工作流程晃酒,數(shù)據(jù)庫建立完畢后需要編寫視圖函數(shù)(view)來處理 Http 請求表牢。同樣先來看 django 的 view 代碼是如何寫的,這里數(shù)據(jù)庫內(nèi)沒有文章先不做文章展示邏輯編寫贝次,待后續(xù)一一進(jìn)行崔兴,這里只寫一個視圖讓首頁可以被訪問。

視圖代碼

from django.views import generic
from django.conf import settings
from .models import Article, Tag, Category, Timeline, Silian


# Create your views here.
class IndexView(generic.ListView):
    """
        首頁視圖,繼承自ListVIew蛔翅,用于展示從數(shù)據(jù)庫中獲取的文章列表
    """
    
    # 獲取數(shù)據(jù)庫中的文章列表
    model = Article
    
    # template_name屬性用于指定使用哪個模板進(jìn)行渲染
    template_name = 'index.html'
    
    # context_object_name屬性用于給上下文變量取名(在模板中使用該名字)
    context_object_name = 'articles'

配置路由

blog/urls.py

from django.conf.urls import url, include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    # allauth
    url(r'^accounts/', include('allauth.urls')),

    # storm
    url('', include('storm.urls', namespace='blog')),  # blog
]

apps/storm/urls.py

# ---------------------------
__author__ = 'stormsha'
__date__ = '2019/2/20 23:27'
# ---------------------------

from django.conf.urls import url
# from .views import goview
from .views import IndexView

urlpatterns = [

    url(r'^$', IndexView.as_view(), name='index'),  # 主頁敲茄,自然排序

]

運(yùn)行效果

運(yùn)行效果.png

現(xiàn)在首頁流程基本走通之,差視圖內(nèi)的邏輯山析、和數(shù)據(jù)渲染的問題了堰燎,靜待后續(xù)。

總結(jié)
本渣渣也是在繁忙的工作至于笋轨,抽出點(diǎn)時間想自己搞一下博客秆剪,但是不想草草了事赊淑,想從這個項(xiàng)目中實(shí)踐如下知識

抓取網(wǎng)站前端頁面源碼、Django通用視圖仅讽、django rest framework膏燃、vue.js、redis數(shù)據(jù)緩存何什、docker容器部署组哩、git、SEO技術(shù)

錢途:想法——實(shí)現(xiàn)——部署——運(yùn)營——維護(hù)——盈利

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末处渣,一起剝皮案震驚了整個濱河市伶贰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌罐栈,老刑警劉巖黍衙,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異荠诬,居然都是意外死亡琅翻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門柑贞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來方椎,“玉大人,你說我怎么就攤上這事钧嘶√闹冢” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵有决,是天一觀的道長闸拿。 經(jīng)常有香客問我,道長书幕,這世上最難降的妖魔是什么新荤? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮台汇,結(jié)果婚禮上苛骨,老公的妹妹穿的比我還像新娘。我一直安慰自己励七,他們只是感情好智袭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布奔缠。 她就那樣靜靜地躺著掠抬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪校哎。 梳的紋絲不亂的頭發(fā)上两波,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天瞳步,我揣著相機(jī)與錄音,去河邊找鬼腰奋。 笑死单起,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的劣坊。 我是一名探鬼主播嘀倒,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼局冰!你這毒婦竟也來了测蘑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤康二,失蹤者是張志新(化名)和其女友劉穎碳胳,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沫勿,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挨约,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了产雹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诫惭。...
    茶點(diǎn)故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蔓挖,靈堂內(nèi)的尸體忽然破棺而出贝攒,到底是詐尸還是另有隱情,我是刑警寧澤时甚,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布隘弊,位于F島的核電站,受9級特大地震影響荒适,放射性物質(zhì)發(fā)生泄漏梨熙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一刀诬、第九天 我趴在偏房一處隱蔽的房頂上張望咽扇。 院中可真熱鬧,春花似錦陕壹、人聲如沸质欲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘶伟。三九已至,卻和暖如春又碌,著一層夾襖步出監(jiān)牢的瞬間九昧,已是汗流浹背绊袋。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留铸鹰,地道東北人癌别。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像蹋笼,于是被迫代替她去往敵國和親展姐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評論 2 354