一、模型层
模型层是什么
- 位于视图与数据库之间
- pytho对象与数据库表的转换
为什么需要模型层
- 屏蔽不同数据库之间的差异
- 开发者更加专注于业务逻辑的开发
- 提供多种便捷的工具有利于开发工作
模型层的配置
- settings.py文件中
ENGINE:表示采用的数据库驱动
NAME: 表示该数据库驱动的文件
创建博客文章类型
设计博客模型
博客组成 | 类型 | 备注 |
---|---|---|
文字标题 | 文字类型 | |
文章摘要 | 文字类型 | |
文章内容 | 文字类型 | |
唯一ID标记 | 数值类型 | 自增、主键 |
发布日期 | 日期类型 |
模型定义字段
- 数字类型:IntegerField
- 文本类型:TextField
- 日期类型:DataTimeField
- 自增:AutoField
- 主键:primary_key
1. 定义字段
from django.db import models
# Create your models here.
class Article(models.Model):
# 唯一ID标识
article_id = models.AutoField(primary_key=True)
# 文章标题\
article_title = models.TextField()
# 文章摘要
article_content = models.TextField()
# 文章内容
content = models.TextField()
# 发布日期
publish_data = models.DateTimeField(auto_now=True)
2.将模型迁移到数据库
认识 django shell
1.django shell
- python shell 交互式的编程
- django shell 类似python shell,但继承了Django项目环境
2.为什么需要django shell
- 临时行操作更加方便
- 小范围Debug更简单,不需要运行整个项目
操作:使用django shell 增加一篇文章
#进入django shell: python manage.py shell ——>如下操作创建一篇文章
#from blog.models import Article 【先导入类】
#a = Article( ) 【创建一个文章对象】
#a.article_title = ‘Ethan’ 【文章标题】
#a.article_content = ‘brief introdction’ 【文章摘要】
#a.content = ‘my name is ethan,my job is coding famer’ 【文章内容】
#a.save( ) 【保存表格】
#book = Article.objects.all( ) 【文章列表赋值到变量book】
#article = book[0] 【取列表中的元素赋值到变量article,列表起始元素从0开始】
#print(article.article_title) 【打印显示变量article的各种属性字段的值】
#print(article.article_content)
#print(article.content)
#print(article.article_id)
#print(article.publish_data)
Django Admin模块
admin模块是什么
- django的后台管理工具
- 能读取定义的模型元数据,提供强大的管理使用页面
为什么要使用Admin模块
- django shell 新增文章过于复杂
- 管理页面是基础设施中的重要部分
- 认证用户、显示管理模型、校验输入等功能
怎么使用
-
创建超级管理员 python manage.py createsuperuser
-
模型注册到admin.py中
- 导入模型中的类 from .model import Article
- 在admin.py中注册 admin.site.register(Article) -
登陆到 管理页面,可以看见应用Blog下的模型 Article,此时增删改查文章数据将会十分方便
-
将标题以列表显示 (默认以加入顺序排名显示):
- 在modles.py中:
- 在类Article代码末尾,添加一个函数: 即可在概览页面显示标题def __str__(self): return self.article_title
实现博客数据返回
即从数据库读取数据,并在网页上显示
操作如下:
- 应用的views.py中引入模型中的的Article类
- 编写函数,返回数据库中的文章内容。
- 注意用到的方法: 访问内容列表 XX.objects.all( )
- 取列表值 [0]…
- 访问对象的属性字段
- 字符串拼接
def article_content(requset):
article = Article.objects.all()[0]
title = article.article_title
brief_content = article.article_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.使用Bootstrap 实现静态博客
- 博客页面设计
- 页面分为:博客主页、博客文章详情页
- 博客主页分为:
- 博客文章详情页:
- Bootstrap与Bootstrap的格栅系统
- Bootstrap是美国Twitter公司的设计师Mark Otto和Jacob Thornton合作基于HTML、CSS、JavaScript 开发的简洁、直观、强悍的前端开发框架。提供非常多的控件并且附带源码。
- Bootstrap格栅系统:将页面均分为12等分,从左到右
- 实现静态页面
- (1)创建应用的templates文件夹,创建一个博客主页index.html和文章详情页面detail.html;
- (2)在html文件中,插入Bootstrap的最新的核心的css、JavaScript文件地址
- (3)博客主页页面编写,分为三个< div>完成。分别是博客标题、内容页面、最新文章列表
- 使用到的标签: ~
- < div class=“container page-header”> ~ ~ ~ ~
- < small>
- < div class=“col-md-9” role="'main"> ~ ~ ~ ~
- < h2>
- < p>
- < h4>< a href="#">最新文章11< /a>< /h4> ~ ~ ~ ~ < a> 超链接标签
**** Tips:pycharm 格式化代码快捷键 Ctrl + Alt + L
- (4) 文章详情页编写,由标题和内容页组成,两个< div>
上述的页面为静态页面,写死在html文件中。不方便修改和维护。
2.Django的模板系统
为什么需要模板
-
视图文件不适合编写HTML代码
-
否则,每次页面设计的修改都要修改python代码
- 而往往页面设计会比python代码更加复杂 -
网页逻辑与网页视图应该分开
-分工不同,互相配合才能高效率开发
什么是模板系统
- 模板的表现形式是文本
- 模板分离了文档的表现形式和表现内容
- 模板定义了特有的占位符
- 指定了哪些是表现形式,哪些表现内容
基本语法
-
变量标签:{{变量}}
例子:< html><body>{{变量}}< /body>< /html>
2.for循环标签:
{% for i in list %},{% endfor %}
例子: <ul>
{% for item in list %}
<li>{{item}}</li>
{% endfor %}
</ul>
3. if-else分支标签:
{% if %}, {% else %}, {% endif %}
例子:{% if true %}
<p>This is a true part</p>
{% else %}
<p>This is a false part</p>
{% endif %}
使用模板渲染博客页面
- 修改之前静态的HTML文件
- 以变量名替换文字,以循环替代重复的行,动态灵活
<div class="container page-body">
<div class="col-md-9" role="'main">
<div class='body-main'>
{% for article in article_list %} # article_list代表文章列表,需要被赋值
<div>
<h2>{{ article.article_title }}</h2>
<p>
{{ article.article_content }}
</p>
</div>
{% endfor %}
</div>
</div>
- 在视图文件中,创建专门渲染该页面的视图函数,传递数据进行渲染
def get_index_page(request):
article_list= Article.objects.all()
return render(request,'blog/index.html', # 渲染-传递数据
{
'article_list':article_list # 给html文件中的article_list传递值
}
)
- 博客主页和文章详细页面改动差异不大,但为了文章详细页面内容便于观看,需要做分行处理,以换行符/n分行。
- 视图函数渲染
def get_details_page(request):
curr_article=Article.objects.all()[0] # 获得当前文章
section_list = curr_article.content.split('\n')
return render(request,'blog/details.html',
{
'section_list':section_list
}
)
- 模板文件
<div class='body-main'>
<div>
{% for section in section_list %}
<p>
{{ section }}
</p>
{% endfor %}
</div>
</div>
实现文章详情页面的跳转
开发到此时,博客项目情况:
- 不能从博客主页跳转到文章详情页
- 只能打开某一篇文章的详情页
因此,需要继续进行改进
设计思路
- 设计文章详情页的URL
- 使用地址转化器传递数字
- path(‘detail/< int:article_id>’,views.get_detail_page)
- 完善视图函数的逻辑
- 如何获得文章的编号 article_id
- 先获取全部的文章,然后用for循环执行迭代,判断手动网址输入的数字id是否与文章的id相匹配,如果匹配,就跳出循环(break)
- 这样就获取了文章的编号article_id
- 首页跳转
-
使用< a >标签实现超链接,一般用在标题行 < h >之后
-
用法: <a href="/blog/detail/{{ article.article_id }} > {{ article.article_title }}
- 含义:将文章标题连接超链接,地址是该文章的详细页<h4><a href="/blog/detail/{{ article.article_id }}">{{ article.article_title }}</a></h4>
实现上下篇文章的跳转
- 修改页面布局
- 修改详情页的HTML文件
- 从BootStrap上复制翻页按钮的代码到detail.html文件中
- 并且翻页按钮的文章标题和超链接内容,使用了 {{ 变量 }}来替换。
- {{ previous_article.article.title}}、{{ next_article.article.title}}
- 然后等待视图函数的模版进行数据渲染
-
完善视图函数逻辑
- 使用了enumerate( )它是python的内置函数,将一个可遍历的对象(列表、元组、字符串等) 组合为一个索引序列,同时列出数据和数据下标。 一般用于for循环中,可以同时得到数据对象的值和其对应的索引值。 语法: enumerate(<遍历对象>,[索引起始值])
a = ['one','two','three','four','five'] for index,j in enumerate(a,1): print('{}:{}'.format(i,j))
-
使用enumerate( )获得全部文章的索引值
-
上下文章的判断分三种:
- 第一篇文章,没有上篇,只有下篇,索引值为0
- 最后一篇文章,没有下篇,只有上篇,索引值为元素个数:len( all_article) - 1
- len()返还列表元素个数
- 排序中间的文章,上篇是索引值加一,下篇为索引值减一
-
判断完上下篇索引值后,以索引值确定上下篇文章是哪一篇
- previous_article = all_article[previous_index]
- next_article = all_article[next_index]
-
返回数据渲染后的模版:传递上下篇变量的值进行渲染
实现主页分页功能
-
设计思路:
1.BootStrap实现分页按钮
- 从BootStrap网页上复制分页按钮的代码到index.html
- 为了使得按钮居中:在左侧9等分的区域中,设置从左偏移3,使得其居中
- < div class=“col-mod-4 col-mod-offset-3”>
2.设计分页的URL
- 两种思路 :
1. blog/index/page_number ~~ ~~ ~~ 较为固定,不灵活
2. blog/index?page=page_number ~~ ~~ ~~ ~~ 使用了查询关键字,更加灵活
- 选择查询关键字设计URL。首先需要在视图函数中获取页面值page_number
- 使用 page = request.GET.get(‘page’)
- 为了保证不出错,进行字符转义 page转为 int( )形 - http://127.0.0.1:8000/blog/index?page=3
3. 使用Django分页组件实现分页
Paginator ----django框架的分页组件
- 导入包:from django.core.paginator import Paginator
- 语法 : pages = Paginator(list,每页数量) ~~ ——> 生成分页后的对象,例如pages
- 一些常用到的Paginator函数: ~~
- pages.num_pages:分页的数量
- pages.cout: 被分页的列表中的元素数量
- 取第几分页: page1 = pages.page(1) ~~ ~~ page2 = pages.page(2)
- 还有没有上一分页 : page1.has_previous( ) ~~ ~~ 有返回True,没有返回Flase
- 还有没有下一分页: page2.has_next( ) ~~ ~~ 有返回True,没有返回Flase
def get_index_page(request):
page = request.GET.get('page')
if page:
page = int(page)
else:
page = 1
print('page param:', page)
all_article = Article.objects.all() # 取出全部文章
paginator = Paginator(all_article, 2) # 执行分页
page_num = paginator.num_pages # 分页数量
print('page num:', page_num)
page_article_list = paginator.page(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
return render(request, 'blog/index.html',
{
'article_list': page_article_list,
'page_num': range(1, page_num + 1), # range()的用法
'curr_page': page,
'previous_page': previous_page,
'next_page': next_page,
}
)
实现显示最近5篇文章的列表
1.取5篇文章列表
- 以发布时间倒序排序
- top5_article_list = Article.objects.order_by(’-publish_date’)[:5]
- “ - ”负号表示倒序
- [:5] 是列表取值从第一个到第五个,左边省略表示从第一个开始取
- 将top5_article_list 数据传进模板进行渲染
2. 修改HTML文件
- 将以前的文章列表替换即可
最后作品截图: