作者:小土豆
博客園:www.cnblogs.com/HouJiao/
掘金:https://juejin.cn/user/2436173500265335
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框架實現后台管理系統。
關於
Django的安裝和簡單使用可以移步 官網 或者 菜鳥教程,那這里直接開始整理本次項目中使用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實現的項目,詳細可以查看以下兩篇文章:
《Vue結合Django-Rest-Frameword實現登錄認證(一)》
《Vue結合Django-Rest-Frameword實現登錄認證(二)》
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.結束
那到此整個項目就總結完了,沒有什么特別復雜的地方,但是也有一部分內容讓我學習到了新的技能。
當然整個過程中不止技術上的進步,更有血和淚的教訓,所以后面一篇文章會對這次的項目做一個經驗教訓總結,所以下次見嘍~
9. 寫在最后
如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者
文章公眾號首發,關注 不知名寶藏程序媛 第一時間獲取最新的文章
筆芯❤️~
