手把手+零基础教你使用Django+Bootstrap搭建一个博客系统

Django

分享源码如下:
项目名:django_introduction
链接: https://pan.baidu.com/s/1F4K91wQ0GlciLcOPtH4hlg 提取码: m2ig

django遵循MVC三层架构模式:也即模型Model、视图View、控制器Controller

开发效率高,功能强大,有丰富的第三方插件

注重安全,避免很多安全漏洞

内容:

  • 准备工作
  • Django项目初体验
  • 初始Django模型层
  • 初始Django视图与模板
  • 总结

1、准备工作

1.1 Python环境安装

1、下载地址如下,直接下载python3.x

https://www.python.org/downloads/

image-20250317164704783

安装之后直接cmd输入python,出现版本信息就是安装成功

image-20250317164952516

2、下载Anaconda,地址如下

https://www.anaconda.com/download/success

image-20250317165318231

cmd出现包提示即安装成功

image-20250317165358856

1.2 Django环境安装

cmd命令行安装django2.0

输入下面的命令输出如下内容就是安装成功

image-20250317165648993

1.3 Pycharm IDE安装

下载地址如下:

https://www.jetbrains.com/pycharm/download/?section=windows#section=windows

点击下载即可,community版本即可,学生认证之后即可使用professional版本

image-20250317165822098

2、Django项目体验

2.1 初识Django项目

命令介绍
  • startproject:创建django项目
  • startapp:创建django应用
  • check:校验项目完整性
  • runserver:进入django环境并且运行django项目
  • test:跑单元测试用例
  • shell:进入django项目的Python Shell环境

数据库相关命令:

  • makemigration:创建模型变更的迁移文件
  • migrate:执行上一个命令创建的迁移文件
  • dumpdata:把数据库数据导出到文件
  • loaddata命令:把文件数据导入到数据库
创建项目

django-admin startproject django_introduction

image-20250317171138049

文件目录如下:

image-20250317171812302

__init__.py:这个文件通常是空的,它使得目录 django_introduction 被 Python 视为一个模块。它在 Django 项目中标记当前目录为包的一部分。

asgi.py:这是一个 Django 启动配置文件,用于配置 Django 与异步服务网关接口 (ASGI) 的连接。如果你需要异步功能或者是用 ASGI 服务器(例如 Daphne)来运行 Django 应用程序时,这个文件很重要。

settings.py:这是 Django 项目的核心配置文件,包含所有关于项目的设置,如数据库配置、已安装的应用、静态文件配置等。几乎所有 Django 项目都需要对这个文件进行配置。

urls.py:这个文件定义了 URL 路由。它将请求的 URL 映射到视图函数上。简单来说,它帮助 Django 知道如何处理不同的请求。

wsgi.py:这个文件用于配置 Django 项目与 WSGI 服务器的连接。WSGI 服务器(如 Gunicorn)是部署 Django 项目时常用的方式。这个文件配置了 Django 与 WSGI 服务器的接口。

manage.py:这个文件是 Django 项目的管理命令入口。你可以通过这个文件来执行很多 Django 的管理任务,比如运行开发服务器、数据库迁移、创建应用等。

下面运行该项目

image-20250317172421363

进入该地址可以看到django的欢迎页面

image-20250317172510898

2.2 初识Django应用

Django应用 VS Django项目

一个Django项目就是一个基于Djangol的Web应用

一个Django应用就是一个可重用的Python软件包,不可以直接运行,每个应用可以自己管理模型、视图、模板、路由和静态文件等

一个Django项目包含一组配置和若干个Django应用

如下图所示:App3同时在项目一和项目二中,这表示Django应用是可重用的,同时每个项目都有自己的Django应用,比如App1和App2只在项目一种

image-20250317172915313

Django应用目录介绍

输入startapp创建Django应用

image-20250317173210364

同时可以看到项目文件夹多了一些文件,这些文件就是blog应用的问价

image-20250317173314084

views.py:视图处理的地方

models.py:定义应用模型的地方

admin.py:定义Admin模块管理对象的地方

apps.py:声明应用的地方

tests.py:编写应用测试用例的地方

urls.py:(自行创建)管理应用路由的地方

2.3 Django HelloWorld

Django视图

在没有框架的时代,我们使用html来展示页面内容,然而不可能通过HTML表达网页所有的内容,还需要有逻辑的处理,那么Django视图就是来处理逻辑来产生内容的
我们在blog应用的views.py中实现一个helloworld函数来返回一个helloworld字符串

函数中request就是http请求的对象,但是直接return 字符串是不可以的,我们需要使用一个response对象,把字符串包裹在HttpResponse中进行返回

# blog/views.py

