Django1.9開發博客(7)- 實現功能


到目前為止我們已經完成了一個django應用的所有基礎部分。 包括url配置、視圖、模型和模板。接下來開始繼續完善我們的博客系統了。

首先我們需要一個顯示每篇文章的詳細頁面,對不?

文章詳情

對於首頁每一篇文章,我們希望點擊標題后可以進入該文章的閱讀頁面。修改post_list.html中的標題href如下:

1
<h1><a href="{% url 'blog.views.post_detail' pk=post.pk %}">{{ post.title }}</a></h1>

 

我來詳細解釋下這個{% url ‘blog.views.post_detail’ pk=post.pk %},{% %} 表示使用django模板標簽而不是普通的HTML文字,這里我們使用了url標簽來生成真正的url鏈接。 blog.views.post_detail是視圖的全路徑。

url配置

我們希望文章詳細頁面的鏈接類似這樣:http://127.0.0.1:8000/post/1/

修改blog/urls.py為下面的這樣:

1
2
3
4
5
6
7
from django.conf.urls import patterns, include, url
from . import views

urlpatterns = patterns('',
url(r'^$', views.post_list),
url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail),
)

 

這個看起來有點復雜,我們來解釋下:

  1. ^ 代表的是開始
  2. post/表示URL開始必須是post/
  3. (?P[0-9]+) – 這部分比較復雜。它表示一個命名參數pk, 它會捕獲url中的這部分然后將它賦值給pk參數傳遞給視圖。 [0-9]表示這部分必須是數字,+表示至少1個數字,也可以多個數字。
  4. / – 然后后面接/
  5. $ – URL的結尾

post_detail視圖

現在去訪問還會報錯,因為我們還沒有post_detail這個視圖。現在我們開始定義它。

修改文件blog/views.py如下:

1
2
3
4
5
from django.shortcuts import render, get_object_or_404

def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})

 

post_detail模板

然后再增加模板blog/templates/blog/post_detail.html:

1
2
3
4
5
6
7
8
9
10
11
{% extends 'blog/base.html' %}

{% block content %}
<div class="date">
{% if post.published_date %}
{{ post.published_date }}
{% endif %}
</div>
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaks }}</p>
{% endblock %}

 

這次我們還是采用模板繼承方式,這里我們還用到了模板標簽if,這是一個條件判斷的標簽。

OK,一切都已准備就緒,現在打開首頁,然后點擊任意一篇文章標題看下結果:

 

搞定!!

創建文章

最后一件事就是要實現文章創建和更新操作,這是博客系統最核心的功能。django自帶的admin很酷,但是確很難定制和美化。 forms非常強大和自由,我們可以好好的利用它來實現我們需要的功能。

forms一個很好的特性就是它既能從頭定義一個表單,也能創建一個ModelForm來將表單結果保存為一個模型。 而這正是我們想要的功能,我們可以創建一個ModelForm來將表單轉換為一個Post模型。

表單對象的定義放在forms.py文件中。我們需要在blog文件夾中創建forms.py文件,結構如下:

blog
   └── forms.py

在里面寫入如下內容:

1
2
3
4
5
6
7
8
from django import forms
from .models import Post

class PostForm(forms.ModelForm):

class Meta:
model = Post
fields = ('title', 'text',)

 

PostForm需要繼承自forms.ModelForm,這樣django就能實現某些神奇的效果。 在里面我們定義了元類Meta,然后指定model為Post,還有字段為title和text。 因為我們只需要對外暴露標題和內容,至於作者就是登陸用戶了,而發布日期和創建日期就是提交時間。

下面我們要做的就是在view中使用我們的form,並在template中顯示它。

我們繼續走四個步驟:頁面上添加鏈接, 外加“三部曲”。基本上每個新功能的增加時只需要增加這四個東東就行了。

增加鏈接

打開blog/templates/blog/base.html,在名字為page-header的div中添加一個新增文章的鏈接:

1
<a href="{% url 'blog.views.post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>

 

