做一个官网需要多长时间

作者:小土豆
博客园:www.cnblogs.com/HouJiao/
掘金://juejin.cn/user/2436173500265335

1. 前言

最近在做一个官网,主页菜单栏六项,对应六个大的模块,每个模块的展示形式大致如下:

1.1 纯图片展示

一张主图横向铺满浏览器:

图片.png

1.2 表格展示

图片.png

1.3 图片+文字左右两列布局展示

第一种左右两列布局:

图片.png

第二种左右两列布局:

图片.png

1.4 图片+文字上下两行布局展示

图片.png

1.5 12宫格三行四列的图片展示

图片.png

1.6 瀑布流式的图片展示

图片.png

1.7 动态效果

除了上面的那些布局之外,还有一些鼠标悬浮的动态效果

1.8 新闻资讯模块

另外还有一个新闻资讯模块,可以查看新闻详情以及带分页功能的新闻列表。虽然没有详细讨论这个模块的具体内容,但是大概知道这个模块可能还需要一个简单的后台管理系统发布编辑文章。

2. 到底花了多长时间

当时看完设计稿就觉得这个官网的内容还是有点多的,因为很多布局都不太一样,而且还需要一个后台管理系统;最终经过一番思考,定下了3周的工作量(不包含周末)。

最终大体做完花了两周的时间,因为前期缺乏沟通出现UI返工问题,后面还完善了一些功能,所以又花了一周时间,整体也算按时交付。

那接下就这个项目中的一些样式功能的实现以及整个过程中出现的一些问题总结出来,希望能给大家一些参考。

3. 本文适合那些人阅读

  • 想学习CSS技能,但不知道从何下手的
  • 想简单复习一下CSS技能
  • 最近有意愿做官网项目的
  • 纯前端开发,有意向入门后端,希望能独立做一套完整但是又不复杂的前后端项目

4. 页面布局和一些CSS效果

做官网这种项目,主要考验一个人的CSS功底,那在这个项目完成的过程中都用到了那些CSS技巧呢?

  • 定位:相对定位、绝对定位
  • 弹性布局:Flex布局
  • 百分比布局
  • 文本溢出: 单行文本溢出、多行文本溢出
  • 鼠标悬浮显示遮罩:利用display和绝对定位

以上就是整个项目中用到的一些CSS技巧,接下来我们就来复习一下这些内容和一些相关的实践应用。

4.1 相对定位

元素设置相对定位以后仍然在文档流中占据着自己原来的位置,通过设置topbottomleftright,可以使元素相对于原来的位置进行移动,相对定位不会影响其他元素的布局。

图片.png

4.1.1 相对定位-应用1

在项目中,有下面这样的例子就是利用相对定位实现的。

图片.png

我们基础的布局是下面这样的:

<p class="logo">公司<br/>logo</p>  <!--这里实际是img元素 -->
<p class="name">公司<br/>X<br/>名称</p>

p.logo后期直接替换成img元素即可

正常情况下,上面的代码浏览器渲染结果如下(尺寸需要通过CSS设置):

图片.png

此时我们可以通过给p.name设置相对定位,并且设置其偏移量就可以实现最终的效果。

p.name{
    position: relative;
    left: 100px;
}

4.1.2 相对定位-应用2

图片.png

table中有一列数据为名称,我们需要在数据前面加上对应的logo

其实正常情况下,不对logo添加任何样式,显示出来是下面这样的效果:

图片.png

很明显的能看出来logo的位置并不是很合适:logo应该垂直居中,同时增加和文字的间距。

增加logo和文字之间的间距可以通过给logo设置padding-right或者margin-right来实现。

调整logo垂直居中一般会选择vertical-align,但是我们经常会发现vertical-algin的效果总是不尽人意,那这个时候相对定位就是非常好的选择。我们可以对logo设置相对定位,然后设置toplogo向下偏移。

.logo{
    positive: relative;
    top: 4px;
}

