Django博客构建

2024-4-20 359 4/20

Django博客构建 Django博客构建

前言

这个django的博客已经不再更新了。因为维护更新起来太过麻烦(就是懒)

项目链接

源码放这了哈!

github仓库地址: https://github.com/dajavv/DjangoBolg

使用工具

    • PyCharm 2023.1
    • python3.10 版本

Hexo框架

在使用了一段时间的Hexo博客后,对该框架的感受:

优势

    • 具有很多的主题,每一款都非常好看
    • 强大的模板语法
    • 生态完善,具有大量插件,比如:bilibili视频的小卡片、全局搜索、评论模块

劣势

    • 部署不便,要使用命令导入静态文件后部署到github,国内登入网络不稳定(痛点)
    • 维护较为困难
    • 加载缓慢
    • 缺少后端进行管理
    • 无法对整体文章进行搜索(可以通过插件实现,比较麻烦,不考虑)
    • 缺少与访客的互动
    • 缺少对访客数据的记录

解决问题

对于这些问题我决定对博客进行重构,让博客具有更强的功能,我计划对Hexo框架所创建的博客进行重构。 在重构的同时对django框架进行学习

功能

    • (√)导航栏
    • (√)白天黑夜切换
    • (√)分类
    • (√)归档
    • (√)标签分类
    • (√)最新文章
    • (√)后台发布公告
    • (√)后台发布文章
    • (√)后台管理
    • (×)代码高亮
    • ## 新计划
    • (×)访客数据统计
    • (×)全站搜索
    • (×)音乐盒

流程

    1. 使用PyCharm创建Django项目,conda创建虚拟环境python3.10,导包
    1. 创建app命名为post
    1. settings中添加post应用
    1. 对原html静态文件进行导入拆分,制作基础模版
    1. 配置路由,创建视图函数,
    1. 检查是否能正常运行显示
    1. 配置数据库,创建数据表,对需要进行动态更新的数据创建数据表
    1. 将要管理的数据表添加到admin文件中
    1. 使用django的模版语法将要动态改变的数据放到html中
    1. 完善功能(分页、分类、归档、标签归类、最新文章……)
    1. 对网页进行测试
    1. 完成

开始

创建虚拟环境

其中的python为python.exe的路径

python -m pip install virtualenv # 安装虚拟环境库
virtualenv env # 创建虚拟环境
env\Scripts\activate # 进入虚拟环境

创建应用

打开控制台 (可以使用使用ctrl+alt+R快捷键打开manage专属控制台)

django-admin startproject 项目名
cd 项目名
python manage.py startapp app名

在settings.py文件INSTALLED_APPS配置项中添加post应用

INSTALLED_APPS = [
 ...
'post' #添加app
]

创建基础模板

对博客网页进行拆分 组件化拆分利于更新与维护,

    • 基础模版
        • 横幅
        • 导航栏
        • 侧边栏
            • 介绍卡片
            • 公告
            • 分类
            • 标签
            • 归档
            • 最新文章
            • 底部页脚
    • 内容模块
        • 分类
        • 归档
        • 标签
        • 文章选项卡
        • 关于

基础模板

在基础模版中,多为静态不需要改动的页面部分,将他们封装在根目录的templates模版文件夹中

{% include 'banner.html' %} #横幅
<div id="main-grid" class="shadow">
    {% include 'head.html' %} #导航栏
    {% include 'right.html' %} #侧边栏
    {% block main %} <!--与app中的index相连--> #文章选项卡片
    {% endblock %}
    {% include 'footer.html' %} #底部页脚
    <div class="back-to-top-wrapper"><!--回到顶部按键-->
        <button id="back-to-top-btn" class="back-to-top-btn" onclick="topFunction()"> #回到顶部的按钮
            <span class="material-symbols-rounded">keyboard_arrow_up</span>
        </button>
    </div>
</div>

Django模版语法

{% include 'banner.html' %} #引入一部分html代码
{% block main %}...{% endblock %} #页面的动态部分,后面写的会覆盖同名的代码块,在基础模版中用于占位
{% extends 'base.html' %} #继承基础模版中的静态部分
{% block title %}网页标题{% endblock %} #指定该网页的标题
{% for i in 传递过来的相应数据 %}...{% endfor %} #和python中的for相似
{% if 判断条件 %}{% elif 判断条件 %}{% else %}{% endif %} #条件加载

静态文件路径配置

在settings配置文件中添加STATICFILES_DIRS配置

