Skip to content

Commit 9175339

Browse files
author
yangxg
committed
Step12: comments
1 parent 4d98a07 commit 9175339

File tree

15 files changed

+248
-7
lines changed

15 files changed

+248
-7
lines changed

blog/static/blog/css/custom.css

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ figure {
200200
padding-bottom: 4em;
201201
}
202202

203-
.post {
203+
.post, .comment-area {
204204
background: #fff;
205205
padding: 30px 30px 0;
206206
}
@@ -647,7 +647,7 @@ figure {
647647
* 10.0 - Contact Form
648648
*/
649649

650-
.contact-form input {
650+
.contact-form input, .comment-form input {
651651
border: 1px solid #aaa;
652652
margin-bottom: 15px;
653653
width: 100%;
@@ -657,7 +657,7 @@ figure {
657657
transition: 0.4s border-color linear;
658658
}
659659

660-
.contact-form textarea {
660+
.contact-form textarea, .comment-form textarea {
661661
border: 1px solid #aaa;
662662
margin-bottom: 15px;
663663
width: 100%;
@@ -668,8 +668,8 @@ figure {
668668
transition: 0.4s border-color linear;
669669
}
670670

671-
.contact-form input:focus,
672-
.contact-form textarea:focus {
671+
.contact-form input:focus, .comment-form input:focus,
672+
.contact-form textarea:focus, .comment-form textarea:focus {
673673
border-color: #666;
674674
}
675675

@@ -798,4 +798,31 @@ figure {
798798
.overlay ul li {
799799
min-height: 34px;
800800
}
801-
}
801+
}
802+
803+
/* Comment list */
804+
.comment-list {
805+
margin-top: 30px;
806+
font-size: 16px;
807+
}
808+
809+
.comment-item {
810+
border-bottom: 1px #ccc solid;
811+
margin-bottom: 20px;
812+
padding-bottom: 20px;
813+
}
814+
815+
.comment-item .name,
816+
.comment-item .date {
817+
color: #444;
818+
font-size: 14px;
819+
}
820+
821+
.comment-item .name:after {
822+
content: '·';
823+
}
824+
825+
.comment-item .text {
826+
padding-top: 5px;
827+
}
828+

blog/views.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from django.shortcuts import render, get_object_or_404
44

5+
from comments.forms import CommentForm
56
from .models import Post, Category
67

78
"""
@@ -25,6 +26,8 @@ def index(request):
2526
return render(request, 'blog/index.html', context={'post_list': post_list})
2627

2728

29+
"""
30+
增加了评论功能后需要相应地更新 detail 函数,更新后的函数见下边。
2831
def detail(request, pk):
2932
post = get_object_or_404(Post, pk=pk)
3033
post.body = markdown.markdown(post.body,
@@ -35,6 +38,25 @@ def detail(request, pk):
3538
])
3639
return render(request, 'blog/detail.html', context={'post': post})
3740
41+
"""
42+
43+
44+
def detail(request, pk):
45+
post = get_object_or_404(Post, pk=pk)
46+
post.body = markdown.markdown(post.body,
47+
extensions=[
48+
'markdown.extensions.extra',
49+
'markdown.extensions.codehilite',
50+
'markdown.extensions.toc',
51+
])
52+
form = CommentForm()
53+
comment_list = post.comment_set.all()
54+
context = {'post': post,
55+
'form': form,
56+
'comment_list': comment_list
57+
}
58+
return render(request, 'blog/detail.html', context=context)
59+
3860

3961
def archives(request, year, month):
4062
post_list = Post.objects.filter(created_time__year=year, created_time__month=month)

blogproject/settings.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
'django.contrib.messages',
3737
'django.contrib.staticfiles',
3838
'blog',
39+
'comments',
3940
]
4041

4142
MIDDLEWARE = [

blogproject/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@
1818

1919
urlpatterns = [
2020
url(r'^admin/', admin.site.urls),
21-
url(r'', include('blog.urls'))
21+
url(r'', include('blog.urls')),
22+
url(r'', include('comments.urls')),
2223
]

comments/__init__.py

Whitespace-only changes.

comments/admin.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.contrib import admin
2+
3+
# Register your models here.

comments/apps.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django.apps import AppConfig
2+
3+
4+
class CommentsConfig(AppConfig):
5+
name = 'comments'

comments/forms.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from django import forms
2+
3+
from .models import Comment
4+
5+
6+
class CommentForm(forms.ModelForm):
7+
class Meta:
8+
model = Comment
9+
fields = ['name', 'email', 'url', 'text']
10+
11+
widgets = {
12+
'name': forms.TextInput(attrs={
13+
'placeholder': "名字",
14+
}),
15+
'email': forms.TextInput(attrs={
16+
'placeholder': "邮箱",
17+
}),
18+
'url': forms.TextInput(attrs={
19+
'placeholder': "网址",
20+
}),
21+
}

comments/migrations/0001_initial.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.10.6 on 2017-04-08 11:38
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
import django.db.models.deletion
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
initial = True
12+
13+
dependencies = [
14+
('blog', '0001_initial'),
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='Comment',
20+
fields=[
21+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('name', models.CharField(max_length=100)),
23+
('email', models.EmailField(max_length=255)),
24+
('url', models.URLField(blank=True)),
25+
('text', models.TextField()),
26+
('created_time', models.DateTimeField(auto_now_add=True)),
27+
('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.Post')),
28+
],
29+
),
30+
]

comments/migrations/__init__.py

Whitespace-only changes.

comments/models.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from django.db import models
2+
from django.utils.six import python_2_unicode_compatible
3+
4+
5+
@python_2_unicode_compatible
6+
class Comment(models.Model):
7+
name = models.CharField(max_length=100)
8+
email = models.EmailField(max_length=255)
9+
url = models.URLField(blank=True)
10+
text = models.TextField()
11+
created_time = models.DateTimeField(auto_now_add=True)
12+
13+
post = models.ForeignKey('blog.Post')
14+
15+
def __str__(self):
16+
# python_2_unicode_compatible 装饰器用于兼容 Python2
17+
return self.text[:20]

comments/tests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

comments/urls.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from django.conf.urls import url
2+
3+
from . import views
4+
5+
app_name = 'comments'
6+
urlpatterns = [
7+
url(r'^comment/post/(?P<post_pk>[0-9]+)/$', views.post_comment, name='post_comment'),
8+
]

comments/views.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from django.shortcuts import render, get_object_or_404, redirect
2+
from blog.models import Post
3+
4+
from .forms import CommentForm
5+
6+
7+
def post_comment(request, post_pk):
8+
# 先获取被评论的文章,
9+
# 因为后面需要把评论和被评论的文章关联起来。
10+
# 这里我们使用了 django 提供的一个快捷函数 get_object_or_404
11+
# 这个函数的作用是当获取的文章(Post)存在时,则获取;
12+
# 否则返回 404 页面给用户。
13+
post = get_object_or_404(Post, pk=post_pk)
14+
15+
# http 请求有 get 和 post 两种方法,
16+
# 一般用户通过表单提交数据都是通过 post 请求,
17+
# 因此只有当用户的请求为 post 时才需要处理表单数据
18+
if request.method == 'POST':
19+
# 用户提交的数据存在 request.POST
20+
# 我们利用这些数据构造了 CommentForm 的实例,
21+
# 这样 django 的表单就生成了
22+
form = CommentForm(request.POST)
23+
24+
# 当调用 form.is_valid() 方法时,
25+
# django 自动帮我们检查表单的数据是否符合格式要求
26+
if form.is_valid():
27+
# 检查到数据是合法的,
28+
# 调用表单的 save 方法保存数据到数据库
29+
# commit=False 的作用是仅仅利用表单的数据生成 Comment 模型类的实例
30+
# 但还不保存数据到数据库
31+
comment = form.save(commit=False)
32+
# 将评论和被评论的文章关联起来
33+
comment.post = post
34+
# 最终将评论数据保存进数据库,
35+
# 调用模型实例的 save 方法
36+
comment.save()
37+
38+
# 重定向到 post 的详情页
39+
return redirect(post)
40+
41+
else:
42+
# 检查到数据不合法,
43+
# 重新渲染详情页,
44+
# 并且渲染表单的错误
45+
# 因此我们传了三个模板变量给 detail.html
46+
# 一个是文章(Post),
47+
# 一个是评论列表,
48+
# 一个是表单 form
49+
comment_list = post.comment_set.all()
50+
context = {'post': post,
51+
'form': form,
52+
'comment_list': comment_list
53+
}
54+
return render(request, 'blog/detail.html', context=context)
55+
56+
# 不是 post 请求,
57+
# 说明用户没有提交数据,
58+
# 重定向到文章详情页
59+
return redirect(post)

templates/blog/detail.html

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,48 @@ <h1 class="entry-title">{{ post.title }}</h1>
1919
{{ post.body|safe }}
2020
</div>
2121
</article>
22+
<section class="comment-area">
23+
<h2>留下你的评论</h2>
24+
<form action="{% url 'comments:post_comment' post.pk %}" method="post" class="comment-form">
25+
{% csrf_token %}
26+
<div class="row">
27+
<div class="col-md-4">
28+
<label for="{{ form.name.id_for_label }}">Name:</label>
29+
{{ form.name }}
30+
{{ form.name.errors }}
31+
</div>
32+
<div class="col-md-4">
33+
<label for="{{ form.email.id_for_label }}">Email:</label>
34+
{{ form.email }}
35+
{{ form.email.errors }}
36+
</div>
37+
<div class="col-md-4">
38+
<label for="{{ form.url.id_for_label }}">Url:</label>
39+
{{ form.url }}
40+
{{ form.url.errors }}
41+
</div>
42+
<div class="col-md-12">
43+
<label for="{{ form.text.id_for_label }}">Comment:</label>
44+
{{ form.text }}
45+
{{ form.text.errors }}
46+
<button type="submit"><span>发表</span></button>
47+
</div>
48+
</div> <!-- row -->
49+
</form>
50+
<div class="comment-list">
51+
<h2>评论列表</h2>
52+
<ul class="list-unstyled">
53+
{% for comment in comment_list %}
54+
<li class="comment-item">
55+
<span class="name">{{ comment.name }}</span><time class="date">{{ comment.created_time }}</time>
56+
<div class="text">
57+
{{ comment.text }}
58+
</div>
59+
</li>
60+
{% empty %}
61+
暂无评论
62+
{% endfor %}
63+
</ul>
64+
</div>
65+
</section>
2266
{% endblock main %}

0 commit comments

Comments
 (0)