Django-博客搭建

本人未專門學(xué)過前端后端知識,只是一知半解,這篇文章主要作為扒源代碼的思路,具體細(xì)節(jié)并未詳細(xì)介紹?。?!

Blog搭建

博客系統(tǒng)使用python編寫,基于Django和clean-blog前段框架編寫。
本文主要是修改DCblog并通過源碼進(jìn)行階段性掃盲?。?!

DCblog app

查看urls.py文件

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^$', views.index, name='index'),
    url(r'^about/', views.about_view, name='about'),
    url(r'^article/', include('article.urls'), name='article'),
    url(r'^tag/', include('tag.urls'), name='tag'),
    url(r'^author/', include('author.urls'), name='author'),
]

urlpatterns += staticfiles_urlpatterns()
handler404 = 'dcblog.views.page404'
handler500 = 'dcblog.views.page500'

下面主要對這幾個url進(jìn)行介紹

url(r'^$', views.index, name='index'),

這兒根目錄調(diào)用的是article.views.index,內(nèi)容如下:
'''
def index(request):
paginator = Paginator(Article.objects.all(), 10)#實例化一個分頁對象
page = request.GET.get('page')#獲取頁碼
try:
articles = paginator.page(page)#獲取某頁對應(yīng)的記錄
except PageNotAnInteger:
articles = paginator.page(1)#如果頁碼不是整數(shù),取第一頁
except EmptyPage:
articles = paginator.page(paginator.num_pages)#如果頁碼太大,沒有相應(yīng)記錄,取最后一頁
return render(request, 'home.html', context={
'articles': articles
})
'''
打開home.html,里面內(nèi)容介紹如下:
首先介紹Django的模板繼承,也就是

{% extends 'base.html' %}

這兒繼承的是base.html模板,查看base.html模板就能發(fā)現(xiàn),這是博客的骨架。打開base.html,如下圖:


這兒大家就可以根據(jù)自己的需要修改文字或者是圖片,除了base.html文件中出現(xiàn)的文字,其他的都在dcblog/settings.py文件的DCBLOG_CONFIG中。
下面回到home.html文件中。
在繼承base.html模板后,home.html繼續(xù)做填充,填充方法如下:

{% extends "master.html" %}
 
{% block content1 %}
    content1里填充的內(nèi)容
{% endblock %}

這兒填充的內(nèi)容主要是顯示頁碼內(nèi)的文章和跳轉(zhuǎn)頁碼。

具體細(xì)節(jié)可以看代碼注釋

url(r'^about/', views.about_view, name='about')

這兒調(diào)用的是about_view函數(shù),代碼如下:

def about_view(request):
    return render(request, 'about.html')

這兒沒什么好說的,打開about.html文件。這兒依然是使用繼承模板,然后發(fā)現(xiàn)如下代碼:

{% extends 'base.html' %}
{% block header_id %}tag-heading{% endblock %}
{% block header_title %}一技破萬法{% endblock %}
{% block header_subtitle %} 生活不止眼前的茍且, 還有詩和遠(yuǎn)方. {% endblock %}
{% block background-image %}{{ SITE_ABOUT_BACKGROUND }}{% endblock %}
{% block content %}

extend就是繼承父模板,然后下面進(jìn)行復(fù)寫、填充。其中block是在子模版中可能會被覆蓋掉的位置。在上面的例子中,block標(biāo)簽定義了三個可以被子模版內(nèi)容填充的block,分別是 header_title 、header_subtitle和background-image。

{% extends 'base.html' %}
{% block header_id %}tag-heading{% endblock %}
{% block header_title %}一技破萬法{% endblock %}
{% block header_subtitle %} 生活不止眼前的茍且, 還有詩和遠(yuǎn)方. {% endblock %}
{% block background-image %}{{ SITE_ABOUT_BACKGROUND }}{% endblock %}
{% block content %}

下面就是分塊填寫文字和鏈接,應(yīng)該都能看懂了。

url(r'^article/', include('article.urls'), name='article'),
url(r'(?P<article_id>[0-9]+)/$', views.detail, name='detail'),

首先介紹一下Django中的URL模塊

  1.  Django處理請求的方式
    

1) Django通過URLconf模塊來進(jìn)行判斷。通常情況下,這就是ROOT_URLCONF配置的價值,但是如果請求攜帶了一個urlconf的屬性(通常被中間件設(shè)置),那么這個被攜帶的urlconf將會替代ROOT_URLCONF的配置。
2) Django會調(diào)用Python模塊并尋找各種urlpatterns。這是一個屬于django.conf.urls.url()實例的python列表。
3) Django會遍歷每個URL pattern,自上而下,并且選取收割匹配請求URL的pattern。
4) 一旦匹配某個url pattern的正則表達(dá)式,Django將導(dǎo)入并調(diào)用相關(guān)的view(這是一個簡單的python函數(shù),或者是一個class-based view)
這個view將會傳遞下列參數(shù):

  • 一個HttpRequest的實例
  • 如果匹配了URL中一個no named group,那么參數(shù)將會按根據(jù)URL中的位置一一對應(yīng)
  • 如果匹配了URL中一個named group,且參數(shù)傳遞是通過named group來匹配的,那么參數(shù)將會被指定的kwargs代替。
    5) 如果沒有任何一個正則表達(dá)式被匹配,那么Django會拋出異常,并報錯。
  1.  URL中的named  group
    