from django.shortcuts import render
from django.http import HttpResponse

def hello_world(request):
    return HttpResponse("Hello world")
Django路由

截至目前,runserver只能看到Django欢迎页面,看不到我们需要展示的字符串,这是因为Django项目对于我们刚才实现的helloworld视图一无所知,使得我们的请求没有办法到达我们刚才实现的视图函数,所以我们需要配置路由绑定视图函数和url

路由的配置分为两个层次,一个是应用层面,一个是项目层面

# 新建的blog/urls.py

from django.urls import path, include
import blog.views

# 应用层次路由配置
# 数组,如果这个url里面含有hello_world,就把他转发给blog.views.hello_world()这个函数
urlpatterns = [
    path('hello_world', blog.views.hello_world)
]
# django_introduction/urls.py


"""
URL configuration for django_introduction project.

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/5.1/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

# 项目层次的路由配置
# 如果url里面含有blog, 就把他转发到刚才实现的应用层面的路由里面
urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls'))
]

最后将blog应用添加到配置文件settings.py里面,否则不能运行

# 在settings.py中找到下面的数组,将blog.apps.BlogConfig添加进去

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # myapp,下面这个apps.py是创建blog应用时候自己自动生成的文件应用的配置文件,我们需要将他添加到这里
    'blog.apps.BlogConfig'
]

启动应用之后输入地址发现回显到页面上

命令:python D:\PythonProject\django_introduction\manage.py runserver

image-20250317181456164

并且控制台上也有相关路由访问信息打出

3、初始Django模型层

3.1 模型层简介

什么是模型层

image-20250317182647030

为什么需要模型层

  • 屏蔽不同数据库(MySQL、SQLite、Oracle)之间的差异
  • 开发者更加专注于业务逻辑的开发
  • 提供很多便捷工具有助开发

在settings.py中有很多配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # 数据库驱动
        'NAME': BASE_DIR / 'db.sqlite3', # 数据库文件所在位置,表示在当前项目路径下db.sqlite3文件
    }
}

3.2 创建博客文章模型

设计博客模型

文章标题——文本类型(字符串形式)

文章摘要——文本类型(字符串形式)

文章内容——文本类型(字符串形式)

唯一ID标记——Int数字类型(自增、主键)

发布日期——日期类型

模型层定义字段

数字类型:IntegerField

文本类型:TextField

日期类型:DateTimeField

自增ID:AutoField

主键定义:primary_key属性

进入blog/models文件,定义博客模型

from django.db import models

# Create your models here.

# 定义模型需要继承Models.model
class Article(models.Model):
    # 文章主键
    article_id = models.AutoField(primary_key=True)
    # 文章标题
    title = models.TextField()
    # 文章摘要
    brief_content = models.TextField()
    # 文章的主要内容
    content = models.TextField()
    # 文章的发布日期
    publish_data = models.DateTimeField(auto_now=True) # 表示默认以当前时间作为文章的发布日期

接下来进行数据库的迁移,把模型的变更生成一个迁移文件

python D:\PythonProject\django_introduction\manage.py makemigrations

image-20250317184648220

接下来运行迁移文件,把迁移文件中的内容同步到数据库中去

image-20250317184844349

3.3 初识Django Shell

Django Shell是什么

Python Shell是用于交互式的Python编程,那么Django Shelli也类似,继承Django项目环境,通过其我们可以使用Django shell里面的一些对象和配置等等

为什么需要Django Shell
  • 临时性操作使用Django Shell更方便,比如我们刚才创建了一个模型,但是我们不知道这个模型是否可用,如果没有Django Shell,那么我们需要编写一个视图文件,然后编写相关的路由来进行模型测试
  • 小范围Debug更简单,不需要运行整个项目来测试
  • 方便开发、方便调试、方便debug
Django Shell的使用

使用shell定义文章,并打印相关信息

输入命令python D:\PythonProject\django_introduction\manage.py shell

D:\PythonProject\django_introduction>python D:\PythonProject\django_introduction\manage.py shell
Python 3.10.0 (tags/v3.10.0:b494f59, Oct  4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.15.0 -- An enhanced Interactive Python. Type '?' for help.

In [2]: from blog.models import Article

In [3]: a = Article()

In [4]: a.title = 'Test Django Shell'

In [5]: a.brief_content = 'Test Django Shell by lijiajian'

In [6]: a.content = 'xiaxiede1'

In [7]: print(a)
Article object (None)

In [9]: articles = Article.objects.all()

In [10]: article = articles[0]

In [11]: a.save()

In [12]: articles = Article.objects.all()

In [13]: article = articles[0]

In [14]: print(a)
Article object (1)

In [15]: print(a.title)
Test Django Shell

In [16]:

3.4 初识Django Admin模块

Django Admin模块是什么

是Django的后台管理工具,读取定义的模型元数据,提供强大的管理使用页面

为什么需要Django Admin模块

Django Shell新增文章太复杂了

管理页面是基础设施中重要的部分

认证用户、显示管理模型、校验输入等功能类似

Django Admin模块的使用
  1. 创建管理员用户

python D:\PythonProject\django_introduction\manage.py createsuperuser

紧接着不需要输入邮箱,但是密码最好是八位数字字母混合,不然会提示强度不够

  1. 登录页面进行管理

浏览器地址栏输入http://127.0.0.1:8000/admin

填入刚刚写的用户名和密码进入管理页面

  1. 注册模型,打开admin.py 输入
from .models import Article

admin.site.register(Article)
  1. 再次打开管理页面,就会发现出现刚刚注册的模型

image-20250317203536841

  1. 我们可以在这里自己手动创建一篇文章

image-20250317203807091

  1. 创建完之后直接保存即可

image-20250317203827024

  1. 为了让可视化页面更客观,我们可以在model定义一个函数,返回文章的名字
from django.db import models

# Create your models here.

# 定义模型需要继承Models.model
class Article(models.Model):
    # 文章主键
    article_id = models.AutoField(primary_key=True)
    # 文章标题
    title = models.TextField()
    # 文章摘要
    brief_content = models.TextField()
    # 文章的主要内容
    content = models.TextField()
    # 文章的发布日期
    publish_data = models.DateTimeField(auto_now=True) # 表示默认以当前时间作为文章的发布日期

    def __str__(self):
        return self.title

ctrl+s保存代码之后返回刷新浏览器

image-20250317204132649

3.5 实现博客数据返回页面

  1. 在views.py下面添加如下代码
def article_content(request):
    article = Article.objects.all()[0]
    title = article.title
    brief_content = article.brief_content
    content = article.content
    article_id = article.article_id
    publish_data = article.publish_data
    return_str = ('title: %s, brief_content: %s, '
                  'content: %s, article_id: %s, publish_data: %s') % (title,
                                                                      brief_content,
                                                                      content,
                                                                      article_id,
                                                                      publish_data)
    return HttpResponse(return_str)
  1. 应用层路由配置
urlpatterns = [
    path('hello_world', blog.views.hello_world),
    path('content', blog.views.article_content)
]
  1. 访问网址

image-20250317205419614

4、初始Django视图与模板

4.1 使用Bootstrap实现静态博客页面

Bootstrap以及Bootstrap的栅格系统

Bootstrap官网链接:https://www.bootcss.com/

  • 来自美国Twitter的前端框架

  • 提供非常多的控件并附带源码

栅格系统可以将整个页面从左往右均分为12等份,那么博客首页的主要内容我们可以给他9份,然后右侧的文章列表,我们可以给他分3份

image-20250317213423309

实现静态页面

在blog文件夹下创建templates/index.html

然后在Bootstrap官网点击起步(v3的“入门”),将BootCDN.cn粘贴到header之间

博客首页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Django Web入门</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
</head>
<body>
<div class="container page-header">
    <h1>Django Web入门
    <small> —— by Cola_Coder</small></h1>
</div>
<div class="container page-body">
    <div class="col-md-9" role="main">
        <div class="body-main">
            <div>
                <h2>文章标题1</h2>
                <p>
    在有些场合,需要对Django处理的每个request都执行某段代码。这类代码可能是在view处理之前修改传入的request,或者记录日志
    信月以便于调试,等等。2这类功能可以用Djangof的中间件框架来实现,该框架由切入到Django的request/response处理过程中的钩子
    集合组成。每个中间件组件部用于某个特定的功能。如果你是顺着这本书读下来的话,你应该已经多次见到中间件了第12章中所有
    的session和user工具都籍由一小簇中间件实现如,由中间件设定view中可见的request.session和request.user)。第13宣j论的
    站点范围cache实际上也是由一个中间件实现,一旦该中间件发现与view相应的response已在缓存中,就不再调用对应的view函数
    第14章所介绍的flatpages redirects和csf等应吊也都是通过中间件组件来完成其魔法股的功能。这个轻量级低层次的plug-in系
    统,能用于全面的修改Django的输入和输出。
                </p>
                <p>
    每个中间件组件都用于某个特定的功能。如果你是顺着这本书读下来的话,你应该已经多次见到中间件了第12章中所有的seSSIOn和
    user工具都籍由一小族中间件实现(例如,由中间件设定view中可见的request.session和requestuser)。第13章讨论的站点范围
    cache实际上也是由一个中间件实现,一旦该中间件发现与view相应的response已在缓存中,就不再调用对应的view函数。第14章所
    介绍的flatpages,redirects,和csrf等应用也都是通过中间件组件来完成其魔法股的功能。
                </p>
            </div>
            <div>
                <h2>文章标题2</h2>
                <p>
    在有些场合,需要对Django处理的每个request都执行某段代码。这类代码可能是在view处理之前修改传入的request,或者记录日志
    信息以便于调试,等等。2这类功能可以用Django的中间件框架来实现,该框架由切入到Django的requestresponse处理过程中的钩子
    集合组成。每个中间件组件都用于某个特定的功能。如果你是顺着这本书读下来的话,你应该已经多次见到中间件了第12章中所有
    的session和user工具都籍由一小族中间件实现(例如,由中间件设定view中可见的request.session和request.user)。第13章讨论的
    站点范围cache实际上也是由一个中间件实现,一旦该中间件发现与view相应的response已在缓存中,就不再调用对应的view函数。
    统,能用于全面的修改Django的输入和输出。
                </p>
                <p>
    每个中间件组件都用于其个特定的功能。如果你是顺着这本书读下来的话,你应该已经多次见到“中间件”了第12章中所有的seSsion和
    user工具都籍由一小簇中间件实现(例如,由中间件设定view中可见的requestsession和requestuser)。第13章讨论的站点范围
    介绍的flatpages,redirects,和csrf等应用也都是通过中间件组件来完成其魔法般的功能。
                </p>
            </div>
        </div>
    </div>
    <div class="col-md-3" role="complementary">
        <div class="body-sidebar">
            <h2>最新文章</h2>
            <h4><a href="#">最新文章1</a></h4>
            <h4><a href="#">最新文章2</a></h4>
            <h4><a href="#">最新文章3</a></h4>
            <h4><a href="#">最新文章4</a></h4>
            <h4><a href="#">最新文章5</a></h4>
            <h4><a href="#">最新文章6</a></h4>
            <h4><a href="#">最新文章7</a></h4>
            <h4><a href="#">最新文章8</a></h4>
            <h4><a href="#">最新文章9</a></h4>
            <h4><a href="#">最新文章10</a></h4>
        </div>
    </div>
</div>
</body>
</html>

image-20250317220518908

文章详情页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Django Web入门</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css"
          integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"
            integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd"
            crossorigin="anonymous"></script>
</head>
<body>
<div class="container page-header">
    <h1>文章标题1</h1>
</div>
<div class="container body-main">
    <div>
        <p>
            在有些场合,需要对Django处理的每个request都执行某段代码。这类代码可能是在view处理之前修改传入的request,或者记录日志
            信息以便于调试,等等。2这类功能可以用Django的中间件框架来实现,该框架由切入到Django的requestresponse处理过程中的钩子
            集合组成。每个中间件组件都用于某个特定的功能。如果你是顺着这本书读下来的话,你应该已经多次见到中间件了第12章中所有
            的session和user工具都籍由一小族中间件实现(例如,由中间件设定view中可见的request.session和request.user)。第13章讨论的
            站点范围cache实际上也是由一个中间件实现,一旦该中间件发现与view相应的response已在缓存中,就不再调用对应的view函数。
            统,能用于全面的修改Django的输入和输出。
        </p>
        <p>
            每个中间件组件都用于其个特定的功能。如果你是顺着这本书读下来的话,你应该已经多次见到“中间件”了第12章中所有的seSsion和
            user工具都籍由一小簇中间件实现(例如,由中间件设定view中可见的requestsession和requestuser)。第13章讨论的站点范围
            介绍的flatpages,redirects,和csrf等应用也都是通过中间件组件来完成其魔法般的功能。
        </p>
    </div>
</div>

</body>
</html>

4.2 初识Django的模板系统

模板系统简介
  • 视图文件不适合编码HTML

  • 页面设计改变需要修改Python代码

  • 网页逻辑和网页视图应该分开设计

  • 模板系统的表现形式是文本

  • 分离文档的表现形式(页面的视图)和表现内容(页面表现逻辑)

  • 模板系统定义了特有的标签占位符,规定了哪一部分是表现形式,哪一部分是表现内容

基本语法
  • 变量标签:{{变量}}
<html><body>{{now}}</body></html>
  • for循环标签:{% for x in list %),{% endfor %}
<ul>
    {% for item in list %}
    	<li>{{ item }}</li>
    {% endfor %}
</ul>
  • if-else分支标签:{% if %}, {% else %}, {% endif %}
{% if %}
	<p>
       it is a true part 
	</p>
{% else %}
	<p>
       it is a false part 
	</p>
{% endif %}

4.3 使用模板系统渲染博客页面

  1. 博客首页
  • 在template文件夹下面新建template.html,填入需要的信息
<html>
<head><title>Ordering notice</title></head>

<body>
<h1>Ordering notice</h1>
<p>Dear {{ person_name }},</p>
<p>Thanks for placing an order from {{ company }}. It's scheduled to ship on {{ ship_date|date:"F j, Y" }}.</p>
<p>Here are the items you've ordered:</p>

<ul>
    {% for item in item_list %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

{% if ordered_warranty %}
    <p>Your warranty information will be included in the packaging.</p>
{% else %}
    <p>You didn't order a warranty, so you're on your own when the products inevitably stop working.</p>
{% endif %}

<p>Sincerely,<br/>{{ company }}</p>

</body>
</html>
  • 在views.py中添加返回article信息的函数
def get_index_page(request):
    all_articles = Article.objects.all()
    # 将模板系统和数据进行渲染然后返回
    # 调用render函数指定模板路径,会自动搜索应用下的templates目录,所以就会来到blog/templates/blog/index.html
    # 大括号里面是页面所需要的数据,字典格式,index页面需要article_list,那么就等于传入的all_articles
    return render(request, "blog/index.html", {
        "article_list": all_articles
    })
    pass
  • 在应用层次的urls中添加url,将访问方法的路径添加进去
urlpatterns = [
    path('hello_world', blog.views.hello_world),
    path('content', blog.views.article_content),
    path('index', blog.views.get_index_page)
]
  • 启动应用,访问http://127.0.0.1:8000/blog/index

image-20250317235138335

  • 这里为了展示好看,我们定义一个tools/import_data.py以及定义多篇文章data/article,都在template目录下面
#!/usr/bin/python
# -*-encoding=utf8 -*-


import os
import django

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_introduction.settings')
django.setup()

from blog.models import Article

data_path = '../data/article'


def main():
    content_list = []
    files = os.listdir(data_path)
    for name in files:
        f = os.path.join(data_path, name)
        with open(f, 'r', encoding='utf-8') as f:
            content = f.read()
            item = (name[:-4], content[:100], content)
            content_list.append(item)
    # Article.objects.all().delete()
    for item in content_list:
        print('saving article: %s' % item[0])
        article = Article()
        article.title = item[0]
        article.brief_content = item[1]
        article.content = item[2]
        article.save()


if __name__ == '__main__':
    main()

image-20250318001102796

  1. 文章详情页
  • 修改detail.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Django Web入门</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css"
          integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"
            integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd"
            crossorigin="anonymous"></script>
</head>
<body>
<div class="container page-header">
    <h1>{{ current_article.title }}</h1>
</div>
<div class="container body-main">
    <div>
        <p>
            {{ current_article.content }}
        </p>

    </div>
</div>


</body>
</html>
  • 定义get_detail_page函数
def get_detail_page(request):
    current_article = Article.objects.all()[0]
    return render(request, "blog/detail.html", {
        "current_article": current_article
    })
  • 格式化内容,将内容按照空行一行一行展示出来
<div class="container body-main">
    <div>
        {% for section in section_list %}
        <p>{{ section }}</p>
        {% endfor %}
    </div>
</div>
  • 访问http://127.0.0.1:8000/blog/detail

image-20250318002803809

4.4 实现文章详情页面跳转

  • 之前的代码不支持博客首页到文章详情页的跳转

  • 只能打开某一篇文章的详情页

  • 现在我们要实现从首页到详情页的跳转

设计文章详情页URL
  • 我们可以使用article_id来指定某一篇具体的文章
  • 注意下面的detail<int:article_id>,就可以表示url后面拼接数字
urlpatterns = [
    path('hello_world', blog.views.hello_world),
    path('content', blog.views.article_content),
    path('index', blog.views.get_index_page),
    # path('detail', blog.views.get_detail_page)
    path('detail/<int:article_id>', blog.views.get_detail_page)
]
完善视图函数逻辑
  • 实现URL路径参数的获取和传递
# views.py

def get_detail_page(request, article_id):
    all_article = Article.objects.all()
    current_article = None
    for article in all_article:
        if article.article_id == article_id:
            current_article = article
            break
    section_list = current_article.content.split("\n")
    return render(request, "blog/detail.html", {
        "current_article": current_article,
        "section_list": section_list
    })
实现首页跳转
  • 实现从首页跳转到detail页面的功能

  • 主要是对blog/index.html修改,我们把href后面的内容都修改为了/blog/detail/{{ article.article_id }} ,让其可以获取到文章的id

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Django Web入门</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
</head>
<body>
<div class="container page-header">
    <h1>Django Web入门
    <small> —— by Cola_Coder</small></h1>
</div>
<div class="container page-body">
    <div class="col-md-9" role="main">
        <div class="body-main">
            {% for article in article_list %}
            <div>
                <h2><a href="/blog/detail/{{ article.article_id }}">{{ article.title }}</a></h2>
                <p>
                    {{ article.brief_content }}
                </p>
            </div>
            {% endfor %}
        </div>
    </div>
    <div class="col-md-3" role="complementary">
        <div class="body-sidebar">
            <h2>最新文章</h2>
            {% for article in article_list %}
            <h4><a href="/blog/detail/{{ article.article_id }}">{{ article.title }}</a></h4>
            {% endfor %}
        </div>
    </div>
</div>
</body>
</html>

4.5 实现上下篇文章跳转

之前我们已经实现了可以跳转到指定某一篇文章的URL,并且实现了文章详情页的跳转,现在我们实现上一篇文章或者是下一篇文章的跳转,我们采用的方案是在文章详情页下面添加两个按钮实现这个功能

  • 先进入Bootstrap的官网,挑选分页按钮代码

image-20250318212640876

  • 然后修改detail.index,在最下方新建一个div,把代码粘贴进去
<div>
    <nav aria-label="...">
        <ul class="pager">
            <li><a href="/blog/detail/{{ previous_article.article_id }}">上一篇:{{ previous_article.title }}</a></li>
            <li><a href="/blog/detail/{{ next_article.article_id }}">下一篇:{{ next_article.title }}</a></li>
        </ul>
    </nav>
</div>
  • 在views中添加切换博客的功能(修改get_detail_page)方法,主要是添加传入指定页面的功能
def get_detail_page(request, article_id):
    all_article = Article.objects.all()
    current_article = None
    previous_index = 0
    next_index = 0
    previous_article = None
    next_article = None
    for index, article in enumerate(all_article):
        if index == 0:
            previous_index = 0
            next_index = index + 1
        elif index == len(all_article) -1:
            previous_index = index - 1
            next_index = index
        else:
            previous_index = index - 1
            next_index = index + 1
        if article.article_id == article_id:
            current_article = article
            previous_article = all_article[previous_index]
            next_article = all_article[next_index]
            break
    section_list = current_article.content.split("\n")
    return render(request, "blog/detail.html", {
        "current_article": current_article,
        "section_list": section_list,
        "previous_article": previous_article,
        "next_article": next_article
    })

效果如下:

image-20250318234238399

4.6 实现分页功能

在博客首页增加分页按钮

一共分为三步:第一步是使用Bootstrap实现分页按钮、第二步是设计分页URL、第三步是使用Django分页组件实现分页功能

  • 在index.html的body-main并列的区域添加分页模块

image-20250318234536768

主要在body-main模块中进行

<div class="col-md-9" role="main">
    <div class="body-main">
        {% for article in article_list %}
            <div>
                <h2><a href="/blog/detail/{{ article.article_id }}">{{ article.title }}</a></h2>
                <p>
                    {{ article.brief_content }}
                </p>
            </div>
        {% endfor %}
    </div>
    <div class="body-footer">
        {# 下面表示的是分页组件占用四列,偏移三列 #}
        <div class="col-md-4 col-md-offset-3">
            <nav aria-label="Page navigation">
                <ul class="pagination">
                    <li>
                        <a href="#" aria-label="Previous">
                            <span aria-hidden="true">&laquo;</span>
                        </a>
                    </li>
                    <li><a href="#">1</a></li>
                    <li><a href="#">2</a></li>
                    <li><a href="#">3</a></li>
                    <li><a href="#">4</a></li>
                    <li><a href="#">5</a></li>
                    <li>
                        <a href="#" aria-label="Next">
                            <span aria-hidden="true">&raquo;</span>
                        </a>
                    </li>
                </ul>
            </nav>
        </div>
    </div>
</div>
  • 使用:blog/index?page=1=>分页为1的首页 的形式来实现分页

在views.py中修改代码,主要是修改get_index_page函数

def get_index_page(request):
    # 获取page参数
    page = request.GET.get('page')
    # 如果page存在(有可能参数没有附带page),就转换为int类型,否则就是1
    if page:
        page = int(page)
    else:
        page = 1
    all_articles = Article.objects.all()
    # 将模板系统和数据进行渲染然后返回
    # 调用render函数指定模板路径,会自动搜索应用下的templates目录,所以就会来到blog/templates/blog/index.html
    # 大括号里面是页面所需要的数据,字典格式,index页面需要article_list,那么就等于传入的all_articles
    return render(request, "blog/index.html", {
        "article_list": all_articles
    })
    pass
  • 使用Django分页组件实现分页功能
    • 下面我们先使用shell来演示如何使用分页组件
In [1]: from django.core.paginator import Paginator

In [2]: l = [1,2,3,4]

In [3]: print(l)
[1, 2, 3, 4]

In [4]: # 分页组件接收两个参数,一个是列表,另一个是每一页的数量

In [5]: p = Paginator(l,2)

In [6]: p.num_pages
Out[6]: 2

In [7]: # 打印分页内容的总的数量

In [8]: p.count
Out[8]: 4

In [9]: # 通过page函数拿到第一页的分页

In [10]: page1 = p.page(1)

In [11]: # 把page1的内容打印出来

In [13]: page1.object_list
Out[13]: [1, 2]

In [14]: page2 = p.page(2)

In [15]: page2.object_list
Out[15]: [3, 4]

In [16]: # 看一下有没有下一页

In [17]: page2.has_next()
Out[17]: False

In [18]: page1.has_next()
Out[18]: True

In [19]: page1.has_previous()
Out[19]: False

In [21]: page2.has_previous()
Out[21]: True
  • 熟悉分页组件的用法之后,我们将其应用到我们的视图文件中去修改get_index_page函数
def get_index_page(request):
    # 获取page参数
    page = request.GET.get('page')
    # 如果page存在(有可能参数没有附带page),就转换为int类型,否则就是1
    if page:
        page = int(page)
    else:
        page = 1
    # 返回所有的文章列表
    all_articles = Article.objects.all()

    # 创建分页器对象,第一个参数是所有的文章列表,第二个参数是每页显示的文章数
    paginator = Paginator(all_articles, 3)
    page_num = paginator.num_pages
    page_article_list = paginator.page(page)
    if page_article_list.has_next():
        next_page = page + 1
    else:
        next_page = page
    if page_article_list.has_previous():
        previous_page = page - 1
    else:
        previous_page = page

    # 将模板系统和数据进行渲染然后返回
    # 调用render函数指定模板路径,会自动搜索应用下的templates目录,所以就会来到blog/templates/blog/index.html
    # 大括号里面是页面所需要的数据,字典格式,index页面需要article_list,那么就等于传入的all_articles
    return render(request, "blog/index.html", {
        "article_list": page_article_list,
        "page_num" : range(1, page_num + 1),
        "current_page": page,
        "next_page": next_page,
        "previous_page": previous_page
    })
    pass
  • 修改index.html,把原先的bootstrap分页的组件给用for循环包裹一下
<nav aria-label="Page navigation">
                    <ul class="pagination">
                        <li>
                            <a href="/blog/index?page={{ previous_page }}" aria-label="Previous">
                                <span aria-hidden="true">&laquo;</span>
                            </a>
                        </li>
                        {% for num in page_num %}
                        <li><a href="/blog/index?page={{ num }}">{{ num }}</a></li>
                        {% endfor %}
                        <li>
                            <a href="/blog/index?page={{ next_page }}" aria-label="Next">
                                <span aria-hidden="true">&raquo;</span>
                            </a>
                        </li>
                    </ul>
                </nav>
  • 展示页面

image-20250319002834447

4.7 实现最近5篇文章列表

  • 在views.py中修改get_index_page函数,多返回一个变量top5_article_list
    • 注意那个“-”减号,表示的是按照倒序排序,不加减号就是按照最老的排序
def get_index_page(request):
    # 获取page参数
    page = request.GET.get('page')
    # 如果page存在(有可能参数没有附带page),就转换为int类型,否则就是1
    if page:
        page = int(page)
    else:
        page = 1
    # 返回所有的文章列表
    all_articles = Article.objects.all()
    # 根据发布日期进行排序,取出最新的5篇文章
    top5_article_list = Article.objects.order_by('-publish_data')[:5]

    # 创建分页器对象,第一个参数是所有的文章列表,第二个参数是每页显示的文章数
    paginator = Paginator(all_articles, 3)
    page_num = paginator.num_pages
    page_article_list = paginator.page(page)
    if page_article_list.has_next():
        next_page = page + 1
    else:
        next_page = page
    if page_article_list.has_previous():
        previous_page = page - 1
    else:
        previous_page = page

    # 将模板系统和数据进行渲染然后返回
    # 调用render函数指定模板路径,会自动搜索应用下的templates目录,所以就会来到blog/templates/blog/index.html
    # 大括号里面是页面所需要的数据,字典格式,index页面需要article_list,那么就等于传入的all_articles
    return render(request, "blog/index.html", {
        "article_list": page_article_list,
        "page_num" : range(1, page_num + 1),
        "current_page": page,
        "next_page": next_page,
        "previous_page": previous_page,
        "top5_article_list": top5_article_list
    })
    pass
  • 修改index.html的最新文章返回内容
<div class="col-md-3" role="complementary">
    <div class="body-sidebar">
        <h2>最新文章</h2>
        {% for article in top5_article_list %}
            <h4><a href="/blog/detail/{{ article.article_id }}">{{ article.title }}</a></h4>
        {% endfor %}
    </div>
</div>
  • 展示效果

image-20250319003505796

5、总结

Django Web框架入门

附加一个小方法:

Q:有一个现成的深度学习的项目。但是没有使用过django,项目在创建的时候是普通的python项目。现在想在这个项目里引入django框架来开发前端内容怎么办?(anaconda、cuda、pycharm这些环境都配置好了,项目可以运行)

A:①安装Django;②创建Django项目;③将原生Python项目的代码和数据迁移到Django项目的对应目录下;④在Django项目中创建应用(类似于原生Python项目中的模块);⑤将原生Python项目中的功能逐渐移动到Django的视图和模型中;⑥配置URLs,定义路由;⑦测试迁移后的项目,确保所有功能正常工作。

<think>嗯,用户想在Django项目中集成Bootstrap5。首先,我需要回忆一下BootstrapDjango中的常用方法。之前用过django-bootstrap5这个第三方库,对吧?用户提到的引用里也提到了这个项目,所以应该推荐这个。 首先,用户需要安装这个库。安装步骤应该是用pip安装django-bootstrap5。然后,在Django的settings.py里添加这个应用到INSTALLED_APPS中。对吧?这样配置之后,模板里就可以用提供的模板标签了。 接下来,如何在模板中使用呢?记得是要加载bootstrap5的标签,然后用{% bootstrap_css %}和{% bootstrap_javascript %}来引入所需的CSS和JS文件。这样就不用手动下载和放置静态文件了,挺方便的。 然后,关于表单的渲染。Bootstrap5的表单样式可能需要特定的类,而使用django-bootstrap5的{% bootstrap_form %}标签可以自动为表单字段添加正确的类,确保样式正确。用户可能需要这个步骤来美化表单。 另外,静态文件的处理。虽然这个库会自动处理,但用户需要确保配置好STATIC_URL,并且运行collectstatic命令,特别是在生产环境中。这可能会是个容易忽略的点,需要提醒用户。 可能用户还会遇到版本兼容性问题,比如Django的版本是否支持,或者Bootstrap5是否有特定要求。建议查看官方文档,或者遇到问题时检查版本信息。 还有,用户可能想自定义样式,这时候可能需要覆盖默认的模板或者添加自定义CSS。应该提到在static目录中创建自己的CSS文件,并在模板中额外引入。 最后,示例代码部分要展示基本用法,包括模板中如何加载库,使用标签引入CSS和JS,以及渲染表单。这样用户可以直接复制修改,快速上手。 检查一下是否需要其他配置,比如中间件或者额外的设置,但看起来这个库的集成相对简单,主要是安装和模板标签的使用。确保步骤清晰,避免遗漏重要环节。</think>### Django集成Bootstrap5的步骤说明 在Django项目中集成Bootstrap5可以通过第三方库$django-bootstrap5$实现,以下是具体实现步骤: #### 1. 安装依赖包 ```bash pip install django-bootstrap5 ``` #### 2. 配置settings.py ```python INSTALLED_APPS = [ # ... 'django_bootstrap5', # ... ] ``` #### 3. 模板基础配置 在基类模板中加载资源(如base.html): ```html {% load django_bootstrap5 %} <!DOCTYPE html> <html> <head> {% bootstrap_css %} {% bootstrap_javascript %} </head> <body> {% block content %}{% endblock %} </body> </html> ``` #### 4. 表单渲染示例 在具体模板中使用Bootstrap样式渲染表单: ```html <form method="post"> {% csrf_token %} {% bootstrap_form form %} {% bootstrap_button "提交" type="submit" %} </form> ``` #### 5. 静态文件配置 确保已配置STATIC_URL: ```python STATIC_URL = '/static/' ``` #### 6. 高级特性(可选) 通过覆盖模板实现样式定制: ```bash your_app/ templates/ django_bootstrap5/ bootstrap5.html # 自定义模板 ``` ### 关键特性说明 1. **自动版本管理**:自动加载Bootstrap 5的最新稳定版资源[^1] 2. **表单增强**:为表单元素自动添加$form-control$等类名[^2] 3. **响应式支持**:内置栅格系统兼容性处理 4. **图标集成**:支持使用Bootstrap Icons(需单独安装) ### 注意事项 - 开发环境需开启DEBUG模式才能自动加载静态文件 - 生产环境需执行$python manage.py collectstatic
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值