title: 博客项目(Django版)项目
tags: Django
notebook: 7.0第五月 Python_web后端
[toc]
一、项目概述项目运行环境Python3.6+
Django 1.11
MySQL 5.7
其他插件(图片处理、分页、验证码....)
项目首页展示
轮播图
博客推荐
最新发布
博客分类
最新评论文章
widgets小插件
搜索功能
博客分类功能
博客标签查询
友情链接
博客分页功能
博客详细
最新评论文章
发表评论
评论展示
评论数
阅读数
登录功能
注册功能
邮箱验证功能
注销功能
页面模板
标签云功能
读者墙功能
用户维护
权限管理
博客分类维护
标签维护
友情链接
轮播图维护
项目演示
项目代码演示代码展示
二、开发环境搭建使用virtualenv 和 virtualenwrapper
MySQL 5.7
sudo apt install mysql-server mysql-client
安装mysql驱动
pip install pymysql
安装Django
pip install django==1.11三、创建项目创建项目和应用
创建项目
django-admin startproject django-blog
创建应用
python manage.py startapp userapppython manage.py startapp blogapp配置数据库
在settings中配置数据库
DATAbaseS = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_blog_db', 'USER': 'root', 'PASSWORD': 'wwy123', 'HOST': '127.0.0.1', 'PORT': '3306',
}
}创建数据库(执行迁移文件)python manage.py migrate创建超级管理员
python manage.py createsuperuser四、创建数据模型USERAPPUSER(用户模型)
from django.contrib.auth.models import AbstractUser
class BlogUser(AbstractUser):
nikename = models.CharField('昵称', max_length=20, default='')EMAIL(邮箱验证数据模型)提示:需要在settings配置文件中设置:AUTH_USER_MODEL = 'users.BlogUser'
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="发送时间", default=datetime.now)
class meta:
verbose_name = "邮箱验证码"
# 复数
verbose_name_plural = verbose_name
def __str__(self):
return '{0}({1})'.format(self.code, self.email)BLOGAPPBanner(轮播图模型)class Banner(models.Model):
title = models.CharField('标题', 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.nameTags(标签模型)class Tags(models.Model):
name = models.CharField('标签名称', max_length=20, default='')
class meta:
verbose_name = '标签'
verbose_name_plural = '标签'
def __str__(self):
return self.nameBlog(博客模型)class Post(models.Model):
user = models.ForeignKey(BlogUser, verbose_name='作者')
category = models.ForeignKey(BlogCategory, verbose_name='博客分类', default=None)
tags = models.ManyToManyField(Tags, verbose_name='标签')
title = models.CharField('标题', max_length=50)
content = models.TextField('内容')
pub_date = models.DateTimeField('发布日期', default=datetime.now)
cover = models.ImageField('博客封面', upload_to='static/images/post', default=None)
views = models.IntegerField('浏览数', 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('发布时间')
content = models.TextField('内容')
def __str__(self):
return self.content
class meta:
verbose_name = '评论'
verbose_name_plural = '评论'Friendlylink(友情链接模型)class Friendlylink(models.Model):
title = models.CharField('标题', max_length=50)
link = models.URLField('链接', max_length=50, default='')
def __str__(self):
return self.title
class meta:
verbose_name = '友情链接'
verbose_name_plural = '友情链接'五、实现首页页面模板创建模板文件夹创建模板文件templates,并在settings.py中设置
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',
],
},
},
]配置静态文件路径STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(base_DIR, "static"), )六、创建首页路由
创建视图函数
def index(request):
return render(request, 'index.html', {})配置url
url(r'^$', index, name='index' )
修改模板CSS JS等静态文件的路径
注册模型
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)模板
八、实现博客推荐{% for banner in banner_list %} {% if banner.is_active %} {% else %} {% endif %} {% endfor %}
{% for banner in banner_list %} {% if banner.is_active %} {% else %} {% endif %} {% endfor %} 上一个 下一个
注册模型
from blogs.models import Banner,Post,BlogCategory,Tags ... admin.site.register(BlogCategory) admin.site.register(Tags) admin.site.register(Post)
编写views
# 视图函数 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 %}
【推荐】{{post.title}}
{{post.content}}
{% endfor %} 九、实现最新发布编写views
# 视图函数 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%}
{{post.category.name}}
{{post.title}}
{{post.views}} {{post.comment_set.count}}
{% autoescape off %}
{{post.content | truncatechars_html:200}}
{% endautoescape %}
{% endfor %}
十、实现博客分类功能编写视图
# 视图函数 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)模型
最新发布
{%for c in blogcategory_list%} {{c.name}}
{% endfor %}
十一、实现最新评论功能编写views
-
{% for post in new_comment_list %}
- {{ post.title }} {{ post.pub_date }} {{ post.views }} {% endfor %}
编写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'),十三、实现友情链接
编写视图 (数据源)
def index(request): .... friendlylink_list = Friendlylink.objects.all() .....
模板
友情链接
{% for friendlylink in friendlylink_list %}
{{ friendlylink.title }} {% endfor %}
十四、实现博客列表功能编写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
十五、实现分页功能{% block title %}知奇博客首页 {% endblock %} {% block custom_css %}{% endblock %}{% block content %} {% endblock %}
安装包
pip install 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)模板
博客列表 {% for post in post_list.object_list %}
{{post.category.name}} {{post.title}} {{post.views}} {{post.comment_set.count}}
{{post.content}}
{% endfor %} {% include "_pagination.html" %}
_pagination.html
{% load i18n %}
{% if post_list.has_previous %}
‹‹ 上一页
{% else %}
‹‹ 上一页
{% endif %}
{% for page in post_list.pages %}
{% if page %}
{% ifequal page post_list.number %}
{{ page }}
{% else %}
{{ page }}
{% endifequal %}
{% else %}
... {% endif %}
{% endfor %}
{% if post_list.has_next %}
下一页 ››
{% else %}
下一页 ››
{% endif %}十六、实现标签云功能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)模板
标签云
-
{% for t in tags %}
- {{t.name}} {{t.count}} {% endfor %}
编写视图
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[0-9]+)/$', blog_list),
模板 index
最新发布
{%for c in blogcategory_list%} {{c.name}}
{% endfor %}
十八、实现按标签查询功能编写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)路由设置
url(r'^tags/(?P[0-9]+)/$', blog_list),
模板
标签云
-
{% for t in tags %}
- {{t.name}} {{t.count}} {% endfor %}
定义视图函数
def blog_detail(request,bid):
post = Post.objects.get(id=bid)
post.views = post.views + 1
post.save()
# 博客标签
tag_list = post.tags.all()
ctx = { 'post': post,
} return render(request, 'show.html', ctx)路由设置
url(r'^blog/(?P[0-9]+)/$', blog_detail, name='blog_detail'),
前端展示
{% extends 'base.html' %}
{% block title %}知奇博客-详细 {% endblock %}
{% block content %}
{{post.title}}
{{post.user.username}}
{{post.category.name}}
{{post.views}}
{{post.content}}
标签:
{% for tag in post.tags.all %} {{tag.name}}
{% endfor %}
{% endblock %} 二十、实现相关推荐功能编写视图
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)
# 相关推荐
# 首先 我们需要取到 这篇文章的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 %}
作者:翁闻宇
链接:https://www.jianshu.com/p/e1b50d3067a3



