【毕业设计】基于Django的个人博客系统

男娘i 2024-03-30 11:55 153阅读 0赞

文章目录

  • 0 前言
  • 1 项目需求
  • 2 项目设计
    • 2.1 数据库设计
    • 2.2 站点管理
    • 2.3 注册
    • 2.4 登录
    • 2.5 网站首页
    • 2.6 个人站点
    • 2.7 文章详情
    • 2.8 后台管理
    • 2.9 批量建立测试数据
  • 3 最后

0 前言

Hi,大家好,学长今天想大家介绍一个学长做过的项目,基于Django的个人博客系统

在这里插入图片描述

1 项目需求

  • 基于ajax和用户认证组件实现登录验证
  • 基于ajax和form组件实现注册功能
  • 系统首页文章列表的渲染
  • 个人站点页面设计
  • 文章详细页的继承
  • 点赞与踩灭
  • 评论功能
  • 富文本编辑器的使用
  • 防止xss攻击

在这里插入图片描述

2 项目设计

2.1 数据库设计

  • 1.继承AbstractUser
  • 2.中介模型
  • 3.联合唯一
    在这里插入图片描述

    from django.db import models

    Create your models here.



    from django.contrib.auth.models import AbstractUser


    class UserInfo(AbstractUser):

    1. """
    2. 用户信息
    3. """
    4. nid = models.AutoField(primary_key=True)
    5. telephone = models.CharField(max_length=11, null=True, unique=True)
    6. avatar = models.FileField(upload_to='avatars/', default="avatars/default.png")
    7. create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)

    1. blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE)

    1. def __str__(self):
    2. return self.username



    class Blog(models.Model):

    1. """
    2. 博客信息
    3. """
    4. nid = models.AutoField(primary_key=True)
    5. title = models.CharField(verbose_name='个人博客标题', max_length=64)
    6. site_name = models.CharField(verbose_name='站点名称', max_length=64)
    7. theme = models.CharField(verbose_name='博客主题', max_length=32)

    1. def __str__(self):
    2. return self.title



    class Category(models.Model):

    1. """
    2. 博主个人文章分类表
    3. """
    4. nid = models.AutoField(primary_key=True)
    5. title = models.CharField(verbose_name='分类标题', max_length=32)
    6. blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)

    1. def __str__(self):
    2. return self.title



    class Tag(models.Model):

    1. nid = models.AutoField(primary_key=True)
    2. title = models.CharField(verbose_name='标签名称', max_length=32)
    3. blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)

    1. def __str__(self):
    2. return self.title



    class Article(models.Model):

    1. nid = models.AutoField(primary_key=True)
    2. title = models.CharField(max_length=50, verbose_name='文章标题')
    3. desc = models.CharField(max_length=255, verbose_name='文章描述')
    4. create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    5. content = models.TextField()

    1. comment_count = models.IntegerField(default=0)
    2. up_count = models.IntegerField(default=0)
    3. down_count = models.IntegerField(default=0)

    1. user = models.ForeignKey(verbose_name='作者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
    2. category = models.ForeignKey(to='Category', to_field='nid', null=True, on_delete=models.CASCADE)
    3. tags = models.ManyToManyField(
    4. to="Tag",
    5. through='Article2Tag',
    6. through_fields=('article', 'tag'),
    7. )

    1. def __str__(self):
    2. return self.title



    class Article2Tag(models.Model):

    1. nid = models.AutoField(primary_key=True)
    2. article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid', on_delete=models.CASCADE)
    3. tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid', on_delete=models.CASCADE)

    1. class Meta:
    2. unique_together = [
    3. ('article', 'tag'),
    4. ]

    1. def __str__(self):
    2. v = self.article.title + "---" + self.tag.title
    3. return v



    class ArticleUpDown(models.Model):

    1. """
    2. 点赞表
    3. """

    1. nid = models.AutoField(primary_key=True)
    2. user = models.ForeignKey('UserInfo', null=True, on_delete=models.CASCADE)
    3. article = models.ForeignKey("Article", null=True, on_delete=models.CASCADE)
    4. is_up = models.BooleanField(default=True)

    1. class Meta:
    2. unique_together = [
    3. ('article', 'user'),
    4. ]



    class Comment(models.Model):

    1. """

    1. 评论表

    1. """
    2. nid = models.AutoField(primary_key=True)
    3. article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)
    4. user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
    5. content = models.CharField(verbose_name='评论内容', max_length=255)
    6. create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    7. parent_comment = models.ForeignKey('self', null=True, on_delete=models.CASCADE)

    1. def __str__(self):
    2. return self.content