4.2 绝对定位

元素设置绝对定位以后,就会脱离正常文档流,原先在文档流中占据的位置会被删除,所以会影响它后面的元素。

图片.png

为绝对定位的元素设置偏移量后,绝对定位的元素的位置是相对于最近的已定位祖先元素,如果元素没有已定位的祖先元素,那么它的位置相对于最初的包含块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>

所以上面这段代码在浏览器的布局如下:

图片.png

如果我们给div.wrapper设置display:flex;div.wrapper就是一个Flex容器,它的子元素div.box都是Flex项目,而对应的布局会变成下面这样:

图片.png

Flex容器内部的Flex项目都会成为行内元素,水平依次排列且默认左对齐。

我们可以通过设置Flex容器justify-content控制Flex项目的水平对齐方式。

图片.png

有关更多Flex布局的内容可以点击这里

那接下来我们看看项目中的Flex布局应用。

4.3.1 弹性布局应用

项目中应用到了Flex布局的就是下面这个模块:

图片.png

该模块由六张不同尺寸的图片组成,并且六张图片拼接成了一张完整的大图。

刚开始看到这个设计的时候也没多想,后面真正做的时候才开始抠脚o(╥﹏╥)o。网上搜索了一下,这种布局大致可以称之为瀑布流式的布局

大概看了网上的一些方法,总觉得看的不是很明白(实际是因为一直持续在做页面布局,大脑有些反应不过来),于是自己就在琢磨怎样先把目前的这个需求给实现了。

于是脑子各种发散,刚开始尝试了浮动+相对定位,确实也实现了基本的布局。但是因为浮动导致父元素失去高度,后续有一个鼠标悬浮的特性无法实现,经过一些折腾没能解决就放弃了这种办法。

出现的问题为:浮动导致父元素高度塌陷,感兴趣的可以去了解一下~

之后经过一番咨询,得到了一个非常简单而支持自适应的方案,那就是Flex布局。那接下来就来掰掰我这个例子是怎么用Flex布局实现的。

我们整体的布局是下面这样的:

图片.png

首先我们将整个布局规整为三个div.box,并且给最外层的div.wrapper设置display:flex;

图片.png

对应的代码如下:

<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进行规整:

图片.png

对应的代码修改如下:

<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.wrapperFlex项目是三个div.boxdiv.box内部的子元素div.topdiv.bottom,它们的表现形式不会发生变化,依然是默认的块级元素展示形式,所以我们在div.box内部增加的div.topdiv.bottom各占父元素的一行。

最后在将div.topdiv.bottom分别拆分成两个div.imgbox,并且给div.topdiv.bottom设置display:flex

图片.png

对应的代码修改如下:

<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>

刷新页面,大致的效果就已经出来了:

图片.png

有没有瞬间觉得Flex布局真香~

接着就是按照设计稿简单调整一下间距就可以了。如果我们需要做自适应,那还需要给图片设置一个百分比:

.box img{
    width: 100%;
}

最终的自适应效果:

2.gif

弹性布局对于本应用有点曲线救国的感觉,它真正更强大的可应用的地方有更多,比如我们前面提到12宫格页面布局,就可以用Flex布局来实现,更多有关Flex布局的应用大家自行就探索吧~

4.4 百分比布局

假如我们有一个尺寸为1200*562的图片,如果不对图片设置的尺寸做任何限制,当浏览器的屏幕宽度小于1200px时,浏览器就会出现横向的滚动条:

图片.png

当屏幕宽度大于1200px时,浏览器左侧就会有空白:

图片.png

那如何让这张图片横向铺满整个浏览器,既不会在小尺寸的屏幕上出现滚动条,也不会在大尺寸的屏幕上出现留白呢?

百分比布局就可以帮我们轻松这个解决。

对于前面的那张图片,不管在什么在多大尺寸的浏览器中,我们为其设置一个百分比宽度,让其在当前尺寸的浏览器中横向铺满浏览器,不出现滚动条也不留白:

