---title: 博客項目(Django版)項目tags: Djangonotebook: 7.0第五月 Python_web后端---[toc]# 一、項目概述## 項目運行環(huán)境1. Python3.6+2. Django 1.113. MySQL 5.74. 其他插件(圖片處理、分頁、驗證碼....)## 項目詳細功能介紹### 前臺功能1. 項目首頁展示2. 輪播圖3. 博客推薦4. 最新發(fā)布5. 博客分類6. 最新評論文章7. widgets小插件8. 搜索功能9. 博客分類功能10. 博客標(biāo)簽查詢11. 友情鏈接12. 博客分頁功能13. 博客詳細14. 最新評論文章15. 發(fā)表評論16. 評論展示17. 評論數(shù)18. 閱讀數(shù)19. 登錄功能20. 注冊功能21. 郵箱驗證功能22. 注銷功能23. 頁面模板24. 標(biāo)簽云功能25. 讀者墻功能### 后臺功能1. 用戶維護2. 權(quán)限管理3. 博客分類維護4. 標(biāo)簽維護5. 友情鏈接6. 輪播圖維護### 項目演示項目演示### 項目代碼演示代碼展示# 二、開發(fā)環(huán)境搭建> 使用virtualenv 和 virtualenwrapper1. MySQL 5.7```vimsudo apt install mysql-server mysql-client```2. 安裝mysql驅(qū)動```vimpip install pymysql```3. 安裝Django```vimpip install django==1.11```# 三、創(chuàng)建項目## 創(chuàng)建項目和應(yīng)用- 創(chuàng)建項目```vimdjango-admin startproject django-blog```- 創(chuàng)建應(yīng)用```vimpython manage.py startapp userapppython manage.py startapp blogapp```## 配置數(shù)據(jù)庫- 在settings中配置數(shù)據(jù)庫```pythonDATABASES = { '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í)行遷移文件)```pythonpython manage.py migrate```## 創(chuàng)建超級管理員```pythonpython manage.py createsuperuser```# 四、創(chuàng)建數(shù)據(jù)模型## USERAPP### USER(用戶模型)```djangofrom django.contrib.auth.models import AbstractUserclass BlogUser(AbstractUser): nikename = models.CharField('昵稱', max_length=20, default='')```> 提示:需要在settings配置文件中設(shè)置:AUTH_USER_MODEL = 'users.BlogUser'### EMAIL(郵箱驗證數(shù)據(jù)模型)```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="發(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(輪播圖模型)```djangoclass 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(博客分類模型)```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(標(biāo)簽?zāi)P?```djangoclass 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(博客模型)```djangoclass 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(評論模型)```djangoclass 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(友情鏈接模型)```djangoclass 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è)置```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', ], }, },]```## 配置靜態(tài)文件路徑```djangoSTATIC_URL = '/static/'STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"),)```# 六、創(chuàng)建首頁路由- 創(chuàng)建視圖函數(shù)```djangodef index(request): return render(request, 'index.html', {})```- 配置url```djangourl(r'^$', index, name='index' )```- 修改模板CSS JS等靜態(tài)文件的路徑# 七、實現(xiàn)幻燈片功能(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 %}
```# 八、實現(xiàn)博客推薦- 注冊模型```djangofrom blogs.models import Banner,Post,BlogCategory,Tags...admin.site.register(BlogCategory)admin.site.register(Tags)admin.site.register(Post)```- 編寫views```django# 視圖函數(shù) 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 %}? ```# 九、實現(xiàn)最新發(fā)布- 編寫views```django# 視圖函數(shù) 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.pub_date|date:'Y-m-d'}}{{post.views}}{{post.comment_set.count}}
? ? ? {% autoescape off %}
? ? ? ? ? {{post.content | truncatechars_html:200}}
? ? ? {% endautoescape %}
{% endfor %}? ```# 十、實現(xiàn)博客分類功能- 編寫視圖```django# 視圖函數(shù) 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
最新發(fā)布
{%for c in blogcategory_list%}{{c.name}}{% endfor %}
```# 十一、實現(xiàn)最新評論功能- 編寫views```django
{% for post in new_comment_list %}
{{ post.title }} {{ post.pub_date }}
{{ post.views }}
{% endfor %}
```# 十二、實現(xiàn)搜索功能- 編寫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'),```# 十三、實現(xiàn)友情鏈接- 編寫視圖? (數(shù)據(jù)源)```djangodef index(request):? ? ....? ? friendlylink_list = FriendlyLink.objects.all()? ? .....```- 模板```django
友情鏈接
{% for friendlylink in friendlylink_list %}{{ friendlylink.title }}{% endfor %}
```# 十四、實現(xiàn)博客列表功能- 編寫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
愛學(xué)習(xí) 更愛分享
{% if user.is_authenticated %}
{% else %}
{% endif %}
{% block content %}{% endblock %}
Copyright ? 2016.Company name All rights reserved.
```# 十五、實現(xiàn)分頁功能- 安裝包```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.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 %}
```# 十六、實現(xiàn)標(biāo)簽云功能```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
標(biāo)簽云
{% for t in tags %}
{% endfor %}
```# 十七、實現(xiàn)分類查詢功能- 編寫視圖```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
最新發(fā)布
{%for c in blogcategory_list%}{{c.name}}{% endfor %}
```# 十八、實現(xiàn)按標(biāo)簽查詢功能- 編寫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)```- 路由設(shè)置```djangourl(r'^tags/(?P[0-9]+)/$', blog_list),```- 模板```django
標(biāo)簽云
{% for t in tags %}
{% endfor %}
```# 十九、實現(xiàn)博客詳情功能- 定義視圖函數(shù)```pythondef 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è)置```pythonurl(r'^blog/(?P[0-9]+)/$', blog_detail, name='blog_detail'),```- 前端展示```html{% extends 'base.html' %}{% block title %}知奇博客-詳細 {% endblock %}{% block content %}
? ? ? {{post.pub_date|date:'Y-m-d'}}? ? ? {{post.user.username}}{{post.category.name}}? ? ? ? ? {{post.views}}? ? ? ? ?
{{post.content}}
標(biāo)簽:? ? {% for tag in post.tags.all %}{{tag.name}}{% endfor %}
{% endblock %}```# 二十、實現(xiàn)相關(guān)推薦功能- 編寫視圖```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)? ? # 相關(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)```- 模板```html {% for tag_post in tag_post_list %}
{% endfor %}```# 二十一、實現(xiàn)發(fā)表評論的功能# 二十二、實現(xiàn)評論列表功能# 二十三、實現(xiàn)登錄功能# 二十四、實現(xiàn)注冊功能# 二十五、實現(xiàn)注冊驗證功能# 二十六、實現(xiàn)注銷功能# 二十七、實現(xiàn)后臺富文本功能