2.2 站点管理

  1. from django.contrib import admin
  2. # Register your models here.
  3. from blog import models
  4. admin.site.register(models.UserInfo)
  5. admin.site.register(models.Article)
  6. admin.site.register(models.Article2Tag)
  7. admin.site.register(models.ArticleUpDown)
  8. admin.site.register(models.Blog)
  9. admin.site.register(models.Category)
  10. admin.site.register(models.Comment)
  11. admin.site.register(models.Tag)

2.3 注册

核心代码

  1. 1.form组件
  2. 1.form组件
  3. class RegForm(forms.Form):pass
  4. 局部钩子 全局钩子
  5. 2.上传头像 avatar
  6. 图像预览
  7. var reader = new FileReader();
  8. 上传文件
  9. formdata = new FormData();
  10. 3.用户文件配置
  11. avatar = models.FileField(upload_to='avatars/', default='avatars/default.png')
  12. MEDIA_ROOT = os.path.join(BASE_DIR, 'blog', 'media')
  13. MEDIA_URL = '/media/'
  14. re_path(r'media/(?P<path>.*)$',serve,{
  15. 'document_root':settings.MEDIA_ROOT})

在这里插入图片描述

2.4 登录

  1. 1.验证码
  2. 随机生成5个字符,0-9 a-z A-Z
  3. pip install pillow
  4. from PIL import Image, ImageDraw, ImageFont
  5. image = Image.new()
  6. 在内存中生成图片直接返回
  7. from io import BytesIO
  8. f = BytesIO()
  9. 2.request.session['valid_str'] = valid_str
  10. 存在session中,为了之后登录,验证是否通过
  11. 3.验证码点击刷新:
  12. $('#valid_img').click(function () {
  13. $(this)[0].src += '?'
  14. });
  15. 4.认证组件
  16. valid_str = request.session.get('valid_str')
  17. if valid_str.upper() == valid_code.upper():
  18. user = auth.authenticate(username = user, password = pwd)
  19. if user:
  20. auth.login(request, user)

在这里插入图片描述

2.5 网站首页

  1. 1.bootstrap搭建页面
  2. 2.导航条
  3. 登录: username / 注销
  4. 未登录: 登录 / 注册
  5. 3.for循环
  6. {
  7. % for article in article_list %}
  8. {
  9. % endfor %}

在这里插入图片描述

2.6 个人站点

  1. 1.文章列表,分类列表,标签列表,日期归档列表
  2. 文章列表: /blog/egon/
  3. 分类列表: /blog/egon/cate/python
  4. 标签列表: /blog/egon/tag/生活
  5. 日期归档列表: /blog/egon/archive/2018-06
  6. 2.模板继承
  7. {
  8. % extends 'base.html' %}
  9. {
  10. % block content %}
  11. {
  12. % endblock content%}}
  13. 3.自定义标签
  14. /blog/templatetags/my_tag.py
  15. @register.inclusion_tag('menu.html')
  16. def get_menu(username):
  17. ...
  18. return {
  19. } # 去渲染 menu.html
  20. 4.分组查询 .annotate() / extra()应用
  21. 多表分组
  22. tag_list = Tag.objects.filter(blog=blog).annotate(
  23. count = Count('article')).values_list('title', 'count')
  24. 单表分组 / DATE_FORMAT() / extra()
  25. date_list = Article.objects.filter(user=user).extra(
  26. select={
  27. "create_ym": "DATE_FORMAT(create_time,'%%Y-%%m')"}).values('create_ym').annotate(
  28. c = Count('nid')).values_list('create_ym', 'c')
  29. 5. 时间、区域配置
  30. TIME_ZONE = 'Asia/Shanghai'
  31. USE_TZ = False

在这里插入图片描述