URL可以通過named group方式傳遞指定參數(shù),語法為: (?P<name>pattern), name 可以理解為所要傳遞的參數(shù)的名稱,pattern代表所要匹配的模式。例如:

url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),

那么year,month將會對應(yīng)views傳遞過來的year,month的值,而后面緊跟的則代表正則表達(dá)匹配的模式。

  1. URL的反向解析
    通常來說在處理完一個表單之后,網(wǎng)頁會發(fā)生跳轉(zhuǎn)。通常寫URL我們都避免硬編碼,這樣不方便后期的調(diào)整。通常我們需要從URL獲取兩種內(nèi)容,最主要是view能夠通過URL獲取一些標(biāo)識并處理,另一些信息則是傳遞過來的參數(shù)。
    Django提供了一種解決方案,URL mapper是與URL設(shè)計一一對應(yīng)。你可以通過URLconf來實現(xiàn),并反向使用它。例如,
    ? 由用戶通過瀏覽器發(fā)起URL請求,調(diào)用view,并將URL中的參數(shù)傳遞給view
    ? 通過view并附上相應(yīng)參數(shù),找到相應(yīng)匹配的URL。
    后者我們稱之為對URLs的反向解析。反向解析的例子,
url(r'^articles/([0-9]{4})/$', views.year_archive, name='news-year-archive'),

下面對于這個鏈接進(jìn)行解析一下:
當(dāng)在home.html中點擊文章時,會跳轉(zhuǎn)到文章界面,其中跳轉(zhuǎn)的路徑為:{% url 'article:detail' article.id%}。假設(shè)點擊最上面一篇文章,地址為:http://x.x.x.x/article/12/,也就是article.id=12,然后跳轉(zhuǎn)到detail函數(shù):

def detail(requests, article_id):
    article = get_object_or_404(Article, pk=article_id)
    # article.content = markdown.markdown(article.content, extensions=[
    #     'markdown.extensions.extra',
    #     'markdown.extensions.codehilite',
    #     'markdown.extensions.toc'
    # ])
    tags = article.tag.all()
    return render(requests, 'article_detail.html', context={
        'article': article,
        'tags': tags
    })

介紹函數(shù): article = get_object_or_404(Article, pk=article_id)
用特定查詢條件獲取某個對象,成功則返回該對象,否則引發(fā)一個 Http404。

get_object_or_404(klass, *args, **kwargs)

參數(shù):

  • klass
    接受一個 Model 類,Manager 或 QuerySet 實例,表示你要對該對象進(jìn)行查詢。
  • kwargs
    查詢條件,格式需要被 get() 和 filter() 接受。
    這兒將所有的標(biāo)簽(article和tags)傳遞到article_detail.html代碼中,然后在里面調(diào)用。
    打開article_detail.html代碼,可以看到如下幾部分:
  1. 標(biāo)簽頁跳轉(zhuǎn):顯示所有tags,點擊跳轉(zhuǎn)到標(biāo)簽頁即tags。
  2. 編輯文章:只有登錄了才能有這一個選項,點擊跳轉(zhuǎn)到edit函數(shù),
url(r'(?P<article_id>[0-9]+)/edit$', views.edit, name='edit'),

這兒就是編輯文章所對應(yīng)的url,先進(jìn)入edit函數(shù)看一下:

@login_required(login_url=reverse_lazy('author:login'))
def edit(request, article_id):
    article = get_object_or_404(Article, pk=article_id)
    if article.author != request.user and request.user.is_superuser:
        return HttpResponseForbidden(render_to_response('error.html', {
            'status_code': 403,
            'message': 'Forbidden :('
        }))
    form = ArticleForm(request.POST or None, instance=article)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect(reverse_lazy('article:detail', kwargs={
            'article_id': form.instance.id
        }))
    context={
        'form': form,
        'header_id': 'tag-heading',
        'title': '編輯文章',
        'subtitle': form.instance.title,
        'background': form.instance.background or settings.DCBLOG_CONFIG.get('SITE_ARTICLE_BACKGROUND'),
        'submit': '保存編輯'
    }
    return render(request, 'generic_form.html', context=context)

這兒首先讀取article,然后判斷登錄的user是不是文章作者,只有文章作者才能修改文件。非文章作者返回值如下:



往下接著讀代碼,這兒添加一個表單
表單內(nèi)容為:

