一、项目概述
项目运行环境
-
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
四、创建数据模型
USERAPP
USER(用户模型)
from django.contrib.auth.models import AbstractUser class BlogUser(AbstractUser): nikename = models.CharField('昵称', max_length=20, default='')
提示:需要在settings配置文件中设置:AUTH_USER_MODEL = 'users.BlogUser'
EMAIL(邮箱验证数据模型)
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)
BLOGAPP
Banner(轮播图模型)
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.name
Tags(标签模型)
class Tags(models.Model): name = models.CharField('标签名称', max_length=20, default='') class Meta: verbose_name = '标签' verbose_name_plural = '标签' 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='标签') 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等静态文件的路径
七、实现幻灯片功能(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)
-
模板
八、实现博客推荐
-
注册模型
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 %}{% endfor %} 【推荐】{{post.title}}
{{post.content}}
九、实现最新发布
-
编写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%}{% endfor %} {{post.category.name}} {{post.title}}
{{post.views}} {{post.comment_set.count}}
{% autoescape off %} {{post.content | truncatechars_html:200}} {% endautoescape %}
十、实现博客分类功能
-
编写视图
# 视图函数 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 %}博客列表
{% endfor %} {% include "_pagination.html" %} {{post.category.name}} {{post.title}}
{{post.views}} {{post.comment_set.count}}
{{post.content}}
_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 %}