2018-01-31

---title: 博客项目(Django版)项目tags: Djangonotebook: 7.0第五月 Python_web后端---[toc]# 一、项目概述## 项目运行环境1. Python3.6+2. Django 1.113. MySQL 5.74. 其他插件(图片处理、分页、验证码....)## 项目详细功能介绍### 前台功能1. 项目首页展示2. 轮播图3. 博客推荐4. 最新发布5. 博客分类6. 最新评论文章7. widgets小插件8. 搜索功能9. 博客分类功能10. 博客标签查询11. 友情链接12. 博客分页功能13. 博客详细14. 最新评论文章15. 发表评论16. 评论展示17. 评论数18. 阅读数19. 登录功能20. 注册功能21. 邮箱验证功能22. 注销功能23. 页面模板24. 标签云功能25. 读者墙功能### 后台功能1. 用户维护2. 权限管理3. 博客分类维护4. 标签维护5. 友情链接6. 轮播图维护### 项目演示项目演示### 项目代码演示代码展示# 二、开发环境搭建> 使用virtualenv 和 virtualenwrapper1. MySQL 5.7```vimsudo apt install mysql-server mysql-client```2. 安装mysql驱动```vimpip install pymysql```3. 安装Django```vimpip install django==1.11```# 三、创建项目## 创建项目和应用- 创建项目```vimdjango-admin startproject django-blog```- 创建应用```vimpython manage.py startapp userapppython manage.py startapp blogapp```## 配置数据库- 在settings中配置数据库```pythonDATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_blog_db', 'USER': 'root', 'PASSWORD': 'wwy123', 'HOST': '127.0.0.1', 'PORT': '3306', }}```## 创建数据库(执行迁移文件)```pythonpython manage.py migrate```## 创建超级管理员```pythonpython manage.py createsuperuser```# 四、创建数据模型## USERAPP### USER(用户模型)```djangofrom django.contrib.auth.models import AbstractUserclass BlogUser(AbstractUser): nikename = models.CharField('昵称', max_length=20, default='')```> 提示:需要在settings配置文件中设置:AUTH_USER_MODEL = 'users.BlogUser'### EMAIL(邮箱验证数据模型)```djangoclass 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(轮播图模型)```djangoclass 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(博客分类模型)```djangoclass BlogCategory(models.Model): name = models.CharField('分类名称', max_length=20, default='') class Meta: verbose_name = '博客分类' verbose_name_plural = '博客分类' def __str__(self): return self.name```### Tags(标签模型)```djangoclass Tags(models.Model): name = models.CharField('标签名称', max_length=20, default='') class Meta: verbose_name = '标签' verbose_name_plural = '标签' def __str__(self): return self.name```### Blog(博客模型)```djangoclass 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(评论模型)```djangoclass 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(友情链接模型)```djangoclass 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中设置```djangoTEMPLATES = [ { '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', ], }, },]```## 配置静态文件路径```djangoSTATIC_URL = '/static/'STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"),)```# 六、创建首页路由- 创建视图函数```djangodef index(request): return render(request, 'index.html', {})```- 配置url```djangourl(r'^$', index, name='index' )```- 修改模板CSS JS等静态文件的路径# 七、实现幻灯片功能(Banner)- 注册模型```djangofrom blogs.models import Banneradmin.site.register(Banner)```- 编写views```djangofrom .models import Bannerdef index(request): banner_list = Banner.objects.all() ctx = { 'banner_list': banner_list, } return render(request, 'index.html', ctx)```- 模板```django

{% for banner in banner_list %}    {% if banner.is_active %}

{% else %}

{% endif %}    {% endfor %}

{% for banner in banner_list %}    {% if banner.is_active %}

{% else %}

{% endif %}    {% endfor %}

上一个下一个

```# 八、实现博客推荐- 注册模型```djangofrom blogs.models import Banner,Post,BlogCategory,Tags...admin.site.register(BlogCategory)admin.site.register(Tags)admin.site.register(Post)```- 编写views```django# 视图函数 HTTPRequestdef 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)```- 模板```html    {% for post in recommend_list %}

【推荐】{{post.title}}

{{post.content}}