<tr><th><label for="id_title">標(biāo)題:</label></th><td><input type="text" name="title" value="ff" class="form-control" placeholder="標(biāo)題" maxlength="100" required id="id_title"></td></tr>
<tr><th><label for="id_background">背景圖片:</label></th><td><input type="text" name="background" class="form-control" placeholder="背景URL, 默認(rèn) /static/img/article-bg.png" maxlength="500" id="id_background"></td></tr>
<tr><th><label for="id_tag_list">Tag list:</label></th><td><input type="text" name="tag_list" value="sddf" class="form-control" placeholder="Tags" id="id_tag_list"></td></tr>
<tr><th><label for="id_content">正文:</label></th><td><textarea name="content" cols="40" rows="10" class="form-control" placeholder="markdown正文" row="20" id="id_content">
df</textarea></td></tr>

代碼理解后續(xù)補上

    form = ArticleForm(request.POST or None, instance=article)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect(reverse_lazy('article:detail', kwargs={
            'article_id': form.instance.id
        }))

然后將參數(shù)傳遞給generic_form.html代碼

{% extends "base.html" %}
{% block head %}
    {{ block.super }}
    <link rel="stylesheet" href="/static/css/hux-blog.min.css">
{% endblock %}

{% block background-image %}{% spaceless %}
    {% if background %}
        {{ background }}
    {% else %}
        {{ SITE_FORM_BACKGROUND }}
    {% endif %}
{% endspaceless %}{% endblock %}
{% if header_id %}
    {% block header_id %}{{ header_id }}{% endblock %}
{% endif %}
{% block header_title %}{{ title }}{% endblock %}
{% block header_subtitle %}{{ subtitle }}{% endblock %

在這段代碼中,就是將context中的內(nèi)容顯示出,然后下面就是細(xì)化每個模塊,這兒
調(diào)用form表單,也就是上面表單內(nèi)容,創(chuàng)建四個窗口并輸入。然后創(chuàng)建一個保存編輯按鈕。


url(r'^tag/', include('tag.urls'), name='tag'),

進(jìn)入tag/urls.py函數(shù),可以看到:


app_name = 'tag'
urlpatterns = [
    url(r'^$', views.tag_index, name='tag_index'),
]

進(jìn)入views.py函數(shù):


def tag_index(request):
    tags = Tag.objects.all()
    return render(request, 'tag.html', {'tags': tags})

這兒調(diào)用的是tag.html代碼,進(jìn)入html代碼:

{% extends 'base.html' %}
{% block head %}
    {{ block.super }}
    <link rel="stylesheet" href="/static/css/hux-blog.min.css">
{% endblock %}


{% block header_title %}標(biāo)簽{% endblock %}
{% block header_subtitle %}
<div id="tag_cloud" class="tags">
    {% for tag in tags %}
    <a href="#{{ tag.name }}" style="background-color: rgb(0, 133, 161);">{{ tag.name }}</a>
    {% endfor %}
</div>
{% endblock %}
{% block background-image %}{{ SITE_TAG_BACKGROUND }}{% endblock %}

這兒就是把title改成標(biāo)簽,然后將所有標(biāo)簽進(jìn)行排列



其中每個標(biāo)簽都帶有herf,分別跳到下面每個標(biāo)簽?zāi)K,下面每個標(biāo)簽?zāi)K都有一個標(biāo)簽名,后面for排列出該標(biāo)簽的文章,點擊文章調(diào)用article:detail article.id顯示文章。

url(r'^author/', include('author.urls'), name='author'),

進(jìn)入author/urls.py中, 總共三個二級url,分別對應(yīng)登錄、注冊、注銷三部分

url(r'^login/', views.login_view, name='login'),

查看login_view函數(shù)

@login_denied
def login_view(request):
    form = LoginForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        username = form.cleaned_data['username']
        password = form.cleaned_data['password']
        user = User.objects.filter(username=username).first()
        if user and user.check_password(password):
            login(request, user)
            return HttpResponseRedirect(reverse_lazy('index'))
        messages.add_message(request, messages.ERROR, '用戶名或密碼錯誤.')
    context = {'form': form,
               'title': '登陸',
               'subtitle': 'login site',
               'submit': '登陸'
               }
    return render(request, 'generic_form.html', context)

這兒調(diào)用LoginForm表單,然后將輸入添加到表單,再進(jìn)行對比,顯示界面由genetic_form.html進(jìn)行顯示,登錄成功之后返回主界面。

url(r'^register/', views.register_view, name='register'),

查看register_view函數(shù)

@login_denied
def register_view(request):
    form = RegisterForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return HttpResponseRedirect(reverse_lazy('index'))
    context = {
        'form': form,
        'title': '注冊',
        'subtitle': 'register and write',
        'submit': '注冊'
    }
    return render(request, 'generic_form.html', context)

這兒調(diào)用RegisterForm表單,同上!

url(r'^logout/', views.logout_view, name='logout'),

這兒沒什么好講的,就是退出返回到最原始界面。



到這兒基本上就能看懂這個博客的大體架構(gòu)了,具體細(xì)節(jié)部分如果后期還要改再扒?。?!

fork自基于Django和clean-blog前端框架的博客系統(tǒng)

一技破萬法
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容