图片.png

这个时候,我们的图片就会适应各种尺寸的屏幕,不会出现滚动条,也不会留白:

4-.gif

如果对于其他元素我们也想实现这样的效果,就可以将其宽度设置为一个百分比数据,这样就能实现自适应的效果。

为元素设置百分比的宽度后,高度就不需要在进行设置了,高度会按照比例自行调节

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元素的宽度能够容纳这行文本,文本内容正常就在一行展示:

图片.png

此时p元素的width600px

如果p元素的宽度无法容纳这行文本,文本内容就会自动换行展示:

图片.png

此时p元素的width500px,而且没有设置元素的高度

那这个时候如果我们想让内容其单行显示,并且多余的内容使用······代替,要怎么实现呢?

其实也非常简单,三个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元素内的文本内容不换行:

图片.png

overflow: hidden;可以让溢出的部分隐藏起来:

图片.png

text-overflow: ellipsis;就可以设置用省略号显示溢出且未显示的那部分内容。

图片.png

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>

默认在浏览器中的展示结果:

图片.png

实现多行文本溢出最简单方法的就是用纯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元素设置这四个必要属性以后,我们来看看效果如何:

图片.png

咦,出现了意外状况,最后一行的文字似乎被截断了导致第四行的部分内容显示出来了。不要慌,这个时候我们将p元素的行高调整成35px就可以了:

图片.png

看到很多文章说-webkit-line-clamp属性是一个非标准属性,只适用于webkit内核的浏览器。但实际上我在FirefoxMicrosoft 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.targetdiv.mask;除此之外,我们还给子元素设置了宽高内边距字体颜色背景色这几个常规的样式属性。

所以上面的代码在浏览器中展示效果如下:

图片.png

那现在我们的目标就是:鼠标悬浮在div.target的时候显示div.mask

4.6.1 第一步

第一步我们先调整div.mask的位置:将其调整到div.target的位置,并且与之重合。

那这一步考察的就是CSS的定位,大致的思路就是:父元素div.wrapper设置相对定位,子元素div.mask设置绝对定位并且按照需要调整偏移量。

/* 省略前面给子元素设置的`宽高`、`内边距`、`字体颜色`和`背景色`这些样式属性 */
.wrapper{
    position: relative;
}
.mask{
    position: absolute;
    top:0px;
}

注意这里的样式省略了前面设置的一些基础属性,只将这一步新增的样式贴出来了。

之后浏览器查看:

图片.png

可以看到第一步已经完成了。

4.6.2 第二步

第二步就是隐藏div.mask:

/* 省略前面给子元素设置的`宽高`、`内边距`、`字体颜色`和`背景色`这些样式属性 */
.mask{
    position: absolute;
    top: 0px;
    display: none;
}

图片.png

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;
}

以上代码完成后,我们看看效果:

3-hover闪烁.gif

这个结果似乎是有了,但是却不尽人意,当我们在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框架:

图片.png

而且内部自带开发服务器、一个名为SQLite的轻量级数据库和一个后端管理系统django admin,安装和使用也比较简单,总体来说对一个前端开发者还是非常友好的。

介于本次官网的文章管理功能不是很复杂,UI上面也没有任何的要求,只需要实现两个基础的功能:登录文章的发布和编辑,所以就用Django框架实现后台管理系统

关于Django的安装和简单使用可以移步 官网 或者 菜鸟教程,那这里直接开始整理本次项目中使用Django的一些重要步骤。

5.1 创建项目

本地的pythondjango环境安装好以后,cmd命令行执行django-admin startproject 项目名称可以创建一个项目:

图片.png

项目创建成功后,进入项目根目录,在项目根目录执行django-admin startapp 模块名称可以创建细分的功能模块:

图片.png

使用django-admin startapp命令创建细分的功能模块后,一定要将该模块配置到settings.INSTALLED_APPS中:

   # 代码位置:/mySystem/mySystem/settings.py
   INSTALLED_APPS = [
        # ...省略部分代码
       'article'
   ]

接着在项目根路径下执行python manage.py runserver 8888就可以启动后端服务。命令执行以后,控制台如果打印如下信息,证明后端服务启动成功:

项目启动成功.png

后端服务启动成功以后,控制台的信息已经告诉我们该服务的地址为://127.0.0.1:8888,那我们在浏览器中访问这个URL就能看到django服务提供的默认页面:

图片.png

5.2 默认数据表生成

接着我们需要创建admin管理系统相关的默认数据表,即在项目根目录下执行python manage.py migrate:

图片.png

完成之后,浏览器中输入//127.0.0.1:8888/admin就可以访问django提供的admin管理系统

图片.png

进入admin管理系统是需要登录的,所以我们接下来我们要做的事就是为admin管理系统创建一个账号。

创建账号依然是在项目根路径下执行python manage.py createsuperuser,接着在命令行输入用户名邮箱密码确认密码,就可以成功创建出一个账号。

图片.png

之后我们就可以用这个账号登录django admin后台管理系统,以下是登录成功之后的页面:

图片.png

到这一步是有没有惊奇的发现后台管理系统的第一个功能登录已经完成了╰(°▽°)╯。

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_nameverbose_name_plural分别为字段数据表定义中文名称,所以后面我们看到的article数据表和表中的字段都会是中文的;如果不配置这两个属性,默认显示的是英文。

之后在项目根目录下分别执行python manage.py makemigrationspython manage.py migrate命令:

图片.png

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数据表了:

图片.png

数据表注册到admin中这一步是不能缺少的,否则admin管理系统是不会显示article这个数据表的

5.4 数据表定制

对于我们刚刚创建的article数据表,点击页面的+Add按钮,输入正文内容,点击右下角的SAVE按钮就可以新增一条文章:

图片.png

models.py中只定义了两个字段编号(a_id)正文内容(a_text),其中编号自增主键,所以我们在新增文章的时候,只需要填入正文内容即可。

点击ARTICLE或者文章,可以查看表中的数据:

图片.png

勾选列表中的复选框,点击动作右侧的下拉框,选择删除所选的文章就可以删除文章:

图片.png

点击文章的编号就能修改对应的文章内容:

图片.png

以上就是文章的操作,也是我们整个后台管理系统需要实现的第二个功能。

不过从以上的结果可以发现列表显示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

这个时候在刷新文章列表就能看到效果:

图片.png

另外一种方法就是在为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

最后我们看下效果文章列表:

图片.png

可以看到列表已经成功的显示了我们定义的内容。

5.4.2 中文配置

为了方便我们的操作,一般会将页面配置成中文模式的,那admin管理系统的中文模式也非常好实现,直接在settings.py文件中定义一个中间件即可:

MIDDLEWARE = [
    'django.middleware.locale.LocaleMiddleware'
]

代码位置在:/mySystem/mySystem/settings.py

配置完成以后,在刷新页面就能看到中文模式的admin管理系统。

图片.png

5.5 功能二次开发

数据表定制完成以后,你以为就结束了吗?no no no,前面我们实现的文章功能太简单了,只能以纯文本的形式编辑文章的正文内容,所以接下来我们就需要在这个基础上对文章的新增编辑功能做一个二次开发。

一般情况下,一篇文章包含的字段至少包含:文章标题文章作者发布时间正文内容文章封面等这些内容,而所以需要对文章的新增编辑进行二次开发;而文章的列表展示删除功能都是比较简单的操作,现有的功能已经可以满足。

从浏览器中我们可以看到新增文章页面url
//127.0.0.1:8888/admin/article/article/add/

图片.png

那么我们就可以自己配置一个路由为:/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:

图片.png

接着在templates目录下创建add.html

图片.png

我们在add.html中写入一些简单的内容:

<p>新增一些文章吧</p>

最后一步还需要在settings.py中对模板文件的位置进行配置:

import os # 新增
TEMPLATES = [
    {
        # 省略代码...
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        # 省略代码...
    },
]

代码位置:/mySystem/mySystem/settings.py

这个时候我们在刷新页面:

图片.png

我们会发现新增页面已经路由到了我们自定义的add.html,这个时候我们就可以在add.html中自由发挥了,比如新增表单控件、嵌入富文本编译器等等。

对于文章的编辑功能也是同样的方法,先找到编辑功能的完整URL://127.0.0.1:8888/admin/article/article/2/change/

图片.png

仔细分析这个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实现的项目,详细可以查看以下两篇文章:

《Vue结合Django-Rest-Frameword实现登录认证(一)》

《Vue结合Django-Rest-Frameword实现登录认证(二)》

6. 项目部署

项目部署也不是什么复杂的事情,只是在这一步也有一些需要注意的东西。

6.1 后端项目部署

对于后端项目,服务器也是需要提供pythondjango框架,安装教程这里就不说了,可自行在网上搜索。

但是需要注意的是,最好是先确定好服务器端的python版本和django版本,因为不同版本的django需要不同的python版本支持:

图片.png

Django 1.x使用python2的环境即可

这里解释一下为什么需要先确定服务器上的环境版本。
有些时候我们使用的服务器有可能已经存在python环境,如果是python2的环境,那django只能选择1.x的版本;
如果是python3的环境,那django版本的选择就没有什么限制;
还有大多时候服务器会并存python2python3,这个时候我们还是需要抉择用哪个python版本。

假如我们直接先在本地去搭建,就可能存在本地环境和服务器环境软件版本不一致的问题。

确定好服务器中软件的版本以后,我们本地搭建环境就和服务器保持一致,编写完功能以后就可以将本地整个目录代码拉到服务器中的某个目录下,后续也不会因为版本问题导致本地测试正常而服务器报错的问题。

本地代码拉到服务器上以后,在服务器项目根目录下执行python manage.py migrate,就能生成对应的数据表,并且还能将本地开发环境中生成的有关数据库的测试数据同步到服务器。

在同步本地开发环境中生成的有关数据库的测试数据之前,需确保本地生成了数据库初始化文件,生成该文件的方法前面已经说过,就不在赘述。

这些准备工作完成以后,如果是自己练习的项目,可以直接启动django内置的server即可,整个后端项目就算部署完成;如果是公司级别的项目,最好用在服务器中安装Apachemod_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 //127.0.0.1:8888/admin/; # 后端服务路径
    }
}

7.问题解决

7.1 部署样式出现问题

前端的功能本地开发好以后,就开始部署到服务器上,但是发现很多自定义的样式没有生效。但是浏览器查看元素会发现能看到我们自定义的样式,但是它的优先级比较低,被element-ui的样式给覆盖了。

这个问题最合适的解决方案就是将main.jselement的样式文件引入顺序放到App组件的前面:

import 'element-ui/lib/theme-chalk/index.css'
import App from './App'

7.2 hover闪烁问题

鼠标悬浮显示遮罩导致的hover闪烁问题前面我们已经做过总结,这里就不在重复,仅仅将这个问题列出来。

其实整个过程中也不止这两个问题,其他出现的问题在前面一些部分写到了注意事项中,所以这里就没有总结;还有一部分是当时出现问题的时候没有记录,现在回想不起来了o(╥﹏╥)o

8.结束

那到此整个项目就总结完了,没有什么特别复杂的地方,但是也有一部分内容让我学习到了新的技能。

当然整个过程中不止技术上的进步,更有血和泪的教训,所以后面一篇文章会对这次的项目做一个经验教训总结,所以下次见喽~

9. 写在最后

如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者

文章公众号首发,关注 不知名宝藏程序媛 第一时间获取最新的文章

笔芯❤️~