这里是模版的配置,设置优先在根目录中寻找templates模版文件夹

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [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',
                'post.mycontextprocessor.getRightInfo'  # 引入分类,路径是app中的类中的函数
            ],
        },
    },
]

路径配置

只有配置了静态文件在html文件中才能正确找到静态的文件

在settings配置文件中

STATIC_URL = 'static/' #根目录下的static文件夹
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static', 'css'),  # BASE_DIR根目录,这条配置会指定对寻找文件的路径,这里我让他去寻找static文件夹中的css文件夹
os.path.join(BASE_DIR, 'static', 'js'),
os.path.join(BASE_DIR, 'static', 'fontawesome'),
]

在html中

<link rel="stylesheet" href="/static/style.css">
其中的href路径,相当于
static/css/style.css
<script src="/static/bundle.js"></script>

路由配置

在项目名的文件夹中的urls文件中进行配置 在这里我将路由导向了app中的urls文件

urlpatterns = [
    path('admin/', admin.site.urls), #django自带的后台管理面板
    path('', include('post.urls')), # 将路由导向app中的urls文件,核心路由配置
]

app中的路由配置

导入视图类来自app中的views文件 导入路由url配置类

from post import views #app中的视图类
from django.urls import path, re_path #

在这里的路由配置方法主要有两种

as_view的作用

as_view()是Django中用于将类视图转换为可调用的视图函数的方法。 在Django中,类视图是基于类的视图的一种方式。类视图通过继承Django提供的一些基类,可以更清晰、灵活地定义视图逻辑,并提供了许多便捷的方法和属性。但在URL配置中,我们需要将视图映射到具体的URL路径上,这就需要将类视图转换为可调用的函数形式。 .as_view()方法就是用来实现这个转换的。当在URL配置中定义一个类视图时,我们通常会使用.as_view() 方法将其转换为可调用的视图函数,并将其作为参数传递给URL配置。

path(常用):

<>中会匹配一个具体的数据,这个数据将会作为参数传递到视图函数当中

      path('page/<int:num>/', views.IndexViex.as_view(), name='页面'), #路由配置
      #参数一:路由将要拼接的url
      #参数二:指定路由的视图函数
      #参数一:别名

      #views视图函数
      def get(self, request,num=1): #num设置了默认值

re_path(使用正则表达式进行匹配):

用r''来标识正则表达式的文字, ^$匹配开头导结尾 (page/.?/)? page/后面匹配任意文本(除换行符),匹配多次,?可有可无,()?该段文本可有可无 post/ 必须存在的路径 (?P\d+)/ 这里使用了django中的专属语法, <>中匹配一个数据,这个数据将会作为参数传递到视图函数当中

      re_path(r'^(page/.*?/)?post/(?P<postid>\d+)/$', views.DetailViex.as_view(), name='文章'),

视图函数的创建

在viexs文件中创建与视图一一应的视图类,同时必须继承View视图类 get方法,因为是类方法索引必须有self,同时,必须有一个名为request消息的参数,这个参数承载了请求者的信息,我们可以对他进行响应处理,在这个方法中将会接收访问该URL时候的get请求,get请求会在进入url时发起( get请求也可以手动发起),多用于获取数据

class IndexViex(View):
    def get(self, request):
        return render(request, 'index.html', {})#向浏览器返回视图,响应数据
        #第一个参数是请求消息
        #第二个参数是指定所要显示的页面,这里是名为index的html网页文件返回到浏览器,(这里会在前面我们在settings中配置的模版文件夹中自动寻找,当根目录中的模版文件夹中没有该html文件时才会来到app的模版文件夹中寻找)
        #第三个参数是响应数据,一般为将要加载到网页中的动态数据,会在html中使用django模版语法进行加载

启动程序

若前面的配置的没有问题,这时候已经可以启动项目查看网页的大体形态了 这时候的页面还是静态的 打开控制台输入启动命令,启动程序

cd 项目文件夹
python manage.py runserver --post=8000

动态数据

数据库配置

在settings文件中设置数据库

默认数据库SQLite,SQLite 是一个轻量级的关系型数据库管理系统,它以文件形式存储数据库,并且不需要独立的数据库服务器进程。这使得 SQLite 在开发和测试阶段非常方便,因为它不需要额外的数据库服务器安装和配置。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',  # 数据库引擎
        'NAME': BASE_DIR / 'db.sqlite3',  # 路径
    }
}

