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/
安装之后直接cmd输入python,出现版本信息就是安装成功
2、下载Anaconda,地址如下
https://www.anaconda.com/download/success
cmd出现包提示即安装成功
1.2 Django环境安装
cmd命令行安装django2.0
输入下面的命令输出如下内容就是安装成功
1.3 Pycharm IDE安装
下载地址如下:
https://www.jetbrains.com/pycharm/download/?section=windows#section=windows
点击下载即可,community版本即可,学生认证之后即可使用professional版本
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
文件目录如下:
__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 的管理任务,比如运行开发服务器、数据库迁移、创建应用等。
下面运行该项目
进入该地址可以看到django的欢迎页面
2.2 初识Django应用
Django应用 VS Django项目
一个Django项目就是一个基于Djangol的Web应用
一个Django应用就是一个可重用的Python软件包,不可以直接运行,每个应用可以自己管理模型、视图、模板、路由和静态文件等
一个Django项目包含一组配置和若干个Django应用
如下图所示:App3同时在项目一和项目二中,这表示Django应用是可重用的,同时每个项目都有自己的Django应用,比如App1和App2只在项目一种
Django应用目录介绍
输入startapp创建Django应用
同时可以看到项目文件夹多了一些文件,这些文件就是blog应用的问价
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
并且控制台上也有相关路由访问信息打出
3、初始Django模型层
3.1 模型层简介
什么是模型层
为什么需要模型层
- 屏蔽不同数据库(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
接下来运行迁移文件,把迁移文件中的内容同步到数据库中去
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模块的使用
- 创建管理员用户
python D:\PythonProject\django_introduction\manage.py createsuperuser
紧接着不需要输入邮箱,但是密码最好是八位数字字母混合,不然会提示强度不够
- 登录页面进行管理
浏览器地址栏输入http://127.0.0.1:8000/admin
填入刚刚写的用户名和密码进入管理页面
- 注册模型,打开admin.py 输入
from .models import Article
admin.site.register(Article)
- 再次打开管理页面,就会发现出现刚刚注册的模型
- 我们可以在这里自己手动创建一篇文章
- 创建完之后直接保存即可
- 为了让可视化页面更客观,我们可以在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保存代码之后返回刷新浏览器
3.5 实现博客数据返回页面
- 在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)
- 应用层路由配置
urlpatterns = [
path('hello_world', blog.views.hello_world),
path('content', blog.views.article_content)
]
- 访问网址
4、初始Django视图与模板
4.1 使用Bootstrap实现静态博客页面
Bootstrap以及Bootstrap的栅格系统
Bootstrap官网链接:https://www.bootcss.com/
-
来自美国Twitter的前端框架
-
提供非常多的控件并附带源码
栅格系统可以将整个页面从左往右均分为12等份,那么博客首页的主要内容我们可以给他9份,然后右侧的文章列表,我们可以给他分3份
实现静态页面
在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>
文章详情页
<!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 使用模板系统渲染博客页面
- 博客首页
- 在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
- 这里为了展示好看,我们定义一个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()
- 文章详情页
- 修改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
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的官网,挑选分页按钮代码
- 然后修改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
})
效果如下:
4.6 实现分页功能
在博客首页增加分页按钮
一共分为三步:第一步是使用Bootstrap实现分页按钮、第二步是设计分页URL、第三步是使用Django分页组件实现分页功能
- 在index.html的body-main并列的区域添加分页模块
主要在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">«</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">»</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">«</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">»</span>
</a>
</li>
</ul>
</nav>
- 展示页面
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>
- 展示效果
5、总结
附加一个小方法:
Q:有一个现成的深度学习的项目。但是没有使用过django,项目在创建的时候是普通的python项目。现在想在这个项目里引入django框架来开发前端内容怎么办?(anaconda、cuda、pycharm这些环境都配置好了,项目可以运行)
A:①安装Django;②创建Django项目;③将原生Python项目的代码和数据迁移到Django项目的对应目录下;④在Django项目中创建应用(类似于原生Python项目中的模块);⑤将原生Python项目中的功能逐渐移动到Django的视图和模型中;⑥配置URLs,定义路由;⑦测试迁移后的项目,确保所有功能正常工作。