12、Bootstrap响应式布局
这节课我们完成对博客列表页的修改
想要实现的效果如图
响应式布局:根据屏幕的大小自动地控制调整页面布局
在www.bootcss.com页面的“全局CSS样式”——“栅格系统”、“栅格参数”:
分为四种屏幕大小:xs(手机)、sm(平板)、md(桌面显示器)、lg(大桌面显示器)。“实例:从堆叠到水平排列”:.col-md-8
表示:列-屏幕大小-占多少列宽度,
1、Bootstrap的响应式设计
- 适应4种屏幕大小、12列布局
- < 768px(手机)
- > = 768px(平板)
- >= 992px(小尺寸显示器)
- >= 1200px(大尺寸显示器)
“布局容器”
2、基本结构
<div class="container">
<div class="row">
<div class="col-xx-*"></div>
<div class="col-xx-*"></div>
</div>
</div>
先改博客列表,打开blog_list.html
注意 ,博客具体分类这里,前面处理方法没有传递给它,是由前面blog/views.py中的blog_list中的context['blogs']
,这里传了一个博客。这里有一个问题,博客列表的模板页面在mysite/templates/blog目录下,需要到mysite/blog/下找到views.py,这里出现了一个纰漏,前面说过,跟项目比较紧密的文件,放到全局静态文件夹里面,而这个模板页面文件跟app比较紧密一些,那么我们还是放到app目录下会好一点。所以我们将mysite/templates/blog整个文件夹剪切到mysite/blog/templates下
修改views.py如下:
打开blog_list.html修改如下:
<!-- C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\templates\blog\blog_list.html -->
{% extends 'base.html' %}
{# 页面标题 #}
{% block title %}
我的网站
{% endblock %}
{% block nav_blog_active %}active{% endblock %}
{# 页面内容 #}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-8">
{% for blog in blogs %}
<a href="{% url 'blog_detail' blog.pk %}">
<h3>{{ blog.title }}</h3>
</a>
<p>{{ blog.content | truncatechars:50}}</p>
{% empty %}
<p>-- 暂无博客,敬请期待 --</p>
{% endfor %}
<p>一共有{{ blogs | length}} 篇博客</p>
</div>
<div class="col-md-4">
<h4>博客分类</h4>
<ul>
{% for blog_type in blog_types %}
<li>
<a href="{% url 'blogs_with_type' blog_type.pk %}">{{ blog_type.type_name }}</a>
</li>
{% empty %}
<li>暂无分类</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endblock %}
刷新页面效果如下:
下面我们要对这两块进行更改。我们看一下官方文档里面的“组件”——“面板”
修改blog_list.html如下:
<div class="col-md-4">
<div class=" panel panel-default">
<div class="panel-heading">博客分类</div>
<div class="panel-body">
<ul>
{% for blog_type in blog_types %}
<li><a href="{% url 'blogs_with_type' blog_type.pk %}">{{ blog_type.type_name }}</a>
</li>
{% empty %}
<li>暂无分类</li>
{% endfor %}
</ul>
</div>
</div>
</div>
刷新页面:
这里博客分类前面的点,我们想要去掉,这就涉及到控制这里的样式,写到base_list.html中去
同样的,我们对左边的博客列表进行相同的处理
我们缩放屏幕发现,这一行两列会被压缩到两行,因为我们只是设置了md中等屏幕样式,而小屏幕我们没有设置,它是默认的按照12列去显示的,所以我们需要加上小屏幕的设置,col-sm-8
我们设置为8和4,然后拉窄页面看看,是生效的。这里如果我们只写小屏幕sm,不写md,也可以,因为它是由小往大去适用的,而刚刚我们写了大的md,而没有写小的sm,是不生效中屏幕的。那我们超小屏幕,这根据需求定,想不想让博客分类栏显示在下一行,或直接不显示这一栏,这里我们先设为让它不显示,即设置它对应的超小屏幕为0 col-xs-0
,发现会出问题。那么该怎么去设置呢,这里有另外一个东西,在官网文档的“响应式工具”这里“可用的类”里面有“可见”或者“隐藏”,我们将超小屏幕下设为隐藏就可以hidden-xs
这里,关于列的响应式布局大概讲到这个地方。
接着我们往下将另外一个内容,将上面ul的样式保存到静态文件夹里面,修改blog_list.html如下,添加代码,加载静态文件:
给ul加一个class,便于后面css样式设置
在static目录下新建blog.css,将前面ul里面的css样式剪切过来,如下内容:
这里又出现了一个新的问题,和刚刚templates模板的问题差不多,我们这个css文件是要放到公共的static目录里面呢,还是要放到blog目录下呢?两者都可以,但为了统一和app的可维护性,我们可以放到app里面的目录,在blog目录下创建static文件夹,把blog.css剪切到这个static目录下
刷新页面,出现了not found的错误,这跟django的机制有关系(刚刚templates同样也有这个问题),原因是多个app可能模板文件名就会重复,重复了之后django找到第一个文件后就不再找第二个同名文件了。
3、Django静态文件命名空间
- 为了避免同名冲突问题
static/app/xxx.css
为了解决这个冲突,需要一个命名空间。命名空间是这么去建立的:在刚刚创建的static下新建一文件夹,这个文件夹名称就是app名称(这里是blog),然后将blog.css放入到blog文件夹下面。然后修改一下blog_list.html里面的路径
刷新页面,发现还是这个问题,原因是我们需要重启一下本地服务python manage.py runserver
接下来我们完善左边的博客列表样式,参考Bootstrap
打开blog_list.html:
<!-- C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\templates\blog\blog_list.html -->
{% extends 'base.html' %}
{# 页面标题 #}
{% block title %}
我的网站
{% endblock %}
{% block nav_blog_active %}active{% endblock %}
{% load staticfiles %}
{% block header_extends %}
<link rel="stylesheet" type="text/css" href="{% static 'blog/blog.css' %}">
{% endblock %}
{# 页面内容 #}
{% block content %}
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-10">
<div class=" panel panel-default">
<div class="panel-heading">{% block blog_list_title %}博客列表(一共有{{ blogs | length}}篇博客){% endblock %}</div>
<div class="panel-body">
{% for blog in blogs %}
<div class="blog">
<h3><a href="{% url 'blog_detail' blog.pk %}">{{ blog.title }}</a></h3>
<p class="blog-info">
<span class="glyphicon glyphicon-tag"></span><a href="{% url 'blogs_with_type' blog.blog_type.pk %}">{{ blog.blog_type }}</a>
<span class="glyphicon glyphicon-time"></span>{{ blog.created_time|date:"Y-m-d" }}
</p>
<p>{{ blog.content | truncatechars:120}}</p>
</div>
{% empty %}
<div class="blog">
<h3>暂无博客,敬请期待</h3>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="hidden-xs col-sm-4 col-md-4 col-lg-2">
<div class=" panel panel-default">
<div class="panel-heading">博客分类</div>
<div class="panel-body">
<ul class="blog-types">
{% for blog_type in blog_types %}
<li><a href="{% url 'blogs_with_type' blog_type.pk %}">{{ blog_type.type_name }}</a>
</li>
{% empty %}
<li>暂无分类</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
修改blog.css如下:
ul.blog-types{
list-style-type: none;
}
div.blog:not(:last-child){ /*最后一个元素不设置成这个样式*/
margin-bottom: 2em;
padding-bottom: 1em;
border-bottom: 1px solid #eee;
}
div.blog h3{
margin-top: 0.5em;
}
div.blog p.blog.info{
margin-bottom: 0;
}
我们点击“随笔”这个分类,进入博客分类列表页面如下:
对于这个页面,我们引用刚刚blog_list.html的模板样式,只需要替换掉“博客列表”这一块,所以在blog_list.html的这里添加一行block块的代码,然后修改blogs_with_type.html如下:
<!-- C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\templates\blog\blogs_with_type.html -->
{% extends 'blog/blog_list.html' %}
{# 页面标题 #}
{% block title %}
{{ blog_type.type_name }}
{% endblock %}
{% block blog_list_title %}
分类:{{ blog_type.type_name }}(一共有{{ blogs | length}}篇博客)
{% endblock %}
刷新页面:
而右边的“博客分类”没有显示分类,因为我们处理方法里面对应的分类信息blogs_with_type方法少了这一块(而views.py中blog_list方法里面是有的),所以没有,我们打开views.py,修改如下:
然后再刷新页面:
接下来我们完善一下具体的博客页面,
打开blog_detail.html修改如下:
修改blog.css如下:
这节内容大概讲到这么些知识:主要是Bootstrap响应式布局、static/templates处理、命名空间(避免文件之间的冲突)、分类页面延用博客列表页面的样式