mysql数据库的配置方法

使用mysql需要额外导入一个包

pip install mysqlclient

导入后对settings中的DATABASES进行配置

DATABASES = {  # 配置数据库
        'default': {
            'ENGINE': 'django.db.backends.mysql',  # mysql数据库引擎
            'NAME': 'boke1',  # 数据库名
            'USER': 'root',  # 账号
            'PASSWORD': '123456',  # 密码
            'HOST': '127.0.0.1',  # url
            'PORT': '3306',  # 端口号
        }
    }

models模型配置

需要我们导入模型库,创建自己的模型类。 在这里写的代码会被转化为sql语句在数据库中创建数据表

from django.db import models#导入模型库


# Create your models here.
class Category(models.Model):#继承于models.Model
    cname = models.CharField(max_length=30, unique=True, verbose_name=u'类别名称')

    def __unicode__(self):
        return u'<Category:%s>' % self.cname

    class Meta:
        db_table = 't_category'  # 表名
        verbose_name_plural = u'类别'


class Tag(models.Model):
    tname = models.CharField(max_length=20, unique=True, verbose_name=u'标签')

    def __unicode__(self):
        return u'<Tag:%s>' % self.tname

    class Meta:
        db_table = 't_tag'
        verbose_name_plural = u'标签'


from ckeditor_uploader.fields import RichTextUploadingField


class Post(models.Model):
    title = models.CharField(max_length=100, unique=True, verbose_name=u'标题')
    desc = models.CharField(max_length=200, verbose_name=u'简介')
    content = RichTextUploadingField(null=True, blank=True, verbose_name=u'内容')  # 引入控件
    created = models.DateTimeField(auto_now_add=True, verbose_name=u'发帖时间')  # 当前时间
    modified = models.DateTimeField(auto_now=True, verbose_name=u'修改时间')  #
    isdelete = models.BooleanField(default=False, verbose_name=u'是否删除')
    category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name=u'所属类别')
    tag = models.ManyToManyField(Tag, verbose_name=u'所属标签')
    words = models.CharField(max_length=15, verbose_name=u'字数')
    photos = models.CharField(max_length=300, verbose_name=u'封面图片')

    def __unicode__(self):
        return u'<Post:%s>' % self.title

    class Meta:
        db_table = 't_Post'
        verbose_name_plural = u'帖子'


class AdminUser(models.Model):
    aname = models.CharField(max_length=20, unique=True, verbose_name='名字')
    avatar = models.CharField(max_length=200, unique=True, verbose_name='头像')
    signature = models.CharField(max_length=100, unique=True, verbose_name='签名')
    announcement = models.CharField(max_length=200, unique=True, verbose_name='公告')
    steam = models.CharField(max_length=200, unique=True, verbose_name='steam链接')
    bilibili = models.CharField(max_length=200, unique=True, verbose_name='bilibili链接')
    github = models.CharField(max_length=200, unique=True, verbose_name='github链接')
    about = models.CharField(max_length=1000, null=True, blank=True, verbose_name=u'关于')
    banner = models.CharField(max_length=200, unique=True, verbose_name='横幅')

    def __unicode__(self):
        return u'<AdminUser:%s>' % self.aname

    class Meta:
        db_table = 't_AdminUser'
        verbose_name_plural = u'管理用户信息'
    verbose_name="名字"#相当于别名会在admin管理界面中使用

    def __unicode__(self):
        return u'<Post:%s>' % self.title #该数据表类在admin管理界面中的标题

数据字段的定意

 aname = models.CharField(max_length=20, unique=True, verbose_name='名字')#字符类型字段,max_length最大长度20,unique不可重复,
 created = models.DateTimeField(auto_now_add=True, verbose_name=u'发帖时间')  # 时间类型字段,auto_now_add自动添加会自动记录当前时间
 isdelete = models.BooleanField(default=False, verbose_name=u'是否删除')#布尔类型字段
 category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name=u'所属类别')#外键
 tag = models.ManyToManyField(Tag, verbose_name=u'所属标签')#多对多类型字段

 content = RichTextUploadingField(null=True, blank=True, verbose_name=u'内容')  # 这里使用了引入的控件库,这个控件库可以使用makdown语法对数据进行编辑

迁移文件

完成数据库的配置后,输入命令创建数据库的迁移文件,执行迁移文件

python manage.py makemigrations #创建迁移文件

python manage.py migrate #执行迁移文件