這時候你的base.html應該是這樣的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{% load staticfiles %}
<html>
<head>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<link href="http://fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
<title>Django Girls Blog</title>
</head>
<body>
<div class="page-header">
<a href="{% url 'blog.views.post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
<h1><a href="/">Django Girls Blog</a></h1>
</div>
<div class="content">
<div class="row">
<div class="col-md-8">
{% block content %}
{% endblock %}
</div>
</div>
</div>
</body>
</html>

 

URL

打開blog/urls.py文件,添加一條配置:

1
url(r'^post/new/$', views.post_new, name='post_new'),

 

現在它的內容應該是這樣的:

1
2
3
4
5
6
7
8
from django.conf.urls import patterns, include, url
from . import views

urlpatterns = patterns('',
url(r'^$', views.post_list),
url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail),
url(r'^post/new/$', views.post_new, name='post_new'),
)

 

post_new視圖

打開文件blog/views.py,先引入PostForm

1
from .forms import PostForm

 

然后增加視圖:

1
2
3
def post_new(request):
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})

 

post_edit.html模板

在blog/templates/blog目錄新建一個post_edit.html頁面,然后寫入下列內容:

1
2
3
4
5
6
7
8
9
{% extends 'blog/base.html' %}

{% block content %}
<h1>New post</h1>
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
{% endblock %}

 

保存后,刷新首頁,點擊加號那個鏈接可以看到如下頁面:

但是當你寫了文字后點擊保存后會發現又跑到這個新建頁面來了。 因為這個是POST提交,但是URL還是一樣的,又會跑到post_new那個視圖中去, 這個視圖只做了頁面跳轉來到了這個新建頁面。

那么我們需要修改下post_new視圖邏輯了:

在頭部先引入下面的依賴:

1
2
from django.core.urlresolvers import reverse
from django.shortcuts import redirect

 

然后修改post_new視圖如下:

1
2
3
4
5
6
7
8
9
10
11
def post_new(request):
if request.method == "POST":
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('blog.views.post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'blog/post_edit.html', {'form': form})

 

上面表示我添加完一篇文章后自動跳轉到文章詳情頁面去,保存后效果:

 

表單驗證

由於我們在Post模型中已經定義了title和text是必需的,django會自動幫我們做驗證。 看下如果我們不輸入title和text直接提交會怎樣:

 

django已經自動幫我們做了驗證,是不是很酷呢?

編輯文章

我們剛剛已經實現了新建文章的功能,那么如果是編輯修改文章呢。接下來我會快速的講解這個流程,現在你應該是可以看得懂的了。

首先打開blog/templates/blog/post_detail.html,添加一行:

1
2
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}">
<span class="glyphicon glyphicon-pencil"></span></a>

 

現在它的內容是這樣的:

1
2
3
4
5
6
7
8
9
10
11
12
{% extends 'blog/base.html' %}

{% block content %}
<div class="date">
{% if post.published_date %}
{{ post.published_date }}
{% endif %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
</div>
<h1>{{ post.title }}</h1>
<p>{{ post.text|linebreaks }}</p>
{% endblock %}

 

然后修改blog/urls.py文件,添加一條:

1
url(r'^post/(?P<pk>[0-9]+)/edit/$', views.post_edit, name='post_edit'),

 

我們會重用模板blog/templates/blog/post_edit.html, 因此只需要修改下view就可以了,打開文件blog/views.py,將下面的內容添加到最后:

1
2
3
4
5
6
7
8
9
10
11
12
def post_edit(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = PostForm(request.POST, instance=post)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('blog.views.post_detail', pk=post.pk)
else:
form = PostForm(instance=post)
return render(request, 'blog/post_edit.html', {'form': form})

 

這個跟post_new幾乎一模一樣,先通過主鍵查到文章:post = get_object_or_404(Post, pk=pk), 然后我們在提交和進入編輯頁面的時候都將post作為instance參數傳遞給PostForm。

OK,現在讓我們來測試下效果:

 

 

 

完美,恭喜你!你的應用已經變得越來越酷了。


免責聲明!

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



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