Django开发博客流程
源码:https://files.cnblogs.com/files/Alone-Tree/dreamblog.rar
一、实现功能
1 基于Ajax和用户认证实现的登录验证 ----验证码
2 基于ajax和form组件实现注册功能
3 系统首页的布局
4 个人站点页面设计
5 文章详细页的设计
6 基于ajax实现文章点赞与踩灭(联合唯一)
7 基于ajax评论功能
8 kindeditor和beautifulSoup
二、所用知识
1 django的ORM:跨表查询,分组查询
2 Bootstrap
3 Ajax
4 用户认证(auth)
三、结果预览
首页
登陆
注册
网站首页
个人站点页
个人后台管理首页
个人资料设置
添加新文章
添加标签或者分类
404页面
四、开发流程
网站分为前端显示、后端管理,建立两个app应用。工程目录结构如下:
backend目录为后端管理,blog为前端显示,media为文件上传目录,static静态文件目录,templates模板
blog应用
1.创建模型表
from django.db import models # Django自带的认证 from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): """ 用户信息 """ nid = models.AutoField(primary_key=True) telephone = models.CharField(max_length=11, null=True, unique=True) avatar = models.FileField(upload_to='avatars/', default="avatars/default.jpg") create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE) def __str__(self): return self.username class Blog(models.Model): """ 博客信息 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='个人博客标题', max_length=64) site = models.CharField(verbose_name='个人博客后缀', max_length=32, unique=True) theme = models.CharField(verbose_name='博客主题', max_length=32) def __str__(self): return self.title class Category(models.Model): """ 博主个人文章分类表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='分类标题', max_length=32) blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Tag(models.Model): """ 博主个人文章标签表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='标签名称', max_length=32) blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Article(models.Model): """ 博主个人文章表 """ nid = models.AutoField(primary_key=True) title = models.CharField(max_length=50, verbose_name='文章标题') desc = models.CharField(max_length=255, verbose_name='文章描述') create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) comment_count = models.IntegerField(verbose_name='评论数', default=0) up_count = models.IntegerField(verbose_name='点赞数', default=0) down_count = models.IntegerField(verbose_name='踩数', default=0) category = models.ForeignKey(verbose_name='文章分类', to='Category', to_field='nid', null=True, on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) tags = models.ManyToManyField(to="Tag", through='Article2Tag', through_fields=('article', 'tag'),) def __str__(self): return self.title class ArticleDetail(models.Model): """ 文章详细表 """ nid = models.AutoField(primary_key=True) content = models.TextField() article = models.OneToOneField(to='Article', to_field='nid', on_delete=models.CASCADE) class Article2Tag(models.Model): """ 文章标签关系表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid', on_delete=models.CASCADE) tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid', on_delete=models.CASCADE) class Meta: unique_together = [ ('article', 'tag'), ] def __str__(self): v = self.article.title + "--" + self.tag.title return v class ArticleUpDown(models.Model): """ 点赞、踩表 """ nid = models.AutoField(primary_key=True) user = models.ForeignKey('UserInfo', null=True, on_delete=models.CASCADE) article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE) is_up = models.BooleanField(default=True) class Meta: unique_together = [ ('article', 'user'), ] class Comment(models.Model): """ 评论表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) content = models.CharField(verbose_name='评论内容', max_length=255) create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) parent_comment = models.ForeignKey('self', verbose_name='父评论', null=True, on_delete=models.CASCADE) def __str__(self): return self.content
2.视图
import json from django.db import transaction from django.db.models import F from django.http import JsonResponse from django.shortcuts import render, redirect, HttpResponse from django.contrib import auth from blog import check_code from blog import forms as myform from blog import models from blog.pager import Paginator def cover(request): return render(request, 'cover.html') def get_valid_img(request): """获取验证码""" data = check_code.get_valid_img(request) return HttpResponse(data) def register(request): """注册""" if request.method == 'GET': form = myform.RegisterForm() else: res = {"user": None, "msg": None, "error_dict": None} valid_code = request.POST.get('valid_code') valid_str = request.session["valid_str"] # 判断验证码是否正确 if valid_code.upper() == valid_str.upper(): form = myform.RegisterForm(request.POST) # 校验数据 if form.is_valid(): username = request.POST.get('username') email = request.POST.get('email') password = request.POST.get('password') avatar = request.FILES.get('avatar') blog = models.Blog.objects.create(title=username, site=username, theme='cs1.css') if avatar: user = models.UserInfo.objects.create_user(username=username, password=password, email=email, avatar=avatar, blog=blog, telephone='0000') else: user = models.UserInfo.objects.create_user(username=username, password=password, email=email, blog=blog, telephone='0000') res["user"] = user.username else: res["error_dict"] = form.errors else: res["msg"] = "验证码错误!" return JsonResponse(res) return render(request, 'register.html', locals()) def login(request): """登陆""" res = {'state': False, 'msg': None} if request.method == 'POST': user = request.POST.get('user') password = request.POST.get('pwd') valid_code = request.POST.get('valid_code') valid_str = request.session["valid_str"] # 判断验证码是否正确 if valid_code.upper() == valid_str.upper(): user = auth.authenticate(username=user, password=password) if user: res['state'] = True auth.login(request, user) else: res['msg'] = '用户名或者密码错误' else: res['msg'] = '验证码错误' return JsonResponse(res) return render(request, 'login.html') def logout(request): """退出""" auth.logout(request) return redirect('/') def index(request): """首页""" total = models.Article.objects.all().count() current_page = request.GET.get('p') page_obj = Paginator(total, current_page) article_list = models.Article.objects.all()[page_obj.start():page_obj.end()] return render(request, 'index.html', locals()) def homesite(request, username, **kwargs): """个人主站""" # 得到用户对象 user = models.UserInfo.objects.filter(username=username).first() if not user: return redirect('/404') # 得到站点对象 blog = user.blog # 得到站点文章集合 if not kwargs: article_list = models.Article.objects.filter(user=user) print('==========',article_list) else: condition = kwargs.get("condition") param = kwargs.get("param") if condition == "cate": article_list = models.Article.objects.filter(user=user).filter(category__title=param) elif condition == "tag": article_list = models.Article.objects.filter(user=user).filter(tags__title=param) else: year, month = param.split("-") article_list = models.Article.objects.filter(user=user).filter(create_time__year=year, create_time__month=month) return render(request, 'homesite.html', locals()) def article_detail(request, username, article_id): """文章详细""" user = models.UserInfo.objects.filter(username=username).first() if not user: return redirect('/404') blog = user.blog article = models.Article.objects.filter(nid=article_id).first() if not article: return redirect('/404') comment_list = models.Comment.objects.filter(article_id=article_id) return render(request, 'article_detail.html', locals()) def poll(request): """点赞踩灭""" is_up = json.loads(request.POST.get("is_up")) article_id = request.POST.get("article_id") user_id = request.user.pk res = {"state": True} try: with transaction.atomic(): models.ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=is_up) if is_up: models.Article.objects.filter(pk=article_id).update(up_count=F("up_count")+1) else: models.Article.objects.filter(pk=article_id).update(down_count=F("down_count") + 1) except Exception as e : res["state"] = False res["first_operate"] = models.ArticleUpDown.objects.filter(article_id=article_id, user_id=user_id).first().is_up return JsonResponse(res) def comment(request): """评论""" res = {"state": True} user_id = request.user.pk article_id = request.POST.get('article_id') content = request.POST.get('content') pid = request.POST.get('pid') with transaction.atomic(): if not pid: obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content) else: obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content, parent_comment_id=pid) models.Article.objects.filter(pk=article_id).update(comment_count=F('comment_count') + 1) print(JsonResponse(res)) return JsonResponse(res) def error(request): return render(request, '404.html')
---恢复内容结束---
一、实现功能
1 基于Ajax和用户认证实现的登录验证 ----验证码
2 基于ajax和form组件实现注册功能
3 系统首页的布局
4 个人站点页面设计
5 文章详细页的设计
6 基于ajax实现文章点赞与踩灭(联合唯一)
7 基于ajax评论功能
8 kindeditor和beautifulSoup
二、所用知识
1 django的ORM:跨表查询,分组查询
2 Bootstrap
3 Ajax
4 用户认证(auth)
三、结果预览
首页
登陆
注册
网站首页
个人站点页
个人后台管理首页
个人资料设置
添加新文章
添加标签或者分类
404页面
四、开发流程
网站分为前端显示、后端管理,建立两个app应用。工程目录结构如下:
backend目录为后端管理,blog为前端显示,media为文件上传目录,static静态文件目录,templates模板
blog应用
1.创建模型表
from django.db import models # Django自带的认证 from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): """ 用户信息 """ nid = models.AutoField(primary_key=True) telephone = models.CharField(max_length=11, null=True, unique=True) avatar = models.FileField(upload_to='avatars/', default="avatars/default.jpg") create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE) def __str__(self): return self.username class Blog(models.Model): """ 博客信息 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='个人博客标题', max_length=64) site = models.CharField(verbose_name='个人博客后缀', max_length=32, unique=True) theme = models.CharField(verbose_name='博客主题', max_length=32) def __str__(self): return self.title class Category(models.Model): """ 博主个人文章分类表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='分类标题', max_length=32) blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Tag(models.Model): """ 博主个人文章标签表 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='标签名称', max_length=32) blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE) def __str__(self): return self.title class Article(models.Model): """ 博主个人文章表 """ nid = models.AutoField(primary_key=True) title = models.CharField(max_length=50, verbose_name='文章标题') desc = models.CharField(max_length=255, verbose_name='文章描述') create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) comment_count = models.IntegerField(verbose_name='评论数', default=0) up_count = models.IntegerField(verbose_name='点赞数', default=0) down_count = models.IntegerField(verbose_name='踩数', default=0) category = models.ForeignKey(verbose_name='文章分类', to='Category', to_field='nid', null=True, on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) tags = models.ManyToManyField(to="Tag", through='Article2Tag', through_fields=('article', 'tag'),) def __str__(self): return self.title class ArticleDetail(models.Model): """ 文章详细表 """ nid = models.AutoField(primary_key=True) content = models.TextField() article = models.OneToOneField(to='Article', to_field='nid', on_delete=models.CASCADE) class Article2Tag(models.Model): """ 文章标签关系表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid', on_delete=models.CASCADE) tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid', on_delete=models.CASCADE) class Meta: unique_together = [ ('article', 'tag'), ] def __str__(self): v = self.article.title + "--" + self.tag.title return v class ArticleUpDown(models.Model): """ 点赞、踩表 """ nid = models.AutoField(primary_key=True) user = models.ForeignKey('UserInfo', null=True, on_delete=models.CASCADE) article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE) is_up = models.BooleanField(default=True) class Meta: unique_together = [ ('article', 'user'), ] class Comment(models.Model): """ 评论表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE) content = models.CharField(verbose_name='评论内容', max_length=255) create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) parent_comment = models.ForeignKey('self', verbose_name='父评论', null=True, on_delete=models.CASCADE) def __str__(self): return self.content
2.视图
import json from django.db import transaction from django.db.models import F from django.http import JsonResponse from django.shortcuts import render, redirect, HttpResponse from django.contrib import auth from blog import check_code from blog import forms as myform from blog import models from blog.pager import Paginator def cover(request): return render(request, 'cover.html') def get_valid_img(request): """获取验证码""" data = check_code.get_valid_img(request) return HttpResponse(data) def register(request): """注册""" if request.method == 'GET': form = myform.RegisterForm() else: res = {"user": None, "msg": None, "error_dict": None} valid_code = request.POST.get('valid_code') valid_str = request.session["valid_str"] # 判断验证码是否正确 if valid_code.upper() == valid_str.upper(): form = myform.RegisterForm(request.POST) # 校验数据 if form.is_valid(): username = request.POST.get('username') email = request.POST.get('email') password = request.POST.get('password') avatar = request.FILES.get('avatar') blog = models.Blog.objects.create(title=username, site=username, theme='cs1.css') if avatar: user = models.UserInfo.objects.create_user(username=username, password=password, email=email, avatar=avatar, blog=blog, telephone='0000') else: user = models.UserInfo.objects.create_user(username=username, password=password, email=email, blog=blog, telephone='0000') res["user"] = user.username else: res["error_dict"] = form.errors else: res["msg"] = "验证码错误!" return JsonResponse(res) return render(request, 'register.html', locals()) def login(request): """登陆""" res = {'state': False, 'msg': None} if request.method == 'POST': user = request.POST.get('user') password = request.POST.get('pwd') valid_code = request.POST.get('valid_code') valid_str = request.session["valid_str"] # 判断验证码是否正确 if valid_code.upper() == valid_str.upper(): user = auth.authenticate(username=user, password=password) if user: res['state'] = True auth.login(request, user) else: res['msg'] = '用户名或者密码错误' else: res['msg'] = '验证码错误' return JsonResponse(res) return render(request, 'login.html') def logout(request): """退出""" auth.logout(request) return redirect('/') def index(request): """首页""" total = models.Article.objects.all().count() current_page = request.GET.get('p') page_obj = Paginator(total, current_page) article_list = models.Article.objects.all()[page_obj.start():page_obj.end()] return render(request, 'index.html', locals()) def homesite(request, username, **kwargs): """个人主站""" # 得到用户对象 user = models.UserInfo.objects.filter(username=username).first() if not user: return redirect('/404') # 得到站点对象 blog = user.blog # 得到站点文章集合 if not kwargs: article_list = models.Article.objects.filter(user=user) print('==========',article_list) else: condition = kwargs.get("condition") param = kwargs.get("param") if condition == "cate": article_list = models.Article.objects.filter(user=user).filter(category__title=param) elif condition == "tag": article_list = models.Article.objects.filter(user=user).filter(tags__title=param) else: year, month = param.split("-") article_list = models.Article.objects.filter(user=user).filter(create_time__year=year, create_time__month=month) return render(request, 'homesite.html', locals()) def article_detail(request, username, article_id): """文章详细""" user = models.UserInfo.objects.filter(username=username).first() if not user: return redirect('/404') blog = user.blog article = models.Article.objects.filter(nid=article_id).first() if not article: return redirect('/404') comment_list = models.Comment.objects.filter(article_id=article_id) return render(request, 'article_detail.html', locals()) def poll(request): """点赞踩灭""" is_up = json.loads(request.POST.get("is_up")) article_id = request.POST.get("article_id") user_id = request.user.pk res = {"state": True} try: with transaction.atomic(): models.ArticleUpDown.objects.create(user_id=user_id, article_id=article_id, is_up=is_up) if is_up: models.Article.objects.filter(pk=article_id).update(up_count=F("up_count")+1) else: models.Article.objects.filter(pk=article_id).update(down_count=F("down_count") + 1) except Exception as e : res["state"] = False res["first_operate"] = models.ArticleUpDown.objects.filter(article_id=article_id, user_id=user_id).first().is_up return JsonResponse(res) def comment(request): """评论""" res = {"state": True} user_id = request.user.pk article_id = request.POST.get('article_id') content = request.POST.get('content') pid = request.POST.get('pid') with transaction.atomic(): if not pid: obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content) else: obj = models.Comment.objects.create(user_id=user_id, article_id=article_id, content=content, parent_comment_id=pid) models.Article.objects.filter(pk=article_id).update(comment_count=F('comment_count') + 1) print(JsonResponse(res)) return JsonResponse(res) def error(request): return render(request, '404.html')