1. 前言
最近在做一个官网,主页菜单栏
有六项
,对应六个大的模块,每个模块的展示形式大致如下:
1.1 纯图片展示
一张主图横向铺满浏览器:
1.2 表格展示
1.3 图片+文字左右两列布局展示
第一种左右两列布局:
第二种左右两列布局:
1.4 图片+文字上下两行布局展示
1.5 12宫格三行四列的图片展示
1.6 瀑布流式的图片展示
1.7 动态效果
除了上面的那些布局之外,还有一些鼠标悬浮的动态效果
。
1.8 新闻资讯模块
另外还有一个新闻资讯
模块,可以查看新闻详情
以及带分页
功能的新闻列表
。虽然没有详细讨论这个模块的具体内容,但是大概知道这个模块可能还需要一个简单的后台管理系统
去发布
、编辑
文章。
2. 到底花了多长时间
当时看完设计稿就觉得这个官网的内容还是有点多的,因为很多布局都不太一样,而且还需要一个后台管理系统
;最终经过一番思考,定下了3周
的工作量(不包含周末)。
最终大体做完花了两周的时间,因为前期缺乏沟通出现UI
返工问题,后面还完善了一些功能,所以又花了一周时间,整体也算按时交付。
那接下就这个项目中的一些样式
、功能
的实现以及整个过程中出现的一些问题总结出来,希望能给大家一些参考。
3. 本文适合那些人阅读
- 想学习CSS技能,但不知道从何下手的
- 想简单复习一下CSS技能
- 最近有意愿做官网项目的
- 纯前端开发,有意向入门后端,希望能独立做一套完整但是又不复杂的前后端项目
4. 页面布局和一些CSS效果
做官网这种项目,主要考验一个人的CSS
功底,那在这个项目完成的过程中都用到了那些CSS
技巧呢?
定位
:相对定位、绝对定位弹性布局
:Flex布局百分比布局
文本溢出
: 单行文本溢出、多行文本溢出鼠标悬浮显示遮罩
:利用display
和绝对定位
以上就是整个项目中用到的一些CSS
技巧,接下来我们就来复习一下这些内容和一些相关的实践应用。
4.1 相对定位
元素设置相对定位
以后仍然在文档流中占据着自己原来的位置,通过设置top
、bottom
、left
、right
,可以使元素相对于原来的位置进行移动,相对定位不会影响其他元素的布局。
4.1.1 相对定位-应用1
在项目中,有下面这样的例子就是利用相对定位
实现的。
我们基础的布局是下面这样的:
<p class="logo">公司<br/>logo</p> <!--这里实际是img元素 -->
<p class="name">公司<br/>X<br/>名称</p>
p.logo
后期直接替换成img
元素即可
正常情况下,上面的代码浏览器渲染结果如下(尺寸需要通过CSS
设置):
此时我们可以通过给p.name
设置相对定位,并且设置其偏移量
就可以实现最终的效果。
p.name{
position: relative;
left: 100px;
}
4.1.2 相对定位-应用2
table
中有一列数据为名称
,我们需要在数据前面加上对应的logo
。
其实正常情况下,不对logo
添加任何样式,显示出来是下面这样的效果:
很明显的能看出来logo
的位置并不是很合适:logo
应该垂直居中,同时增加和文字的间距。
增加logo
和文字之间的间距可以通过给logo
设置padding-right
或者margin-right
来实现。
调整logo
垂直居中一般会选择vertical-align
,但是我们经常会发现vertical-algin
的效果总是不尽人意,那这个时候相对定位
就是非常好的选择。我们可以对logo
设置相对定位,然后设置top
将logo
向下偏移。
.logo{
positive: relative;
top: 4px;
}
4.2 绝对定位
元素设置绝对定位以后,就会脱离正常文档流,原先在文档流中占据的位置会被删除,所以会影响它后面的元素。
为绝对定位的元素设置偏移量后,绝对定位的元素的位置是相对于最近的已定位祖先元素
,如果元素没有已定位的祖先元素,那么它的位置相对于最初的包含块html
元素。
已定位
指的是设置了position:relative;
或者position:absolute;
。其中块级元素
设置绝对定位
以后其内容将不再默认占满浏览器一整行,它的宽将由内容撑开。
在后面的内容中会有关于绝对定位
的具体应用。
4.3 弹性布局
Flex
布局也被称为是弹性布局
,通过给元素设置display:flex
来实现。
Webkit
内核的浏览器,必须加上-webkit
前缀,即display: -webkit-flex;
如果元素设置了display:flex
,那么该元素就被称为Flex容器
,该元素内的子元素
就被称为Flex项目
。
我们都知道,div
是块级元素
。
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
所以上面这段代码在浏览器的布局如下:
如果我们给div.wrapper
设置display:flex;
则div.wrapper
就是一个Flex容器
,它的子元素div.box
都是Flex项目
,而对应的布局会变成下面这样:
即Flex容器
内部的Flex项目
都会成为行内元素
,水平依次排列且默认左对齐。
我们可以通过设置Flex容器
的justify-content
控制Flex项目
的水平对齐方式。
有关更多
Flex
布局的内容可以点击这里
那接下来我们看看项目中的Flex布局
应用。
4.3.1 弹性布局应用
项目中应用到了Flex布局
的就是下面这个模块:
该模块由六张不同尺寸的图片组成,并且六张图片拼接成了一张完整的大图。
刚开始看到这个设计的时候也没多想,后面真正做的时候才开始抠脚o(╥﹏╥)o。网上搜索了一下,这种布局大致可以称之为瀑布流式的布局
。
大概看了网上的一些方法,总觉得看的不是很明白(实际是因为一直持续在做页面布局,大脑有些反应不过来),于是自己就在琢磨怎样先把目前的这个需求给实现了。
于是脑子各种发散,刚开始尝试了浮动+相对定位
,确实也实现了基本的布局。但是因为浮动导致父元素失去高度,后续有一个鼠标悬浮的特性无法实现,经过一些折腾没能解决就放弃了这种办法。
出现的问题为:
浮动导致父元素高度塌陷
,感兴趣的可以去了解一下~
之后经过一番咨询,得到了一个非常简单而支持自适应的方案,那就是Flex布局
。那接下来就来掰掰我这个例子是怎么用Flex布局
实现的。
我们整体的布局是下面这样的:
首先我们将整个布局规整为三个div.box
,并且给最外层的div.wrapper
设置display:flex;
:
对应的代码如下:
<div class="wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<style>
.wrapper{
display: -webkit-flex;
display: flex;
}
</style>
接着在对中间的div.box
进行规整:
对应的代码修改如下:
<div class="wrapper">
<div class="box"></div>
<div class="box">
<div class="top"></div>
<div class="bottom"></div>
</div>
<div class="box"></div>
</div>
<style>
.wrapper{
display: -webkit-flex;
display: flex;
}
</style>
我们的
Flex容器
为div.wrapper
,Flex项目
是三个div.box
,div.box
内部的子元素div.top
、div.bottom
,它们的表现形式不会发生变化,依然是默认的块级元素
展示形式,所以我们在div.box
内部增加的div.top
、div.bottom
各占父元素的一行。
最后在将div.top
、div.bottom
分别拆分成两个div.imgbox
,并且给div.top
和div.bottom
设置display:flex
:
对应的代码修改如下:
<div class="wrapper">
<div class="box"></div>
<div class="box">
<div class="top">
<div class="imgbox"></div>
<div class="imgbox"></div>
</div>
<div class="bottom">
<div class="imgbox"></div>
<div class="imgbox"></div>
</div>
</div>
<div class="box"></div>
</div>
<style>
.wrapper{
display: -webkit-flex;
display: flex;
}
.wrapper .box .top, .wrapper .box .bottom{
display: -webkit-flex;
display: flex;
}
</style>
那么此时整个页面的布局工作基本完成了。接下来,我们将对应的图片
引入:
<div class="wrapper">
<div class="box">
<img src='./1.png'/>
</div>
<div class="box">
<div class="top">
<div class="imgbox">
<img src='./3.png'/>
</div>
<div class="imgbox">
<img src='./4.png'/>
</div>
</div>
<div class="bottom">
<div class="imgbox">
<img src='./5.png'/>
</div>
<div class="imgbox">
<img src='./6.png'/>
</div>
</div>
</div>
<div class="box">
<img src='./2.png'/>
</div>
</div>
刷新页面,大致的效果就已经出来了:
有没有瞬间觉得Flex布局
真香~
接着就是按照设计稿简单调整一下间距就可以了。如果我们需要做自适应,那还需要给图片设置一个百分比:
.box img{
width: 100%;
}
最终的自适应效果:
弹性布局对于本应用有点曲线救国的感觉,它真正更强大的可应用的地方有更多,比如我们前面提到12宫格页面布局,就可以用Flex布局来实现,更多有关Flex布局的应用大家自行就探索吧~
4.4 百分比布局
假如我们有一个尺寸为1200*562
的图片,如果不对图片设置的尺寸做任何限制,当浏览器的屏幕宽度小于1200px
时,浏览器就会出现横向的滚动条:
当屏幕宽度大于1200px
时,浏览器
左侧就会有空白:
那如何让这张图片横向铺满整个浏览器,既不会在小尺寸的屏幕上出现滚动条,也不会在大尺寸的屏幕上出现留白呢?
百分比布局
就可以帮我们轻松这个解决。
对于前面的那张图片,不管在什么在多大尺寸的浏览器中,我们为其设置一个百分比宽度,让其在当前尺寸的浏览器中横向铺满浏览器,不出现滚动条也不留白:
这个时候,我们的图片就会适应各种尺寸的屏幕,不会出现滚动条,也不会留白:
如果对于其他元素我们也想实现这样的效果,就可以将其宽度设置为一个百分比数据,这样就能实现自适应的效果。
为元素设置百分比的宽度后,高度就不需要在进行设置了,高度会按照比例自行调节
4.5 文本溢出
在很久很久以前,做文本溢出的时候我都是采用字符串截取
然后在拼接······
的方式。后面一直没有去更新这方面的技能,傻傻的用了很久。直到这次get
到了实现文本溢出
的新技能,所以将内容总结如下。
4.5.1 单行文本溢出
我们有下面这样一段文本:
<p>Hello大家好,我是小土豆,关注"不知名宝藏程序媛"第一时间获取最新文章</p>
<style>
p{
padding: 10px;
border: 1px dashed rgb(100, 98, 98);
color: rgb(100, 98, 98);
}
</style>
如果p
元素的宽度
能够容纳这行文本,文本内容正常就在一行展示:
此时
p
元素的width
为600px
如果p
元素的宽度
无法容纳这行文本,文本内容就会自动换行展示:
此时
p
元素的width
为500px
,而且没有设置元素的高度
那这个时候如果我们想让内容其单行显示,并且多余的内容使用······
代替,要怎么实现呢?
其实也非常简单,三个CSS
属性就能轻松解决:
p{
padding: 10px;
border: 1px dashed rgb(100, 98, 98);
color: rgb(100, 98, 98);
width: 500px;
/* 以下便是解决单行文本溢出的三个CSS属性 */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
其中white-space
属性可以控制p
元素内的文本内容不换行:
overflow: hidden;
可以让溢出的部分隐藏起来:
text-overflow: ellipsis;
就可以设置用省略号
显示溢出且未显示的那部分内容。
4.5.2 多行文本溢出
下面有一段文本:
<p>Hello大家好,我是小土豆,关注"不知名宝藏程序媛"第一时间获取最新文章|Hello大家好,我是小土豆,关注"不知名宝藏程序媛"第一时间获取最新文章|Hello大家好,我是小土豆,关注"不知名宝藏程序媛"第一时间获取最新文章</p>
<style>
p{
padding: 10px;
border: 1px dashed rgb(100, 98, 98);
color: rgb(100, 98, 98);
width: 500px;
line-height: 30px;
}
</style>
默认在浏览器中的展示结果:
实现多行文本溢出
最简单方法的就是用纯CSS
来实现:
p{
padding: 10px;
border: 1px dashed rgb(100, 98, 98);
color: rgb(100, 98, 98);
width: 500px;
line-height: 30px;
/* 纯css实现多行文本溢出的四个必要属性 */
-webkit-line-clamp: 3;
display: -webkit-box;
-webkit-box-orient: vertical;
overflow : hidden;
}
其中-webkit-line-clamp
就是用来控制文本显示的行数
,设置为3
表示文本内容只显示3行
。
给p
元素设置这四个必要属性以后,我们来看看效果如何:
咦,出现了意外状况,最后一行的文字似乎被截断了导致第四行的部分内容显示出来了。不要慌,这个时候我们将p
元素的行高调整成35px
就可以了:
看到很多文章说
-webkit-line-clamp
属性是一个非标准属性,只适用于webkit
内核的浏览器。但实际上我在Firefox
和Microsoft Edge
中做了测试,发现是可以实现多行文本溢出
的效果;只有IE浏览器
不支持。(尤大都官宣Vue3将不再支持IE11了,所以暂且认为这个方案是成功的 O(∩_∩)O哈哈~)
当然实现文本溢出
的方法还有很多,这里只列出来了最简单便捷的方法,其他的方法大家感兴趣的可以自行研究~
4.6 鼠标悬浮显示遮罩
鼠标悬浮显示遮罩的实现方式一般都是在目标悬浮元素
的同级写一个隐藏的元素,然后通过:hover
让隐藏的元素显示出来。
隐藏元素一般都会采用
绝对定位
,所以这个例子也是前面绝对定位
的一个应用。
首先我们先写下面这样一段代码:
<div class="wrapper">
<div class="target">
div.target
</div>
<div class="mask">
div.mask
</div>
</div>
<style>
.target{
width: 120px;
height: 120px;
padding: 10px;
background-color: #ccc;
color: #fff;
}
.mask{
width: 120px;
height: 120px;
padding: 10px;
background-color: rgb(192, 53, 53);
color: #fff;
}
</style>
上面代码的内容非常简单,就一个父元素div.wrapper
包裹这两个同级子元素:div.target
和div.mask
;除此之外,我们还给子元素设置了宽高
、内边距
、字体颜色
和背景色
这几个常规的样式属性。
所以上面的代码在浏览器中展示效果如下:
那现在我们的目标就是:鼠标悬浮在div.target
的时候显示div.mask
。
4.6.1 第一步
第一步
我们先调整div.mask
的位置:将其调整到div.target
的位置,并且与之重合。
那这一步考察的就是CSS
的定位,大致的思路就是:父元素div.wrapper
设置相对定位
,子元素div.mask
设置绝对定位
并且按照需要调整偏移量。
/* 省略前面给子元素设置的`宽高`、`内边距`、`字体颜色`和`背景色`这些样式属性 */
.wrapper{
position: relative;
}
.mask{
position: absolute;
top:0px;
}
注意这里的样式省略了前面设置的一些基础属性,只将这一步新增的样式贴出来了。
之后浏览器查看:
可以看到第一步已经完成了。
4.6.2 第二步
第二步就是隐藏div.mask
:
/* 省略前面给子元素设置的`宽高`、`内边距`、`字体颜色`和`背景色`这些样式属性 */
.mask{
position: absolute;
top: 0px;
display: none;
}
4.6.3 第三步
第三步也是最后一步,就是实现:鼠标悬浮在div.target
元素上,让div.mask
显示。这个需求前半句好像比较好实现,就是为div.target
添加伪类:hover
,但是如何在div.target:hover
的时候让它的同级兄弟元素div.mask
显示呢?
那这个问题使用CSS
的相邻兄弟选择器(Adjacent sibling selector)
就能实现:
.target:hover + .mask{
display: inline-block;
}
以上代码完成后,我们看看效果:
这个结果似乎是有了,但是却不尽人意,当我们在div.target
元素上移动鼠标,div.mask
出现了闪烁。
这个问题说来刚开始也很困惑,不过因为时间的关系就没有在深入研究其原因,而是找了个别的办法规避了。 最近在做回顾的时候又思路了一番,大致猜测了一下原因:当鼠标悬浮在div.target
上的时候,div.mask
元素显示;当鼠标发生移动,鼠标监测当前悬浮在div.mask
元素上,那这个时候div.target:hover
就失效了,失效的结果就是div.mask
隐藏;当div.mask
隐藏以后,div.target:hover
又生效,div.mask
又显示出来了。在鼠标移动时,这个过程就在循环执行,所以就出现了div.mask
的闪烁。
后面就这个问题探索到了很多种解决方案,一 一给大家列出来。
第一个解决方案就是将目标hover
元素由div.target
改为它的父元素div.wrapper
。
因为我们的父元素
div.wrapper
是默认的块级元素,并且没有设置尺寸,因此它默认展一整行,所以div.wrapper:hover
的范围是一整行。所以第一个方案还需要对父元素的尺寸进行控制,可以直接给父元素设置宽度,或者为父元素设置属性display:inline-block;
.wrapper{
position: relative;
display: inline-block;
}
/* CSS选择器由“子元素选择器”变为“子元素选择器” */
.wrapper:hover > .mask{
display: inline-block;
}
其他样式代码不变
第二种方案是为div.mask
设置pointer-events: none;
,保持hover
依然定义在div.target
元素上。
.wrapper{
position: relative;
}
.mask{
/* 省略其余样式代码 */
pointer-events: none;
}
/* hover目标元素依然是div.target */
.target:hover + .mask{
display: inline-block;
}
5. Django和Django Admin
django
是一个python web
框架,它是一个和MVC
非常接近的MVT
框架:
而且内部自带开发服务器
、一个名为SQLite
的轻量级数据库和一个后端管理系统django admin
,安装和使用也比较简单,总体来说对一个前端开发者还是非常友好的。
介于本次官网的文章管理
功能不是很复杂,UI
上面也没有任何的要求,只需要实现两个基础的功能:登录
和文章的发布和编辑
,所以就用Django
框架实现后台管理系统
。
5.1 创建项目
本地的python
和django
环境安装好以后,cmd
命令行执行django-admin startproject 项目名称
可以创建一个项目:
项目创建成功后,进入项目根目录,在项目根目录执行django-admin startapp 模块名称
可以创建细分的功能模块:
使用
django-admin startapp
命令创建细分的功能模块后,一定要将该模块配置到settings.INSTALLED_APPS
中:# 代码位置:/mySystem/mySystem/settings.py INSTALLED_APPS = [ # ...省略部分代码 'article' ]
接着在项目根路径下执行python manage.py runserver 8888
就可以启动后端服务。命令执行以后,控制台如果打印如下信息,证明后端服务
启动成功:
后端服务
启动成功以后,控制台的信息已经告诉我们该服务的地址为:http://127.0.0.1:8888
,那我们在浏览器中访问这个URL
就能看到django
服务提供的默认页面:
5.2 默认数据表生成
接着我们需要创建admin管理系统
相关的默认数据表
,即在项目根目录下执行python manage.py migrate
:
完成之后,浏览器中输入http://127.0.0.1:8888/admin
就可以访问django
提供的admin管理系统
:
进入admin管理系统
是需要登录的,所以我们接下来我们要做的事就是为admin管理系统
创建一个账号。
创建账号
依然是在项目根路径下执行python manage.py createsuperuser
,接着在命令行输入用户名
、邮箱
、密码
和确认密码
,就可以成功创建出一个账号。
之后我们就可以用这个账号登录django admin后台管理系统
,以下是登录成功之后的页面:
到这一步是有没有惊奇的发现后台管理系统
的第一个功能登录
已经完成了╰(°▽°)╯。
5.3 数据表基础操作
第一个功能我们已经在不经意间完成了,那接下来就是文章
的发布
和编辑
了。
首先我们需要创建一张数据表
,在django
框架中,创建数据表
的第一步是创建一个models
类:
# *_*coding:utf-8 *_*
from django.db import models
# Create your models here.
class Article(models.Model):
a_id = models.AutoField(primary_key=True, verbose_name="编号") # 文章编号 主键 自动生成
a_text = models.TextField(verbose_name="正文内容") # 文章内容
class Meta:
verbose_name_plural='文章'
代码位置:
/mySystem/article/models.py
,使用djang-admin startapp
创建article
模块时会自动生成models.py
文件。
代码中的verbose_name
和verbose_name_plural
分别为字段
和数据表
定义中文名称
,所以后面我们看到的article
数据表和表中的字段
都会是中文的;如果不配置这两个属性,默认显示的是英文。
之后在项目根目录下分别执行python manage.py makemigrations
和python manage.py migrate
命令:
python manage.py makemigrations
会根据models.py
文件中定义的数据表
和字段
生成对应的数据表初始化文件,即/mySystem/article/migrations/0001_initial.py
;后者会根据生成的0001_initial.py
文件创建数据表
;如果后期表结构
发生变化,先修改models.py
,在重复执行这两个命令即可。
以上两个命令执行成功后,数据表
就已经创建出来了,接着我们还需要将这个数据表
注册到admin
中:
# *_*coding:utf-8 *_*
from django.contrib import admin
from article.models import Article
# Register your models here.
admin.site.register(Article)
代码位置在:
/mySystem/article/admin.py
,创建article
模块时会自动生成admin.py
。
这个时候我们在刷新页面就能看到我们刚刚创建的article
数据表了:
数据表
注册到admin
中这一步是不能缺少的,否则admin管理系统
是不会显示article
这个数据表的
5.4 数据表定制
对于我们刚刚创建的article
数据表,点击页面的+Add
按钮,输入正文内容
,点击右下角的SAVE
按钮就可以新增一条文章:
models.py
中只定义了两个字段编号(a_id)
和正文内容(a_text)
,其中编号
是自增主键
,所以我们在新增文章的时候,只需要填入正文内容
即可。
点击ARTICLE
或者文章
,可以查看表中的数据:
勾选列表中的复选框
,点击动作
右侧的下拉框,选择删除所选的文章
就可以删除文章:
点击文章的编号就能修改对应的文章内容:
以上就是文章的增
、删
、改
、查
操作,也是我们整个后台管理系统需要实现的第二个功能。
不过从以上的结果可以发现列表显示Article Object
而不是具体的数据,而且除了前面我们给数据表
和字段
设置的中文以外,其他的操作按钮均是英文的。
这个两个问题其实是admin管理系统
的默认显示,当然我们也可以对这些显示做一些定制。
5.4.1 列表展示具体字段
想让列表显示具体的字段,第一种方法就是为article
模型定义__str__
方法并返回想要显示的字段:
# *_*coding:utf-8 *_*
from django.db import models
# Create your models here.
class Article(models.Model):
a_id = models.AutoField(primary_key=True, verbose_name="编号") # 文章编号 主键 自动生成
a_text = models.TextField(verbose_name="正文内容") # 文章内容
class Meta:
verbose_name_plural='文章'
def __str__(self):
return self.a_text
这个时候在刷新文章列表
就能看到效果:
另外一种方法就是在为article
定义对应的ArtcileAdmin
类,并且在list_display
设置列表需要展示的字段即可,最后在将ArticleAdmin
注册到admin
中:
# *_*coding:utf-8 *_*
from django.contrib import admin
from article.models import Article
# 为article模型定义对应的ArtcileAdmin
class ArticleAdmin(admin.ModelAdmin):
list_display = ('a_id','a_text') # 设置列表需要展示的字段
# Register your models here.
admin.site.register(Article, ArticleAdmin) # 将ArticleAdmin也注册到admin中
代码位置在:
/mySystem/article/admin.py
最后我们看下效果文章列表:
可以看到列表
已经成功的显示了我们定义的内容。
5.4.2 中文配置
为了方便我们的操作,一般会将页面配置成中文模式的,那admin
管理系统的中文模式
也非常好实现,直接在settings.py
文件中定义一个中间件
即可:
MIDDLEWARE = [
'django.middleware.locale.LocaleMiddleware'
]
代码位置在:
/mySystem/mySystem/settings.py
配置完成以后,在刷新页面就能看到中文模式的admin管理系统。
5.5 功能二次开发
数据表定制完成以后,你以为就结束了吗?no no no,前面我们实现的文章功能太简单了,只能以纯文本的形式编辑文章的正文内容,所以接下来我们就需要在这个基础上对文章的新增
和编辑
功能做一个二次开发。
一般情况下,一篇文章包含的字段至少包含:
文章标题
、文章作者
、发布时间
、正文内容
、文章封面
等这些内容,而所以需要对文章的新增
和编辑
进行二次开发;而文章的列表展示
和删除功能
都是比较简单的操作,现有的功能已经可以满足。
从浏览器中我们可以看到新增文章
页面url
为http://127.0.0.1:8888/admin/article/article/add/
:
那么我们就可以自己配置一个路由为:/admin/article/article/add/
,然后编写对应的视图文件
和模板文件
。
首先我们需要在主路由
文件中配置路径:
from django.contrib import admin
from django.urls import path
from django.urls import include # 新增代码
import article
urlpatterns = [
path('admin/article/', include('article.urls')), # 新增代码
path('admin/', admin.site.urls),
]
代码位置:
/mySystem/mySystem/urls.py
,新增的代码在备注中有说明
该文件为整个项目的主路由文件,所有的请求url
都从这里开始分发,一般为了项目的模块化和更好的分工,会将不同模块的路由到对应模块的urls.py
文件中,
接着将后半部分路径配置到article
模块下的路由文件中:
from django.urls import path
from article import views
urlpatterns = [
path('article/add/', views.addArticle),
]
代码位置:
/mySystem/article/urls.py
然后我们编写对应的视图函数
:
from django.shortcuts import render
# Create your views here.
def addArticle(request):
return render(request, 'add.html', {})
代码位置:
/mySystem/article/views.py
视图文件中我们针对/admin/article/article/add/
请求渲染了一个模板文件add.html
,所以我们还需要创建对应的模板文件。
首先在/mySystem/article/
创建文件夹templates
:
接着在templates
目录下创建add.html
:
我们在add.html
中写入一些简单的内容:
<p>新增一些文章吧</p>
最后一步还需要在settings.py
中对模板文件的位置进行配置:
import os # 新增
TEMPLATES = [
{
# 省略代码...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
# 省略代码...
},
]
代码位置:
/mySystem/mySystem/settings.py
这个时候我们在刷新页面:
我们会发现新增页面已经路由到了我们自定义的add.html
,这个时候我们就可以在add.html
中自由发挥了,比如新增表单控件、嵌入富文本编译器等等。
对于文章的编辑功能也是同样的方法,先找到编辑功能的完整URL
:http://127.0.0.1:8888/admin/article/article/2/change/
。
仔细分析这个URL
会发现这个URL
中有一个参数是变化的,那就是文章的编号
,所以我们的路由
配置必须要用正则
才能进行匹配:
from django.urls import path, re_path
from article import views
urlpatterns = [
path('article/add/', views.addArticle),
re_path('article/(\d+)/change/', views.updateArticle), # 正则路径
]
代码位置在:
/mySystem/article/urls.py
需要注意的是,本地搭建的django
版本为3.x
,所以正则路由
是需要使用re_path
来配置;如果是django 1.x
版本,不管是普通路由
还是正则路由
,均可使用url
匹配即可,详细可参考官方文档
。
接下来就是为文章编辑
功能编写对应的视图函数
和模板文件
即可,这块同前面的新增功能,所以就不在多说了。
因为我们对新增
和编辑
功能进行二次开发,那同时还需要实现对应的提交保存数据库
逻辑。比如我们的文章新增
功能,在add.html
中新增表单后,需要有对应的提交
功能,这个提交
功能就是将用户填写的文章信息
提交并保存到数据库。那这个功能同样是先配置路由:
from django.urls import path, re_path
from article import views
urlpatterns = [
path('article/submitAdd', views.submitAdd) # 将文章内容保存到数据库
]
代码位置在:
/mySystem/article/urls.py
这里省略了前面配置的文章新增
和文章编辑
路由
然后在编写对应的视图函数submitAdd
。
以上两个步骤完成以后,前端在提交表单时的url
为:/admin/article/article/submitAdd
,用户填写好内容点击提交后,后端就会将数据保存到数据库中。
5.6 小结
那到这里整个后端功能就结束,大部分功能都我们借助了django admin
,同时对文章新增
和文章编辑
功能做了二次开发。
如果在整个项目中后端功能比较复杂且UI要求比较高,那我们可能就得自己从0开始实现一个后台管理系统
,对于后台管理系统
最基础且重要的功能就是登录功能
,关于这个功能我之前也有过总结,是用django+vue
实现的项目,详细可以查看以下两篇文章:
6. 项目部署
项目部署也不是什么复杂的事情,只是在这一步也有一些需要注意的东西。
6.1 后端项目部署
对于后端项目,服务器也是需要提供python
和django
框架,安装教程这里就不说了,可自行在网上搜索。
但是需要注意的是,最好是先确定好服务器
端的python
版本和django
版本,因为不同版本的django
需要不同的python
版本支持:
Django 1.x
使用python2
的环境即可
这里解释一下为什么需要先确定服务器上的环境版本。
有些时候我们使用的服务器
有可能已经存在python
环境,如果是python2
的环境,那django
只能选择1.x
的版本;
如果是python3
的环境,那django
版本的选择就没有什么限制;
还有大多时候服务器
会并存python2
和python3
,这个时候我们还是需要抉择用哪个python
版本。
假如我们直接先在本地去搭建,就可能存在本地环境和服务器环境软件版本不一致的问题。
确定好服务器中软件的版本以后,我们本地搭建环境就和服务器保持一致,编写完功能以后就可以将本地整个目录代码拉到服务器中的某个目录下,后续也不会因为版本问题导致本地测试正常而服务器报错的问题。
本地代码拉到服务器上以后,在服务器项目根目录下执行python manage.py migrate
,就能生成对应的数据表,并且还能将本地开发环境中生成的有关数据库的测试数据同步到服务器。
在同步本地开发环境中生成的有关数据库的测试数据之前,需确保本地生成了数据库初始化文件,生成该文件的方法前面已经说过,就不在赘述。
这些准备工作完成以后,如果是自己练习的项目,可以直接启动django
内置的server
即可,整个后端项目就算部署完成;如果是公司级别的项目,最好用在服务器中安装Apache
和mod_wsgi
来部署项目。
6.2 前端项目部署
前端部署项目非常简单,在服务器
安装nginx
即可,然后将编译打包后的代码源码上传至服务器
的某个位置,在修改nginx
的配置文件nginx.conf
:
server {
listen 80; # 通过那个端口访问前端网页
server_name localhost;
location / {
root /var/www/lr/; # 前端编译打包后的代码路径
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /admin/ { # 将以/admin/开头的请求转发到proxy_pass 配置的服务
proxy_pass http://127.0.0.1:8888/admin/; # 后端服务路径
}
}
7.问题解决
7.1 部署样式出现问题
前端的功能本地开发好以后,就开始部署到服务器上,但是发现很多自定义的样式没有生效。但是浏览器查看元素会发现能看到我们自定义的样式,但是它的优先级比较低,被element-ui
的样式给覆盖了。
这个问题最合适的解决方案就是将main.js
中element
的样式文件引入顺序放到App
组件的前面:
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
7.2 hover闪烁问题
鼠标悬浮显示遮罩导致的hover闪烁问题
前面我们已经做过总结,这里就不在重复,仅仅将这个问题列出来。
其实整个过程中也不止这两个问题,其他出现的问题在前面一些部分写到了注意事项中,所以这里就没有总结;还有一部分是当时出现问题的时候没有记录,现在回想不起来了o(╥﹏╥)o
8.结束
那到此整个项目就总结完了,没有什么特别复杂的地方,但是也有一部分内容让我学习到了新的技能。
当然整个过程中不止技术上的进步,更有血和泪的教训,所以后面一篇文章会对这次的项目做一个经验教训总结,所以下次见喽~
作者:小土豆biubiubiu
原文出处:https://www.cnblogs.com/HouJiao/p/14703511.html