{% endfor %}  ```# 九、实现最新发布- 编写views```django# 视图函数 HTTPRequestdef 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)```- 模板```django    {% for post in post_list%}

{{post.category.name}}

{{post.title}}

{{post.pub_date|date:'Y-m-d'}}{{post.views}}{{post.comment_set.count}}

      {% autoescape off %}

          {{post.content | truncatechars_html:200}}

      {% endautoescape %}


{% endfor %}  ```# 十、实现博客分类功能- 编写视图```django# 视图函数 HTTPRequestdef 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)```- 模型```html

最新发布

{%for c in blogcategory_list%}{{c.name}}{% endfor %}

```# 十一、实现最新评论功能- 编写views```django

{% for post in new_comment_list %}

{{ post.title }} {{ post.pub_date }}

{{ post.views }}

{% endfor %}

```# 十二、实现搜索功能- 编写views```djangofrom django.views.generic.base import Viewfrom django.db.models import Qclass 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```djangourl(r'^search$', SearchView.as_view(), name='search'),```# 十三、实现友情链接- 编写视图  (数据源)```djangodef index(request):    ....    friendlylink_list = FriendlyLink.objects.all()    .....```- 模板```django

友情链接

{% for friendlylink in friendlylink_list %}{{ friendlylink.title }}{% endfor %}

```# 十四、实现博客列表功能- 编写views```djangodef blog_list(request):    post_list = POST.objects.all()    ctx = {        'post_list': post_list,    }    return render(request, 'list.html', ctx)```- 编写路由```djangourl(r'^list$', blog_list, name='blog_list'),```- base.html```html

标签云

读者墙

  RSS订阅

爱学习 更爱分享

首页

博客

{% if user.is_authenticated %}

欢迎,{{user.username}}

注销

{% else %}

登录

注册

{% endif %}

{% block content %}{% endblock %}

Copyright © 2016.Company name All rights reserved.

```# 十五、实现分页功能- 安装包```djangopip install django-pure-pagination```> 参考链接: https://github.com/jamespacileo/django-pure-pagination```djangodef 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)```- 模板```django

博客列表

{% for post in post_list.object_list %}

{{post.category.name}}

{{post.title}}

{{post.pub_date|date:'Y-m-d'}} {{post.views}}{{post.comment_set.count}}

{{post.content}}

{% endfor %}  {% include "_pagination.html" %}```- _pagination.html```django{% 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 %}

```# 十六、实现标签云功能```djangodef 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)```- 模板```html

标签云

{% for t in tags %}

{{t.name}}{{t.count}}

{% endfor %}

```# 十七、实现分类查询功能- 编写视图```djangodef 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)```- 编写路由```djangourl(r'^category/(?P[0-9]+)/$', blog_list),```- 模板 index```html

最新发布

{%for c in blogcategory_list%}{{c.name}}{% endfor %}

```# 十八、实现按标签查询功能- 编写views```djangodef 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)```- 路由设置```djangourl(r'^tags/(?P[0-9]+)/$', blog_list),```- 模板```django

标签云

{% for t in tags %}

{{t.name}}{{t.count}}

{% endfor %}

```# 十九、实现博客详情功能- 定义视图函数```pythondef 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)```- 路由设置```pythonurl(r'^blog/(?P[0-9]+)/$', blog_detail, name='blog_detail'),```- 前端展示```html{% extends 'base.html' %}{% block title %}知奇博客-详细 {% endblock %}{% block content %}

{{post.title}}

      {{post.pub_date|date:'Y-m-d'}}      {{post.user.username}}{{post.category.name}}          {{post.views}}         

{{post.content}}

标签:    {% for tag in post.tags.all %}{{tag.name}}{% endfor %}

{% endblock %}```# 二十、实现相关推荐功能- 编写视图```djangodef 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)```- 模板```html {% for tag_post in tag_post_list %}

{{ tag_post.title }}

{% endfor %}```# 二十一、实现发表评论的功能# 二十二、实现评论列表功能# 二十三、实现登录功能# 二十四、实现注册功能# 二十五、实现注册验证功能# 二十六、实现注销功能# 二十七、实现后台富文本功能

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容