2.7 文章详情

  1. 1.模板继承
  2. article = Article.objects.filter(pk=article_id).first()
  3. {
  4. % extends 'base.html' %}
  5. {
  6. % block content %}
  7. ...
  8. {
  9. {
  10. article.articledetail.content|safe }}
  11. {
  12. % endblock content %}

在这里插入图片描述

2.8 后台管理

  1. 1.支持文章编辑
  2. 2.支持富文本编辑器(支持渲染已有文章)
  3. 3.支持删除文章
  4. 4.防止Xss攻击(基于BS4
  5. # 防止xss攻击,过滤script标签
  6. soup = BeautifulSoup(content, "html.parser")
  7. for tag in soup.find_all():
  8. if tag.name == "script":
  9. tag.decompose()

在这里插入图片描述

2.9 批量建立测试数据

  • 1.定制建立测试数据
  • 2.初始化得到100条用户信息,以及为100个客户分别添加文章、博客的详细信息

核心代码

  1. def supreme(request):
  2. """
  3. 这是数据初始化视图,将会生成99条测试数据,用户名为管理员输入的字符后,加1_99.
  4. 密码为管理员填入的密码
  5. :param request:
  6. :return:
  7. """
  8. tag_title = ['BASIC', 'C',
  9. 'C++', 'PASCAL', 'FORTRAN', 'LISP', 'Prolog', 'CLIPS', 'OpenCyc', 'Fazzy', 'Python', 'PHP', 'Ruby',
  10. 'Lua']
  11. category_titles = ['非技术区',
  12. '软件测试',
  13. '代码与软件发布',
  14. '计算机图形学',
  15. '游戏开发',
  16. '程序人生',
  17. '求职面试',
  18. '读书区',
  19. '转载区',
  20. 'Windows',
  21. '翻译区',
  22. '开源研究',
  23. 'Flex']
  24. userlist = []
  25. bolglist = []
  26. article_list = []
  27. tag_list = []
  28. cat_list = []
  29. article2tag_list = []
  30. if request.is_ajax():
  31. form = UserForm(request.POST)
  32. response = {
  33. 'user': None, 'msg': None}
  34. if form.is_valid():
  35. response['user'] = form.cleaned_data.get('user')
  36. # 生成一条用户记录
  37. user = form.cleaned_data.get('user')
  38. pwd = form.cleaned_data.get('pwd')
  39. email = form.cleaned_data.get('email')
  40. avatar_obj = request.FILES.get('avatar')
  41. extra = {
  42. }
  43. if avatar_obj:
  44. extra['avatar'] = avatar_obj
  45. with transaction.atomic():
  46. for i in range(1, 100):
  47. Blog.objects.create(title='blog%s' % i)
  48. UserInfo.objects.create_user(username=user + str(i), password=pwd, email=email, **extra)
  49. UserInfo.objects.filter(username=user + str(i)).update(blog_id=i)
  50. for title in tag_title:
  51. tag_list.append(Tag(title=title, blog_id=i))
  52. for cat in category_titles:
  53. cat_list.append(Category(title=cat, blog_id=i))
  54. import random
  55. for c in range(1, 7):
  56. with open('/home/hyc/PycharmProjects/cnblog/static/superme/%s.txt' % c, 'r',
  57. encoding='utf-8') as f:
  58. content = f.read()
  59. soup = BeautifulSoup(content, "html.parser")
  60. for tag in soup.find_all():
  61. if tag.name == "script":
  62. tag.decompose()
  63. desc = soup.text[0:150] + "..."
  64. c_id = 13 * (i - 1) + random.randrange(1, 9)
  65. article_list.append(
  66. Article(desc=desc, title='article%s' % c, content=content, user_id=i, category_id=c_id))
  67. Category.objects.bulk_create(cat_list)
  68. Tag.objects.bulk_create(tag_list)
  69. Article.objects.bulk_create(article_list)
  70. else:
  71. response['msg'] = form.errors
  72. return JsonResponse(response)
  73. my_from = UserForm
  74. return render(request, 'supreme.html', {
  75. 'from': my_from})

3 最后

发表评论

表情:
评论列表 (有 0 条评论,153人围观)

还没有评论,来说两句吧...

相关阅读