这时候在根目录下就会生成一个db.sqlite3数据库文件 下载驱动,对数据库进行连接

后台管理系统

这里使用django自带的管理系统 在应用的admin文件夹中配置

from __future__ import unicode_literals
from django.contrib import admin
from .models import *

# Register your models here.
admin.site.register(Category)  # 注册到admin控制面板中
admin.site.register(Tag)
admin.site.register(Post)
admin.site.register(AdminUser)

并且在urls配置中

path('admin/', admin.site.urls),

添加管理用户

对数据库中的auth_user表添加默认管理员账户(我用的是PyCharm右侧的数据库栏手动添加的数据)

python manage.py collectstatic --noinput
python manage.py compress --force

登入管理页面http://127.0.0.1:8000/admin/ 输入你所设置的后台管理账户 添加数据库基础测试数据 在admin中我们可以对配置的数据库数据进行可视化管理

404跳转

在urls配置中添加这一条代码 这行代码会读取settings中的DEBUG配置(该配置为TRUE时),当我们访问不存在的网址时,就会进行跳转

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

视图

在views文件中,我们需要书写代码逻辑对前端的数据进行响应 对库进行导入

import math#数学库

from django.core.paginator import Paginator #分页器
from django.http import HttpResponse, HttpResponseRedirect #响应
from django.shortcuts import render, redirect #渲染,重定向
from django.urls import reverse
from django.views import View  # 导入

from post.models import * #定义的全部模型类

类继承于View,定义视图类。 这是主页的响应类,这里使用render渲染视图

render(request,'要渲染的html文件,响应数据')

首页

渲染index.html文件 请求中的num会从url中得到 使用Paginator分页器,结果返回数据,postList当前页码的数据,page_list页面列表,currentNum当前页码 通过构建一个最大为9个索引的码列表,根据当前页面不断更改页码列表

# Create your views here.
class IndexViex(View):
    def get(self, request, num=1):
        num = int(num)  # 转型

        postList = Post.objects.all().order_by('-created')  # 查询所有的帖子信息,按照发帖时间排序
        page_obj = Paginator(postList, 10)  # 创建分页器对象,每一页显示一条记录
        page_post = page_obj.page(num)  # 获取num页的数据

        begin = int(num - math.ceil(10.0 / 2))  # 页码num在数组中的相对位置
        # print(begin)  # [-4,-3,-2,-1,0,1,2,3,4] 页面的相对位置?
        if begin < 1:  # 当前位置在1(数组后半段)之前,
            begin = 1  # 将当前位置变为1
        end = begin + 9
        if end > page_obj.num_pages:
            end = page_obj.num_pages  # 获取页码总数(最大页码)
        if end < 10:  #
            begin = 1
        else:
            begin = end - 9
        page_list = range(begin, end + 1)  # 构造一个最大为10的数组,并且里面的数字随着页面num的增大而变换,
        return render(request, 'index.html', {'postList': page_post, 'page_list': page_list, 'currentNum': num})

文章

渲染detail.html文件 在这里会通过postid帖子id进行查询获得帖子的内容数据

class DetailViex(View):
    def get(self, request, postid):  # 文章内容
        postid = int(postid)
        post_obj = Post.objects.get(id=postid)  # 条件查询id
        return render(request, 'detail.html', {'post_obj': post_obj})

分类

通过导入的模型类查询该类别的文章,显示在同一页面上

def getPostByCid(request, categorie):  # 分类
    # categoryid = int(category)
    c_post = Post.objects.filter(category__cname=categorie)  # 查询类别下的文章

    # print(c_post)
    return render(request, 'postlist.html', {'categorie': categorie, 'c_post': c_post})

归档

查询全部

def getPostArchives(request):
    c_post = Post.objects.all()  # 查询全部

    return render(request, 'archives.html', {'c_post': c_post})

标签

根据tag查询文章

def getPostTags(request, tag):
    c_post = Post.objects.filter(tag__tname=tag)  # 根据标签名查询

    return render(request, 'tags.html', {'tag': tag, 'c_post': c_post})

关于

读取关于页面的数据表,返回页面信息

def About(request):
    post_obj = AdminUser.objects.all()[0]
    return render(request, 'about.html', {'post_obj': post_obj})

404跳转

# def page_not_found(request, exception):  # 全局404处理函数
#     return redirect('11')  # 重定向回到主页
- THE END -

dajavv

4月20日05:07

最后修改:2024年4月20日
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论