一舌胶、項目概述
項目運行環(huán)境
Python3.6+
Django 1.11
MySQL 5.7
其他插件(圖片處理婴梧、分頁炮沐、驗證碼....)
項目詳細(xì)功能介紹
前臺功能
項目首頁展示
輪播圖
博客推薦
最新發(fā)布
博客分類
最新評論文章
widgets小插件
搜索功能
博客分類功能
博客標(biāo)簽查詢
友情鏈接
博客分頁功能
博客詳細(xì)
最新評論文章
發(fā)表評論
評論展示
評論數(shù)
閱讀數(shù)
登錄功能
注冊功能
郵箱驗證功能
注銷功能
頁面模板
標(biāo)簽云功能
讀者墻功能
后臺功能
用戶維護(hù)
權(quán)限管理
博客分類維護(hù)
標(biāo)簽維護(hù)
友情鏈接
輪播圖維護(hù)
項目演示
項目演示
# 二伊诵、開發(fā)環(huán)境搭建
> 使用virtualenv 和 virtualenwrapper
**1\. MySQL 5.7**
sudo apt install mysql-server mysql-client
**2\. 安裝mysql驅(qū)動**
pip install pymysql
**3\. 安裝Django**
pip install django==1.11
# 三滥嘴、創(chuàng)建項目
## 創(chuàng)建項目和應(yīng)用
* 創(chuàng)建項目
django-admin startproject django-blog
* 創(chuàng)建應(yīng)用
python manage.py startapp userapp
python manage.py startapp blogapp
## 配置數(shù)據(jù)庫
* 在settings中配置數(shù)據(jù)庫
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_blog_db',
'USER': 'root',
'PASSWORD': 'wwy123',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
## 創(chuàng)建數(shù)據(jù)庫(執(zhí)行遷移文件)
python manage.py migrate
## 創(chuàng)建超級管理員
python manage.py createsuperuser
# 四、創(chuàng)建數(shù)據(jù)模型
## USERAPP
### USER(用戶模型)
from django.contrib.auth.models import AbstractUser
class BlogUser(AbstractUser):`
nikename = models.CharField('昵稱', max_length=20, default='')
> 提示:需要在settings配置文件中設(shè)置:AUTH_USER_MODEL = 'users.BlogUser'
### EMAIL(郵箱驗證數(shù)據(jù)模型)
class EmailVerifyRecord(models.Model):`
code = models.CharField(verbose_name='驗證碼', max_length=50,default='')
email = models.EmailField(max_length=50, verbose_name="郵箱")
send_type = models.CharField(verbose_name="驗證碼類型", choices=(("register",u"注冊"),("forget","找回密碼"), ("update_email","修改郵箱")), max_length=30)
send_time = models.DateTimeField(verbose_name="發(fā)送時間", default=datetime.now)
class Meta:
verbose_name = "郵箱驗證碼"
# 復(fù)數(shù)
verbose_name_plural = verbose_name
def str(self):
return '{0}({1})'.format(self.code, self.email)
## BLOGAPP
### Banner(輪播圖模型)
class Banner(models.Model):`
title = models.CharField('標(biāo)題', max_length=50)
cover = models.ImageField('輪播圖', upload_to='static/images/banner')
link_url = models.URLField('圖片鏈接', max_length=100)
idx = models.IntegerField('索引')
is_active = models.BooleanField('是否是active', default=False)
def str(self):
return self.title
class Meta:
verbose_name = '輪播圖'
verbose_name_plural = '輪播圖'
### Category(博客分類模型)
class BlogCategory(models.Model):`
name = models.CharField('分類名稱', max_length=20, default='')
class Meta:
verbose_name = '博客分類'
verbose_name_plural = '博客分類'
def str(self):
return self.name
### Tags(標(biāo)簽?zāi)P?
class Tags(models.Model):`
name = models.CharField('標(biāo)簽名稱', max_length=20, default='')
class Meta:
verbose_name = '標(biāo)簽'
verbose_name_plural = '標(biāo)簽'
def str(self):
return self.name
### Blog(博客模型)
class Post(models.Model):`
user = models.ForeignKey(BlogUser, verbose_name='作者')
category = models.ForeignKey(BlogCategory, verbose_name='博客分類', default=None)
tags = models.ManyToManyField(Tags, verbose_name='標(biāo)簽')
title = models.CharField('標(biāo)題', max_length=50)
content = models.TextField('內(nèi)容')
pub_date = models.DateTimeField('發(fā)布日期', default=datetime.now)
cover = models.ImageField('博客封面', upload_to='static/images/post', default=None)
views = models.IntegerField('瀏覽數(shù)', default=0)
recommend = models.BooleanField('推薦博客', default=False)
def str(self):
return self.title
class Meta:
verbose_name = '博客'
verbose_name_plural = '博客'
### Comment(評論模型)
class Comment(models.Model):`
post = models.ForeignKey(Post, verbose_name='博客')
user = models.ForeignKey(BlogUser, verbose_name='作者')
pub_date = models.DateTimeField('發(fā)布時間')
content = models.TextField('內(nèi)容')
def str(self):
return self.content
class Meta:
verbose_name = '評論'
verbose_name_plural = '評論'
### FriendlyLink(友情鏈接模型)
class FriendlyLink(models.Model):`
title = models.CharField('標(biāo)題', max_length=50)
link = models.URLField('鏈接', max_length=50, default='')
def str(self):
return self.title
class Meta:
verbose_name = '友情鏈接'
verbose_name_plural = '友情鏈接'
# 五换团、實現(xiàn)首頁頁面模板
## 創(chuàng)建模板文件夾
> 創(chuàng)建模板文件templates,并在settings.py中設(shè)置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'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',
],
},
},
]
## 配置靜態(tài)文件路徑
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
# 六把还、創(chuàng)建首頁路由
* 創(chuàng)建視圖函數(shù)
def index(request):`
return render(request, 'index.html', {})
* 配置url
url(r'^$', index, name='index' )
* 修改模板CSS JS等靜態(tài)文件的路徑
# 七、實現(xiàn)幻燈片功能(Banner)
* 注冊模型
from blogs.models import Banner
admin.site.register(Banner)
* 編寫views
from .models import Banner
def index(request):
banner_list = Banner.objects.all()
ctx = {
'banner_list': banner_list,
}
return render(request, 'index.html', ctx)
* 模板
<div id="focusslide" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
{% for banner in banner_list %}
{% if banner.is_active %}
<li data-target="#focusslide" data-slide-to="{{banner.idx}}" class="active"></li>
{% else %}
<li data-target="#focusslide" data-slide-to="{{banner.idx}}"></li>
{% endif %}
{% endfor %}
</ol>
<div class="carousel-inner" role="listbox">
{% for banner in banner_list %}
{% if banner.is_active %}
<div class="item active">
<a href="{{banner.link_url}}" target="_blank" title="{{banner.title}}" >
<img src="{{banner.cover}}" alt="{{banner.title}}" class="img-responsive"></a>
</div>
{% else %}
<div class="item">
<a href="{{banner.link_url}}" target="_blank" title="{{banner.title}}" >
<img src="{{banner.cover}}" alt="{{banner.title}}" class="img-responsive"></a>
</div>
{% endif %}
{% endfor %}
</div>
<a class="left carousel-control" href="#focusslide" role="button" data-slide="prev" rel="nofollow">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">上一個</span> </a>
<a class="right carousel-control" href="#focusslide" role="button" data-slide="next" rel="nofollow">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">下一個</span> </a>
</div>
``
# 八俏脊、實現(xiàn)博客推薦
* 注冊模型
from blogs.models import Banner,Post,BlogCategory,Tags
...
admin.site.register(BlogCategory)
admin.site.register(Tags)
admin.site.register(Post)
* 編寫views
`# 視圖函數(shù) HTTPRequest`
def index(request):
banner_list = Banner.objects.all()
recommend_list = Post.objects.filter(recommend=1)
ctx = {
'banner_list': banner_list,
'recommend_list': recommend_list,
}
return render(request, 'index.html', ctx)
* 模板
{% for post in recommend_list %}
<article class="excerpt-minic excerpt-minic-index">
<h2><span class="red">【推薦】</span><a target="_blank" href="/blog/{{post.id}}/" title="{{post.title}}" >{{post.title}}</a>
</h2>
<p class="note">{{post.content}}</p>
</article>
{% endfor %}
# 九全谤、實現(xiàn)最新發(fā)布
* 編寫views
`# 視圖函數(shù) HTTPRequest`
def index(request):
...
post_list = Post.objects.order_by('-pub_date').all()[:10]
....
ctx = {
'banner_list': banner_list,
'recommend_list': recommend_list,
'post_list': post_list,
}
return render(request, 'index.html', ctx)
* 模板
{% for post in post_list%}
<article class="excerpt excerpt-1" style="">
<a class="focus" href="/blog/{{post.id}}/" title="{{post.title}}" target="_blank" ><img class="thumb" data-original="/{{post.cover}}" src="/{{post.cover}}" alt="{{post.title}}" style="display: inline;"></a>
<header><a class="cat" href="#" title="{{post.category.name}}" >{{post.category.name}}<i></i></a>
<h2><a href="/blog/{{post.id}}/" title="{{post.title}}" target="_blank" >{{post.title}}</a>
</h2>
</header>
<p class="meta">
<time class="time"><i class="glyphicon glyphicon-time"></i>{{post.pub_date|date:'Y-m-d'}}</time>
<span class="views"><i class="glyphicon glyphicon-eye-open"></i>{{post.views}}</span> <a class="comment" href="##comment" title="評論" target="_blank" ><i class="glyphicon glyphicon-comment"></i>{{post.comment_set.count}}</a>
</p>
<p class="note">
{% autoescape off %}
{{post.content | truncatechars_html:200}}
{% endautoescape %}
</p>
</article>
{% endfor %}
# 十、實現(xiàn)博客分類功能
* 編寫視圖
`# 視圖函數(shù) HTTPRequest`
def index(request):
banner_list = Banner.objects.all()
recommend_list = Post.objects.filter(recommend=1)
post_list = Post.objects.order_by('-pub_date').all()[:10]
blogcategory_list = BlogCategory.objects.all()
ctx = {
'banner_list': banner_list,
'recommend_list': recommend_list,
'post_list': post_list,
'blogcategory_list': blogcategory_list,
}
return render(request, 'index.html', ctx)
* 模型
<div class="title">
<h3>最新發(fā)布</h3>
<div class="more">
{%for c in blogcategory_list%}
<a href="/category/{{c.id}}" title="{{c.name}}" >{{c.name}}</a>
{% endfor %}
</div>
</div>
# 十一爷贫、實現(xiàn)最新評論功能
* 編寫views
<ul>
{% for post in new_comment_list %}
<li><a title="{{ post.title }}" href="#"><span class="thumbnail">
<img class="thumb" data-original="/{{ post.cover }}"
src="/{{ post.cover }}"
alt="{{ post.title }}" style="display: block;">
</span><span class="text">{{ post.title }}</span><span class="muted"><i
class="glyphicon glyphicon-time"></i>
{{ post.pub_date }}
</span><span class="muted"><i class="glyphicon glyphicon-eye-open"></i>{{ post.views }}</span></a></li>
{% endfor %}
</ul>
# 十二认然、實現(xiàn)搜索功能
* 編寫views
from django.views.generic.base import View
from django.db.models import Q
class SearchView(View):
def get(self, request):
pass
def post(self, request):
kw = request.POST.get('keyword')
post_list = Post.objects.filter(Q(title__icontains=kw)|Q(content__icontains=kw))
ctx = {
'post_list': post_list
}
return render(request, 'list.html', ctx)
- urls
url(r'^search$', SearchView.as_view(), name='search'),
# 十三、實現(xiàn)友情鏈接
* 編寫視圖 (數(shù)據(jù)源)
def index(request):
....
friendlylink_list = FriendlyLink.objects.all()
.....
* 模板
<div class="widget widget_sentence">
<h3>友情鏈接</h3>
<div class="widget-sentence-link">
{% for friendlylink in friendlylink_list %}
<a href="{{ friendlylink.link }}" title="{{ friendlylink.title }}"
target="_blank">{{ friendlylink.title }}</a>
{% endfor %}
</div>
</div>
# 十四漫萄、實現(xiàn)博客列表功能
* 編寫views
def blog_list(request):
post_list = POST.objects.all()
ctx = {
'post_list': post_list,
}
return render(request, 'list.html', ctx)
* 編寫路由
url(r'^list$', blog_list, name='blog_list'),
- base.html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}知奇博客首頁 {% endblock %}</title>
<meta name="keywords" content="">
<meta name="description" content="">
{% block custom_css %}{% endblock %}
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="/static/css/nprogress.css">
<link rel="stylesheet" type="text/css" href="/static/css/style.css">
<link rel="stylesheet" type="text/css" href="/static/css/font-awesome.min.css">
<link rel="apple-touch-icon-precomposed" href="/static/images/icon.png">
<link rel="shortcut icon" href="/static/images/favicon.ico">
<script src="/static/js/jquery-2.1.4.min.js"></script>
<script src="/static/js/nprogress.js"></script>
<script src="/static/js/jquery.lazyload.min.js"></script>
</head>
<body class="user-select">
<header class="header">
<nav class="navbar navbar-default" id="navbar">
<div class="container">
<div class="header-topbar hidden-xs link-border">
<ul class="site-nav topmenu">
<li><a href="#" >標(biāo)簽云</a></li>
<li><a href="#" rel="nofollow" >讀者墻</a></li>
<li><a href="#" title="RSS訂閱" >
<i class="fa fa-rss">
</i> RSS訂閱
</a></li>
</ul>
愛學(xué)習(xí) 更愛分享
</div>
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#header-navbar" aria-expanded="false"> <span class="sr-only"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button>
<h1 class="logo hvr-bounce-in"><a href="#" title="知奇課堂博客"><img src="/static/images/201610171329086541.png" alt="知奇課堂博客"></a></h1>
</div>
<div class="collapse navbar-collapse" id="header-navbar">
<ul class="nav navbar-nav navbar-left">
<li><a data-cont="知奇課堂博客" title="知奇課堂博客" href="/">首頁</a></li>
<li><a data-cont="博客" title="博客" href="/list">博客</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %}
<li><a data-cont="用戶" title="用戶" href="#">歡迎卷员,{{user.username}}</a></li>
<li><a data-cont="注冊" title="注冊" href="/logout">注銷</a></li>
{% else %}
<li><a data-cont="登錄" title="登錄" href="/login">登錄</a></li>
<li><a data-cont="注冊" title="注冊" href="/register">注冊</a></li>
{% endif %}
</ul>
</div>
</div>
</nav>
</header>
{% block content %}
{% endblock %}
<footer class="footer">
<div class="container">
<p>Copyright ? 2016.Company name All rights reserved.</p>
</div>
<div id="gotop"><a class="gotop"></a></div>
</footer>
<script src="/static/js/bootstrap.min.js"></script>
``
<script src="/static/js/scripts.js"></script>
</body>
</html>
# 十五、實現(xiàn)分頁功能
* 安裝包
pip install django-pure-pagination
> 參考鏈接: [https://github.com/jamespacileo/django-pure-pagination](https://github.com/jamespacileo/django-pure-pagination)
def blog_list(request):
post_list = Post.objects.all()
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
p = Paginator(post_list, per_page=1, request=request)
post_list = p.page(page)
ctx = {
'post_list': post_list,
}
return render(request, 'list.html', ctx)
* 模板
<section class="container">
<div class="content-wrap">
<div class="content">
<div class="title">
<h3 style="line-height: 1.3">博客列表</h3>
</div>
{% for post in post_list.object_list %}
<article class="excerpt excerpt-1"><a class="focus" href="/blog/{{post.id}}" title="{{post.title}}" target="_blank" >
<img class="thumb" data-original="/{{post.cover}}" src="/{{post.cover}}" alt="{{post.title}}" style="display: inline;"></a>
<header><a class="cat" href="/category/{{post.category.id}}" title="{{post.category.name}}" >{{post.category.name}}<i></i></a>
<h2><a href="/blog/{{post.id}}" title="{{post.title}}" target="_blank" >{{post.title}}</a></h2>
</header>
<p class="meta">
<time class="time"><i class="glyphicon glyphicon-time"></i> {{post.pub_date|date:'Y-m-d'}}</time>
<span class="views"><i class="glyphicon glyphicon-eye-open"></i> {{post.views}}</span>
<a class="comment" href="##comment" title="評論" target="_blank" ><i class="glyphicon glyphicon-comment"></i>{{post.comment_set.count}}</a></p>
<p class="note">{{post.content}}</p>
</article>
{% endfor %}
{% include "_pagination.html" %}
- _pagination.html
{% load i18n %}
<div class="pagination">
{% if post_list.has_previous %}
<a href="?{{ post_list.previous_page_number.querystring }}" class="prev">‹‹ 上一頁</a>
{% else %}
<span class="disabled prev">‹‹ 上一頁</span>
{% endif %}
{% for page in post_list.pages %}
{% if page %}
{% ifequal page post_list.number %}
<span class="current page">{{ page }}</span>
{% else %}
<a href="?{{ page.querystring }}" class="page">{{ page }}</a>
{% endifequal %}
{% else %}
...
{% endif %}
{% endfor %}
{% if post_list.has_next %}
<a href="?{{ post_list.next_page_number.querystring }}" class="next">下一頁 ››</a>
{% else %}
<span class="disabled next">下一頁 ››</span>
{% endif %}
</div>
# 十六腾务、實現(xiàn)標(biāo)簽云功能
class TagMessage(object):
def init(self, tid, name, count):
self.tid = tid
self.name = name
self.count = count
def blog_list(request):
post_list = Post.objects.all()
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
p = Paginator(post_list, per_page=1, request=request)
post_list = p.page(page)
tags = Tags.objects.all()
tag_message_list = []
for t in tags:
count = len(t.post_set.all())
tm = TagMessage(t.id, t.name, count)
tag_message_list.append(tm)
ctx = {
'post_list': post_list,
'tags': tag_message_list
}
return render(request, 'list.html', ctx)
* 模板
<h3>標(biāo)簽云</h3>
<div class="widget-sentence-content">
<ul class="plinks ptags">
{% for t in tags %}
<li><a href="/tags/{{t.tid}}" title="{{t.name}}" draggable="false">{{t.name}} <span class="badge">{{t.count}}</span></a></li>
{% endfor %}
</ul>
</div>
</div>
# 十七毕骡、實現(xiàn)分類查詢功能
* 編寫視圖
def blog_list(request, cid=-1):
post_list = None
if cid != -1:
cat = BlogCategory.objects.get(id=cid)
post_list = cat.post_set.all()
else:
post_list = Post.objects.all()
....
ctx = {
'post_list': post_list,
'tags': tag_message_list
}
return render(request, 'list.html', ctx)
* 編寫路由
url(r'^category/(?P<cid>[0-9]+)/$', blog_list),
* 模板 index
<div class="title">
<h3>最新發(fā)布</h3>
<div class="more">
{%for c in blogcategory_list%}
<a href="/category/{{c.id}}" title="{{c.name}}" >{{c.name}}</a>
{% endfor %}
</div>
</div>
# 十八、實現(xiàn)按標(biāo)簽查詢功能
* 編寫views
def blog_list(request, cid=-1, tid=-1):
post_list = None
if cid != -1:
cat = BlogCategory.objects.get(id=cid)
post_list = cat.post_set.all()
elif tid != -1:
tag = Tags.objects.get(id=tid)
post_list = tag.post_set.all()
else:
post_list = Post.objects.all()
....
ctx = {
'post_list': post_list,
'tags': tag_message_list
}
return render(request, 'list.html', ctx)
* 路由設(shè)置
url(r'^tags/(?P<tid>[0-9]+)/$', blog_list),
* 模板
<h3>標(biāo)簽云</h3>
<div class="widget-sentence-content">
<ul class="plinks ptags">
{% for t in tags %}
<li><a href="/tags/{{t.tid}}" title="{{t.name}}" draggable="false">{{t.name}} <span class="badge">{{t.count}}</span></a></li>
{% endfor %}
</ul>
</div>
</div>
</div>
# 十九、實現(xiàn)博客詳情功能
* 定義視圖函數(shù)
def blog_detail(request,bid):
post = Post.objects.get(id=bid)
post.views = post.views + 1
post.save()
# 博客標(biāo)簽
tag_list = post.tags.all()
ctx = {
'post': post,
}
return render(request, 'show.html', ctx)
* 路由設(shè)置
url(r'^blog/(?P<bid>[0-9]+)/$', blog_detail, name='blog_detail'),
* 前端展示
{% extends 'base.html' %}
{% block title %}知奇博客-詳細(xì) {% endblock %}
{% block content %}
<section class="container">
<div class="content-wrap">
<div class="content">
<header class="article-header">
<h1 class="article-title"><a href="#" title="{{post.title}}" >{{post.title}}</a></h1>
<div class="article-meta"> <span class="item article-meta-time">
<time class="time" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="發(fā)表時間:{{post.pub_date|date:'Y-m-d'}}">
<i class="glyphicon glyphicon-time"></i> {{post.pub_date|date:'Y-m-d'}}</time>
</span>
<span class="item article-meta-source" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="來源:{{post.user.username}}">
<i class="glyphicon glyphicon-globe"></i> {{post.user.username}}</span>
<span class="item article-meta-category" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="{{post.category.name}}">
<i class="glyphicon glyphicon-list"></i> <a href="#" title="{{post.category.name}}" >{{post.category.name}}</a></span>
<span class="item article-meta-views" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="瀏覽量:{{post.views}}">
<i class="glyphicon glyphicon-eye-open"></i> {{post.views}}</span>
<span class="item article-meta-comment" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="評論量">
<i class="glyphicon glyphicon-comment"></i> </span> </div>
</header>
<article class="article-content">
<p>{{post.content}}</p>
</article>
<div class="article-tags">標(biāo)簽:
{% for tag in post.tags.all %}
<a href="/tags/{{tag.id}}">{{tag.name}}</a>
{% endfor %}
</div>
{% endblock %}
# 二十未巫、實現(xiàn)相關(guān)推薦功能
* 編寫視圖
def blog_detail(request, pid):
post = Post.objects.get(id=pid)
post.views = post.views + 1
post.save()
comment_list = Comment.objects.order_by('-pub_date')
最新評論的博客 列表
new_comment_list = []
去重
for c in comment_list:
if c.post not in new_comment_list:
new_comment_list.append(c.post)
相關(guān)推薦
首先 我們需要取到 這篇文章的tag
tag_post_list = []
for tag in post.tags.all():
tag_post_list.extend(tag.post_set.all())
ctx = {
'post': post,
'new_comment_list': new_comment_list,
'tag_post_list': tag_post_list
}
return render(request, 'show.html', ctx)
* 模板
{% for tag_post in tag_post_list %}
<li><a href="{% url 'blog:detail' tag_post.id %}" title="">{{ tag_post.title }}</a></li>
{% endfor %}
# 二十一窿撬、實現(xiàn)發(fā)表評論的功能
-
show.html
<h3>評論</h3>
</div>
<div id="respond">
<form id="comment-form" name="comment-form" action="/comment/{{post.id}}" method="POST">
<div class="comment">
<input name="username" id="" value="{{user.username}}" class="form-control" size="22" placeholder="您的昵稱(必填)" maxlength="15" autocomplete="off" tabindex="1" type="text">
<!-- <input name="" id="" class="form-control" size="22" placeholder="您的網(wǎng)址或郵箱(非必填)" maxlength="58" autocomplete="off" tabindex="2" type="text"> -->
<div class="comment-box">
<textarea placeholder="您的評論或留言(必填)" name="content" id="comment-textarea" cols="100%" rows="3" tabindex="3"></textarea>
<div class="comment-ctrl">
<div class="comment-prompt" style="display: none;"> <i class="fa fa-spin fa-circle-o-notch"></i> <span class="comment-prompt-text">評論正在提交中...請稍后</span> </div>
<div class="comment-success" style="display: none;"> <i class="fa fa-check"></i> <span class="comment-prompt-text">評論提交成功...</span> </div>
<button type="submit" name="comment-submit" id="comment-submit" tabindex="4">評論</button>
</div>
</div>
</div>
{% csrf_token %}
</form>
* 編寫視圖類
class CommentView(View):
def get(self, request):
pass
def post(self, request, bid):
comment = Comment()
comment.user = request.user
comment.post = Post.objects.get(id=bid)
comment.content = request.POST.get('content')
comment.pub_date = datetime.now()
comment.save()
Ajax
return HttpResponseRedirect(reverse("blog_detail", kwargs={"bid":bid}))
* 編寫路由
url(r'^comment/(?P<bid>[0-9]+)$', CommentView.as_view(), name='comment'),
# 二十二、實現(xiàn)評論列表功能
* 編寫視圖
def blog_detail(request,bid):
post = Post.objects.get(id=bid)
post.views = post.views + 1
post.save()
最新評論博客
new_comment_list = Comment.objects.order_by('-pub_date').all()[:10]
comment_list = post.comment_set.all()
去重
new_comment_list1 = []
post_list1 = []
for c in new_comment_list:
if c.post.id not in post_list1:
new_comment_list1.append(c)
post_list1.append(c.post.id)
博客標(biāo)簽
tag_list = post.tags.all()
相關(guān)推薦(標(biāo)簽相同的)
post_recomment_list = set(Post.objects.filter(tags__in=tag_list)[:6])
ctx = {
'post': post,
'new_comment_list': new_comment_list1,
'post_recomment_list': post_recomment_list,
'comment_list': comment_list
}
return render(request, 'show.html', ctx)
{% for comment in comment_list %}
<li class="comment-content"><span class="comment-f">#{{forloop.counter}}</span><div class="comment-main"><p><a class="address" href="#" rel="nofollow" target="_blank">{{comment.user.username}}</a><span class="time">({{comment.pub_date|date:'Y-m-d'}})</span><br>{{comment.content}}</p></div></li>
{% endfor %}
# 二十三叙凡、實現(xiàn)登錄功能
# 二十四劈伴、實現(xiàn)注冊功能
# 二十五、實現(xiàn)注冊驗證功能
# 二十六握爷、實現(xiàn)注銷功能
# 二十七跛璧、實現(xiàn)后臺富文本功能