實(shí)驗(yàn)三:數(shù)據(jù)庫(kù)系統(tǒng)開發(fā)

實(shí)驗(yàn)三:數(shù)據(jù)庫(kù)系統(tǒng)開發(fā)

一骚秦、實(shí)驗(yàn)?zāi)康募耙?/h3>

(一) 實(shí)驗(yàn)?zāi)康?/h4>

在熟練掌握MySQL基本命令她倘、SQL語(yǔ)言以及用C語(yǔ)言編寫MySQL操作程序的基礎(chǔ)上璧微,學(xué)習(xí)簡(jiǎn)單數(shù)據(jù)庫(kù)系統(tǒng)的設(shè)計(jì)方法,包括數(shù)據(jù)庫(kù)概要設(shè)計(jì)硬梁、邏輯設(shè)計(jì)前硫。

(二) 實(shí)驗(yàn)要求

  1. 該系統(tǒng)的E-R圖至少包括8個(gè)實(shí)體和7個(gè)聯(lián)系(必須有一對(duì)一聯(lián)系、一對(duì)多聯(lián)系荧止、多對(duì)多聯(lián)系)屹电。
  2. 在設(shè)計(jì)的關(guān)系中需要體現(xiàn)關(guān)系完整性約束:主鍵約束、外鍵約束跃巡,空值約束危号。
  3. 對(duì)幾個(gè)常用的查詢創(chuàng)建視圖、并且在數(shù)據(jù)庫(kù)中為常用的屬性(非主鍵)建立索引素邪。
  4. 該系統(tǒng)功能必須包括:插入外莲、刪除、連接查詢娘香、嵌套查詢苍狰、分組查詢。其中插入烘绽,刪除操作需體現(xiàn)關(guān)系表的完整性約束淋昭,例如插入空值、重復(fù)值時(shí)需給予提示或警告等安接。
  5. 加分項(xiàng):界面友好翔忽、包含事務(wù)管理、觸發(fā)器等功能盏檐。

二歇式、實(shí)驗(yàn)環(huán)境

  • 操作系統(tǒng):windows 10
  • 數(shù)據(jù)庫(kù):MySql 5.5.29
  • 高級(jí)語(yǔ)言:python 3.5
  • 網(wǎng)站設(shè)計(jì):django-1.8

三、實(shí)驗(yàn)內(nèi)容

這一部分的目錄如下:

  1. 用戶需求
  2. 概念設(shè)計(jì)
  3. 邏輯設(shè)計(jì)
  4. 觸發(fā)器和事務(wù)管理
  5. 具體實(shí)現(xiàn)(MySql)
  6. 界面設(shè)計(jì)(django)

(一) 用戶需求

這是一個(gè)關(guān)于音樂的數(shù)據(jù)庫(kù)[1]胡野。有以下需求

(1) 歌曲的屬性有:名稱材失、發(fā)布日期、時(shí)長(zhǎng)硫豆、風(fēng)格龙巨、演唱者、作詞人熊响、作曲人 旨别、所屬的專輯。
(2) 演唱者可以是歌手汗茄,也可以是組合秸弛。組合中的成員由歌手組成。歌手的屬性有:名字、性別递览、地區(qū)和所屬的唱片公司叼屠。組合的屬性有:名字、地區(qū)和所屬的唱片公司非迹。
(3) 專輯的屬性有:名字环鲤、發(fā)布日期和主打歌。
(4) 公司的屬性有:名字憎兽、建立時(shí)間和地區(qū)。
(5) 作詞人和作曲人的屬性有:姓名吵冒、性別纯命。

(二) 概念設(shè)計(jì)

1.演唱者

上述數(shù)據(jù)庫(kù)系統(tǒng)設(shè)計(jì)的主要困難在于,如何去處理演唱者痹栖。

為了解決這個(gè)問題亿汞,在已有的兩個(gè)實(shí)體——歌手(Singer)和組合(Band)的基礎(chǔ)上,增加了演唱者(Performer)這個(gè)實(shí)體揪阿。然后通過(guò)兩兩之間建立聯(lián)系集疗我,維持它們關(guān)系。如下圖

</img>

2.歌曲與演唱者南捂、作曲人及作詞人

如下圖吴裤,歌曲(Song)與演唱者(Performer)、作曲人(Composer)及作詞人(Lyricist)分別建立聯(lián)系集:SingSong溺健、LyricsBy麦牺、Compose。

</img>

3.演唱者與唱片公司及專輯

如下圖鞭缭,演唱者(Performer)與唱片公司(RecordCompany)和專輯(Album)分別建立聯(lián)系集:CreateAlbum剖膳、WorkOn。

4.歌曲與專輯

如下圖岭辣,歌曲與專輯建立兩個(gè)聯(lián)系集吱晒,分別為:AlbumMember、TitleSong沦童,以表示“歌曲屬于專輯”和“一個(gè)歌曲是專輯的主打歌”這兩個(gè)聯(lián)系仑濒。

</img>

5.總體ER圖

6.功能需求規(guī)格說(shuō)明

查詢數(shù)據(jù)

(1) 根據(jù)名稱查詢歌曲、演唱者搞动、專輯躏精、唱片公司;
(2) 查看歌曲的演唱者鹦肿、作詞人和作曲人矗烛;
(3) 查看演唱者所屬的唱片公司、演唱的所有歌曲和發(fā)布的專輯;
(4) 查看專輯中的所有的音樂和主打歌瞭吃;
(5) 查看一個(gè)唱片公司中所有的組合和歌手碌嘀;
(6) 根據(jù)風(fēng)格查詢歌曲。

插入數(shù)據(jù)

(1) 插入歌曲歪架、歌手或組合股冗、專輯、唱片公司和蚪、作詞人止状、作曲人;
(2) 插入歌曲時(shí)攒霹,選擇演唱者怯疤,選擇專輯,選擇作詞人和作曲人催束;
(3) 插入歌手或組合時(shí)集峦,選擇公司;
(4) 插入專輯時(shí)抠刺,選擇演唱者塔淤。

刪除數(shù)據(jù)

(1) 刪除歌曲、歌手或組合速妖、專輯高蜂、唱片公司、作詞人买优、作曲人妨马。

更改數(shù)據(jù)

(1) 更改以下實(shí)體集的屬性:歌曲、歌手或組合杀赢、專輯烘跺、唱片公司、作詞人脂崔、作曲人滤淳;
(2) 更改歌曲的演唱者、作詞人和作曲人及所屬專輯砌左,或改為空脖咐;
(3) 更改歌手或組合所屬的公司,或改為空汇歹;
(4) 更改專輯的演唱者屁擅,或改為空。

(三) 邏輯設(shè)計(jì)

1.模式的合并

上面ER圖中产弹,共包括8個(gè)實(shí)體和10個(gè)聯(lián)系派歌。

(1) 一對(duì)一聯(lián)系有:TitleSong, PerformBand, PerformSinger。
(2) 一對(duì)多聯(lián)系有:AlbumMember, CreateAlbum, WorkOn, LyricsBy, Compose。
(3) 多對(duì)多聯(lián)系有:BandMember胶果,SingSong匾嘱。

需要說(shuō)明的是

(1) 一個(gè)歌手可能存在多個(gè)組合中。這可能是因?yàn)橐恍└枋炙诮M合解散之后早抠,他們加入了另一個(gè)組合霎烙,或者是有一些組合為非商業(yè)性的,允許其成員加入另一個(gè)組合蕊连。因此悬垃,BandMember為多對(duì)多聯(lián)系。
(2) 一首歌曲甘苍,可能由兩人合唱盗忱,但是這兩人由不構(gòu)成一個(gè)組合。因此羊赵,SingSong為多對(duì)多聯(lián)系。

根據(jù)下面的合并規(guī)則

(1) 一對(duì)多的聯(lián)系扇谣,聯(lián)系集可以合并到“一”對(duì)應(yīng)的那個(gè)實(shí)體集的關(guān)系模式中昧捷;
(2) 一對(duì)一的聯(lián)系,聯(lián)系集可以合并到的任何一個(gè)實(shí)體集的關(guān)系模式中罐寨。

因此

(1) 將TitleSong合并到Album中靡挥;
(2) 將PerformBand合并到Band中;
(3) 將PerformSinger合并到Singer中鸯绿;
(4) 將AlbumMember合并到Song中跋破;
(5) 將CreateAlbum合并到Album中;
(6) 將WorkOn合并到Performer中瓶蝴;
(7) 將LyricsBy合并到Song毒返;
(8) 將Compose合并到Song。

2.將ER圖轉(zhuǎn)化為關(guān)系模式

實(shí)體集

  • Song(<u>id</u>, name, style, issue_date, duration, lyricist_id, composer_id, album_id)
  • Album(<u>id</u>, name, issue_date, title_song_id, performer_id)
  • Performer(<u>id</u>, company_id)
  • Band(<u>id</u>, name, region, performer_id)
  • Singer(<u>id</u>, name, gender, region, performer_id)
  • Company(<u>id</u>, name, region, established_time)
  • Lyricist(<u>id</u>, name, gender)
  • Composer(<u>id</u>,name, gender)

聯(lián)系集

  • SingSong(<u>song_id</u>, <u>performer_id</u>)
  • BandMember(<u>band_id</u>, <u>singer_id</u>)

注:上述關(guān)系模式中舷手,帶下劃線的屬性為主鍵拧簸,加粗的為非空屬性,斜體的為外鍵男窟。

3.視圖

視圖關(guān)系可以定義為包含查詢結(jié)果的關(guān)系盆赤。視圖是有用的,它可以隱藏不需要的屬性歉眷,可以把信息從多個(gè)關(guān)系收集到一個(gè)單一的視圖中牺六。

下面定義了一些視圖,在“具體實(shí)現(xiàn)”這一節(jié)中汗捡,我們將對(duì)它們進(jìn)行具體的實(shí)現(xiàn)

  • PerformerName:查詢演唱者的ID和名字(歌手或者組合的名字)淑际。

  • SongOfPerformer:查詢演唱者演唱的所有歌曲。

  • AlbumOfPerformer:查詢演唱者創(chuàng)作的所有專輯。

  • SingerInfor:查詢歌手的詳細(xì)信息庸追,包括所屬的唱片公司霍骄。

  • BandInfor:查詢組合的詳細(xì)信息,包括所屬的唱片公司淡溯。

  • SingerOfBand:查詢組合中所有的歌手读整。

  • SongInfor:查詢歌曲的詳細(xì)信息,包括作詞人和作曲人的名稱以及所屬專輯的名稱咱娶。

  • SongOfAlbum:查詢專輯中所有的歌曲米间。

  • AlbumInfor:查詢專輯的詳細(xì)信息,包括創(chuàng)作專輯的表演者和主打歌膘侮。

  • PerformerOfCompany:查詢公司和旗下的所有表演者屈糊。

4.索引

創(chuàng)建索引的目的

索引(index)是一種數(shù)據(jù)結(jié)構(gòu),它允許數(shù)據(jù)庫(kù)系統(tǒng)高級(jí)地找到關(guān)系中那些在索引屬性上給出定值的元祖琼了,而不用掃描關(guān)系中的所有元祖逻锐。

因此,在下面的關(guān)系模式的屬性上建立索引

  • Song.name
  • Album.name
  • Singer.name
  • Band.name

(四) 觸發(fā)器及事務(wù)管理

1.觸發(fā)器

根據(jù)以下定義

觸發(fā)器(trigger)是一條語(yǔ)句雕薪,當(dāng)對(duì)數(shù)據(jù)庫(kù)作修改時(shí)昧诱,它被自動(dòng)執(zhí)行。要設(shè)置觸發(fā)器機(jī)制所袁,必須滿足兩個(gè)要求:

  • 指明什么條件下執(zhí)行觸發(fā)器盏档。
  • 指明觸發(fā)器執(zhí)行時(shí)的動(dòng)作。

觸發(fā)器有很多適合的用途燥爷,但是在如下場(chǎng)合下蜈亩,不應(yīng)該使用觸發(fā)器。

  • 使用觸發(fā)器是替代級(jí)聯(lián)特性來(lái)實(shí)現(xiàn)外鍵約束的on delete cascade特性前翎。因?yàn)檫@樣不僅需要完成大量的工作量稚配,而且會(huì)使數(shù)據(jù)庫(kù)中的約束集合難以理解。
  • 使用觸發(fā)器來(lái)維護(hù)視圖鱼填。
  • 使用觸發(fā)器來(lái)復(fù)制和備份數(shù)據(jù)庫(kù)药有。

此外,使用觸發(fā)器時(shí)應(yīng)特別小心苹丸,因?yàn)檫\(yùn)行期間一個(gè)觸發(fā)器可以引發(fā)另一個(gè)觸發(fā)器愤惰。在最壞的情況下,一個(gè)觸發(fā)器錯(cuò)誤會(huì)導(dǎo)致一個(gè)無(wú)限的觸發(fā)鏈赘理。

定義如下觸發(fā)器

  • InsertPerformer
    • 觸發(fā)條件:在插入一個(gè)歌手或者一個(gè)組合之后宦言。
    • 動(dòng)作:在Perfromer表中插入一條數(shù)據(jù),然后將相應(yīng)的Performer.id作為這個(gè)歌手或者組合屬性performer_id的值商模。

2.事務(wù)管理

事務(wù)的定義如下[2]

事務(wù)(transaction)是訪問并可能更新各種數(shù)據(jù)項(xiàng)的一個(gè)程序執(zhí)行單元奠旺。

事務(wù)具有ACID特性:原子性蜘澜、一致性、隔離性响疚、持久性鄙信。

  • 原子性保證事務(wù)的所有映像在數(shù)據(jù)庫(kù)中要么全部反映出來(lái),要么根本不反映忿晕;一個(gè)故障不能讓數(shù)據(jù)庫(kù)處于事務(wù)部分執(zhí)行后的狀態(tài)装诡。
  • 一致性保證若數(shù)據(jù)庫(kù)一開始是一致的,則事務(wù)(單獨(dú))執(zhí)行后數(shù)據(jù)庫(kù)仍處于一致狀態(tài)践盼。
  • 隔離性保證并發(fā)執(zhí)行的事務(wù)是相互隔離鸦采,使得每個(gè)事務(wù)感覺不到系統(tǒng)中其他的事務(wù)的并發(fā)執(zhí)行。
  • 持久性保證一旦一個(gè)事務(wù)提交后咕幻,它對(duì)數(shù)據(jù)庫(kù)的改變不會(huì)丟失渔伯,既是系統(tǒng)可能出現(xiàn)故障。

事務(wù)管理的目的就是肄程,維護(hù)事物的ACID特性锣吼,分為并發(fā)控制和恢復(fù)系統(tǒng)。雖然這些顯得十分復(fù)雜蓝厌,但在界面設(shè)計(jì)那一節(jié)中吐限,我們將看到如何用簡(jiǎn)單的django語(yǔ)句實(shí)現(xiàn)簡(jiǎn)單的事務(wù)管理。

(五) 具體實(shí)現(xiàn)(MySql)

1.建表

以下為創(chuàng)建MySQL數(shù)據(jù)表的SQL通用語(yǔ)法:

CREATE TABLE table_name (column_name column_type);

在上一節(jié)中褂始,一共定義了10張數(shù)據(jù)表能扒。在附錄2中給出了創(chuàng)建它們的sql語(yǔ)句域那。

2.添加視圖

以下為創(chuàng)建視圖的SQL通用語(yǔ)法:

CREATE VIEW view_name AS + [查詢語(yǔ)句];

在上一節(jié)中,一共定義了10個(gè)視圖伞剑。在附錄3中給出了創(chuàng)建它們的sql語(yǔ)句舀寓。

3.添加觸發(fā)器

以下為創(chuàng)建觸發(fā)器的通用語(yǔ)法:

CREATE TRIGGER trigger_name 
AFTER/BEFORE 
INSERT/UPDATE/DELETE ON table_name
FOR EACH ROW
BEGIN
    sql語(yǔ)句
END;

因此胆数,使用如下sql語(yǔ)句創(chuàng)建兩個(gè)觸發(fā)器

create trigger InsertPerformer1
after 
insert on Singer
for each row
begin 
    insert into Performer values();
    set new.performer_id = (select max(id) from  Performer);
end;

create trigger InsertPerformer2
before 
insert on Band
for each row
begin 
    insert into Performer values();
    set new.performer_id = (select max(id) from  Performer);
end;

4.添加索引

創(chuàng)建索引的語(yǔ)法相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,如下

CREATE INDEX index_name on table_name(column_name);

因此互墓,使用如下語(yǔ)句創(chuàng)建4個(gè)索引

create index Song_name_index on Song(name);
create index Album_name_index on Album(name);
create index Singer_name_index on Singer(name);
create index Band_name_index on Band(name);

5.導(dǎo)出EER圖

下面的的EER圖(Enhanced Entity-Relationship Model)必尼,是使用MySQL Workbench導(dǎo)出的

(六) 界面設(shè)計(jì)(django)

需要說(shuō)明的是,這一節(jié)的大部分內(nèi)容已經(jīng)超出了實(shí)驗(yàn)的要求篡撵,但是為了以后參考的方便判莉,在這里總結(jié)以下django搭建網(wǎng)站的主要步驟。因此育谬,這部分更像一個(gè)關(guān)于django教程券盅。本次實(shí)驗(yàn)中所有的代碼都可以在https://github.com/1140310118/music_pool處獲取。以下大部分的內(nèi)容膛檀,參考自http://www.kancloud.cn/wizardforcel/django-chinese-docs-18/锰镀。

需要再次強(qiáng)調(diào)的是娘侍,本次實(shí)驗(yàn)使用的django版本是1.8。這是因?yàn)橛韭煌姹镜膁jango之間的存在一定的差異憾筏。

這一節(jié)的目錄如下

  1. 安裝django
  2. 創(chuàng)建項(xiàng)目mysite
  3. 創(chuàng)建應(yīng)用music_pool
  4. 將數(shù)據(jù)庫(kù)導(dǎo)出到 model.py 中
  5. 啟用網(wǎng)站管理
  6. 創(chuàng)建頁(yè)面
  7. 使用表單
  8. 簡(jiǎn)單的事務(wù)管理

1. 安裝django

在命令行中使用如下命令安裝django

pip install django==1.8

安裝結(jié)束,在命令行中輸入python花鹅。然后嘗試導(dǎo)入django

>>> import django
>>> django.get_version()
'1.8'

如果你使用的是Python3氧腰,那么安裝后可能存在關(guān)于數(shù)據(jù)庫(kù)的問題。

django 使用的MySQLdb連接數(shù)據(jù)庫(kù)翠胰,但是MySQLdb只支持Python2.容贝,還不支持python3。

因此之景,我們使用PyMySQL代替MySQLdb斤富。具體來(lái)說(shuō),在下面的文件中

[Python的路徑]\Lib\site-packages\django\db\backends\mysql\__init__.py 

添加如下語(yǔ)句

import pymysql 
pymysql.install_as_MySQLdb()

2. 創(chuàng)建項(xiàng)目mysite

在命令行中锻狗,使用cd命令進(jìn)入存儲(chǔ)你想存儲(chǔ)代碼的目錄满力,然后運(yùn)行以下命令

django-admin.py startproject mysite

于是,當(dāng)前目錄下建立了一個(gè)mysite目錄轻纪,結(jié)構(gòu)如下

mysite/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        wsgi.py

從外層的mysite目錄切換進(jìn)去油额,通過(guò)如下命令,我們就能運(yùn)行服務(wù)器

python manage.py runserver

http://127.0.0.1:8000/刻帚,我們將看到如下頁(yè)面

3. 編輯setting.py

在mysite/settings.py中保存Django項(xiàng)目的配置×仕唬現(xiàn)在通過(guò)編輯它,修改項(xiàng)目的配置崇众。

修改數(shù)據(jù)庫(kù)設(shè)置(DATABASES)為

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'music_pool',
        'USER': 'root',
        'HOST': '',
        'PORT': '3306',
        'PASSWORD':[你的密碼],
    }
}

修改完成之后掂僵,運(yùn)行如下命令,進(jìn)行數(shù)據(jù)庫(kù)的同步

python manage.py syncdb

運(yùn)行此命令后顷歌,命令行會(huì)提示是否創(chuàng)建管理員賬戶锰蓬,選擇是,因?yàn)檫@將會(huì)非常有用眯漩。

設(shè)置語(yǔ)言版本

LANGUAGE_CODE = 'zh-cn'

注:在1.9及以后的版本中芹扭,需要使用'zh-hans'。

更改時(shí)區(qū)(TIME_ZONE)

TIME_ZONE = 'Asia/Shanghai'

4. 創(chuàng)建應(yīng)用music_pool

使用如下命令赦抖,創(chuàng)建應(yīng)用

python manage.py startapp music_pool

這將創(chuàng)建一個(gè)music_pool目錄舱卡,如下

music_pool/
    __init__.py
    models.py
    tests.py
    views.py

為了激活這個(gè)應(yīng)用,我們編輯setting.py文件队萤,在INSTALLED_APPS設(shè)置中加入'music_pool'灼狰,結(jié)果如下

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'music_pool',
)

5. 將數(shù)據(jù)庫(kù)導(dǎo)出到 models.py 中

在music_pool/models.py中,我們可以創(chuàng)建按照如下的方式浮禾,創(chuàng)建模型

from django.db import models

class Company(models.Model):
    name = models.CharField(max_length=255)
    region = models.CharField(max_length=255)
    established_time = models.DateTimeField('date established')

class Performer(models.Model):
    company = models.ForeignKey(Company)

#...

然后在命令行中使用如下命令交胚,在數(shù)據(jù)庫(kù)中創(chuàng)建相應(yīng)的表

python manage.py syncdb

但是份汗,由于我們已經(jīng)在數(shù)據(jù)庫(kù)中創(chuàng)建了表,因此采取導(dǎo)入MySQL數(shù)據(jù)庫(kù)的辦法蝴簇。在命令行中杯活,使用如下語(yǔ)句

python manage.py inspectdb >music_pool/models.py

這樣,MySQL數(shù)據(jù)庫(kù)中的表就導(dǎo)出到models.py中熬词。比如在models.py建立了一個(gè)Album對(duì)象與數(shù)據(jù)庫(kù)中的Album表相對(duì)應(yīng)

class Album(models.Model):
    name = models.CharField(max_length=255)
    issue_date = models.DateField(blank=True, null=True)
    title_song = models.ForeignKey('Song', blank=True, null=True)
    performer = models.ForeignKey('Performer', blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'album'

manage.py = False 表明告訴Django不要管理此表的創(chuàng)建旁钧、修改和刪除。為了預(yù)防一些潛在的錯(cuò)誤互拾,建議注釋掉這一行歪今。這里需要注意的是

當(dāng)Django根據(jù)models.py中的模型創(chuàng)建數(shù)據(jù)庫(kù)中的表時(shí),會(huì)在未指明主鍵的情況下為每個(gè)模型分配一個(gè)id作為主鍵颜矿;每個(gè)模型中的外鍵屬性寄猩,在表中的名字會(huì)被附上"_id"。

因此骑疆,相應(yīng)地田篇,從數(shù)據(jù)庫(kù)中導(dǎo)數(shù)的models中的對(duì)象

  1. 不會(huì)有id屬性;
  2. 外鍵屬性中的"_id"也會(huì)被去掉箍铭。

因此泊柬,導(dǎo)出之后會(huì)存在一些錯(cuò)誤。如在Bandmember中

unique_together = (('band_id', 'singer_id'),)

我們改成

unique_together = (('band', 'singer'),)

這里的unique_together是為了解決django不支持多字段主鍵的問題诈火。

此外兽赁,在啟動(dòng)服務(wù)器還出現(xiàn)如下錯(cuò)誤

 HINT: Rename field 'Song.album', or add/change a related_name argument to the definition for field 'Album.title_song'.

因此,類Album進(jìn)行相應(yīng)的修改

title_song = models.ForeignKey('Song', blank=True, null=True, related_name='title_song')

修改完畢之后冷守,再次運(yùn)行 python manage.py syncdb 以同步據(jù)庫(kù)闸氮。

6. 啟用網(wǎng)站管理

Django 是在新聞編輯室環(huán)境下編寫的,“內(nèi)容發(fā)表者”和“公共”網(wǎng)站之間有 非常明顯的界線教沾。網(wǎng)站管理員使用這個(gè)系統(tǒng)來(lái)添加新聞、事件译断、體育成績(jī)等等授翻, 而這些內(nèi)容會(huì)在公共網(wǎng)站上顯示出來(lái)。Django 解決了為網(wǎng)站管理員創(chuàng)建統(tǒng)一 的管理界面用以編輯內(nèi)容的問題孙咪。

管理界面不是讓網(wǎng)站訪問者使用的堪唐。它是為網(wǎng)站管理員準(zhǔn)備的。

使用如下命令翎蹈,啟動(dòng)服務(wù)器

python manage.py runserver

使用瀏覽器淮菠,訪問http://127.0.0.1:8000/admin/。我們將看到如下的登錄界面

輸入在前面創(chuàng)建的用戶名和密碼荤堪,登錄進(jìn)去合陵。我們將看到

這些是一些可編輯的內(nèi)容枢赔,包括group,users 和 sites拥知。這些都是django默認(rèn)情況下自帶的核心功能踏拜。

下面,我們 Song 對(duì)象添加到這個(gè)頁(yè)面低剔。首先找到music_pool/admin.py速梗,如果沒有,那就創(chuàng)建一個(gè)襟齿。

music_pool/
    __init__.py
    models.py
    tests.py
    views.py
    admin.py

在admin.py文件中添加如下內(nèi)容:

from django.contrib import admin
from music_pool.models import Song
admin.site.register(Song)

重啟服務(wù)器姻锁,登錄管理員賬戶,我們將看到如下頁(yè)面

然后猜欺,我們就可以對(duì)Song對(duì)象進(jìn)行編輯了位隶!比如添加一條記錄。

7. 創(chuàng)建頁(yè)面

在這一步將創(chuàng)建一個(gè)頁(yè)面替梨,用來(lái)顯示所有的歌曲及其作詞人钓试、作曲人和所屬專輯。

在music_pool目錄下創(chuàng)建一個(gè)名為url.py的文件副瀑。

music_pool/
    __init__.py
    admin.py
    models.py
    tests.py
    urls.py
    views.py

在music_pool/url.py文件中添加以下內(nèi)容

from django.conf.urls import patterns, url
from music_pool import views

urlpatterns = patterns('',
    url(r'^$', views.all_song, name='songs')
)

接下來(lái)弓熏,在mysite/urls.py中添加一個(gè)include()方法,于是這個(gè)文件內(nèi)容變成下面的樣子

from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^music_pool/', include('music_pool.urls')),
    url(r'^admin/', include(admin.site.urls)),
)

URL部分的任務(wù)完成了糠睡,接下來(lái)挽鞠,我們需要編寫URL對(duì)應(yīng)的views.all_song這個(gè)方法了。

在music_pool/views.py文件中添加如下語(yǔ)句

from django.shortcuts import render
from music.models import Song

def all_song(request):
    song_list=Song.get_all()
    context = {'song_list': song_list}
    return render(request, 'music_pool/song_list.html', context)

在函數(shù)views.all_song狈孔,我們首先通過(guò)models.Song查詢得到了所有的歌曲信认,然后將參數(shù)傳遞給模板music/song_list.html。

首先均抽,我們來(lái)實(shí)現(xiàn)Song.get_all()這個(gè)函數(shù)嫁赏,編輯music_pool/models.py,在Song這個(gè)類下添加如下方法

@classmethod
def get_all(self):

    sql=""" select name, style, issue_date, duration, lyricist_name, composer_name, album_name  
            from `SongInfor`
        """
    song_list=Song.objects.raw(sql)
    return song_list

接下來(lái)油挥,我們添加模板music_pool/song_list.html潦蝇。在music_pool下創(chuàng)建一個(gè)templates目錄,在這個(gè)目錄下創(chuàng)建一個(gè)music_pool目錄深寥,并在其中創(chuàng)建一個(gè)song_list.html文件攘乒。于是,我們的模板文件的路徑應(yīng)該是mysite/music_pool/templates/music_pool/song_list.html惋鹅。

在song_list.html添加如下內(nèi)容

{% if song_list %}
    <ul>
    {% for song in song_list %}
        {{song.name}}&nbsp;
        {{song.style}}&nbsp;
        {{song.issue_date}}&nbsp;
        {{song.duration}}&nbsp;
        {{song.lyricist_name}}&nbsp;
        {{song.composer_name}}&nbsp;
        {{song.album_name}}
    {% endfor %}
    </ul>
{% else %}
    <p>No Song are available.</p>
{% endif %}

8. 使用表單

9. 簡(jiǎn)單的事務(wù)管理

下面實(shí)現(xiàn)了事務(wù)的原子性则酝。

from django.db import transaction

@transaction.atomic
def view_func(request):
    try:
        with transaction.atomic():
            # ...
    except IntegrityError:
        # ...

在比1.8更高的版本中,提供了更加高級(jí)的事務(wù)管理接口闰集。

四沽讹、實(shí)驗(yàn)體會(huì)

  1. 本次實(shí)驗(yàn)的主要任務(wù)是數(shù)據(jù)庫(kù)設(shè)計(jì)般卑,過(guò)分地將精力放在django上,實(shí)在不好妥泉,不好椭微。

附錄1 數(shù)據(jù)庫(kù)設(shè)計(jì)階段

  1. 刻畫用戶需求
  2. 概念設(shè)計(jì)
    • 構(gòu)建ER圖:實(shí)體、實(shí)體的屬性盲链、實(shí)體之間的聯(lián)系蝇率、實(shí)體和聯(lián)系上的約束
    • 明確功能需求:描述在數(shù)據(jù)上進(jìn)行的各類操作
  3. 邏輯設(shè)計(jì)
    • 將高層概念模式映射到將使用的數(shù)據(jù)庫(kù)系統(tǒng)的實(shí)現(xiàn)數(shù)據(jù)模型上,通常是將ER模型映射到關(guān)系模式刽沾。
  4. 物理設(shè)計(jì)
    • 指明數(shù)據(jù)庫(kù)的物理特征本慕,包括文件組織格式和索引結(jié)構(gòu)的選擇。

附錄2 MySQL-創(chuàng)建數(shù)據(jù)表

Create table Song(`id` int(8) not null auto_increment,
                    name varchar(255) not null,
                    style varchar(255),
                    issue_date date,
                    duration time,
                    lyricist_id int(8),
                    composer_id int(8),
                    album_id int (8),
                    primary key(`id`));

Create table Album(`id` int(8) not null auto_increment,
                    name varchar(255) not null,
                    issue_date date,
                    title_song_id int(8),
                    performer_id int(8),
                    primary key(`id`));

Create table Performer(`id` int(8) not null auto_increment,
                    company_id int(8),
                    primary key(`id`));

Create table Band(`id` int(8) not null auto_increment,
                    name varchar(255) not null,
                    region varchar(255),
                    performer_id int(8),
                    primary key(`id`));

Create table Singer(`id` int(8) not null auto_increment,
                    name varchar(255) not null,
                    gender varchar(255),
                    region varchar(255),
                    performer_id int(8),
                    primary key(`id`));

Create table Company(`id` int(8) not null auto_increment,
                    name varchar(255) not null,
                    region varchar(255),
                    established_time date,
                    primary key(`id`));

Create table Lyricist(`id` int(8) not null auto_increment,
                    name varchar(255) not null,
                    gender varchar(255),
                    primary key(`id`));

Create table Composer(`id` int(8) not null auto_increment,
                    name varchar(255) not null,
                    gender varchar(255),
                    primary key(`id`));

Create table SingSong(song_id int(8) not null,
                    performer_id int(8) not null,
                    primary key(song_id,performer_id));

Create table BandMember(band_id int(8) not null,
                    singer_id int(8) not null,
                    primary key(band_id,singer_id));

添加外鍵約束

alter table Song
    add constraint lyricsBy foreign key (lyricist_id)
    references Lyricist (`id`) 
    ON DELETE SET NULL 
    ON UPDATE SET NULL;

alter table Song
    add constraint Compose foreign key (composer_id)
    references Composer (`id`) 
    ON DELETE SET NULL 
    ON UPDATE SET NULL;

alter table Song
    add constraint album_member foreign key (album_id)
    references Album (`id`) 
    ON DELETE SET NULL 
    ON UPDATE SET NULL;

alter table Album
    add constraint title_song foreign key (title_song_id)
    references Song (`id`) 
    ON DELETE SET NULL 
    ON UPDATE SET NULL;

alter table Album
    add constraint create_album foreign key (performer_id)
    references Performer (`id`) 
    ON DELETE SET NULL 
    ON UPDATE SET NULL;

alter table Performer
    add constraint work_on foreign key (company_id)
    references Company (`id`) 
    ON DELETE SET NULL 
    ON UPDATE SET NULL;

alter table Band
    add constraint performer_band foreign key (performer_id)
    references Performer (`id`) 
    ON DELETE SET NULL 
    ON UPDATE SET NULL;

alter table Singer
    add constraint performer_Singer foreign key (performer_id)
    references Performer (`id`) 
    ON DELETE SET NULL 
    ON UPDATE SET NULL;

alter table SingSong
    add constraint sing_song foreign key (song_id)
    references Song (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE;

alter table SingSong
    add constraint song_performer foreign key (performer_id)
    references Performer (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE;

alter table BandMember
    add constraint bandmember_band foreign key (band_id)
    references Band (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE;

alter table BandMember
    add constraint bandmember_singer foreign key (singer_id)
    references Singer (`id`) 
    ON DELETE CASCADE 
    ON UPDATE CASCADE;

附錄3 MySQL-創(chuàng)建視圖

create view PerformerName as 
    select Performer.id as id, Band.name as band_name, Singer.name as singer_name
    from Performer left outer join Band on (Performer.id=Band.performer_id)
                   left outer join Singer on (Performer.id=Singer.performer_id); 

create view SongOfPerformer as 
    select SingSong.performer_id, SingSong.song_id, Song.name 
    from  SingSong join Song on (SingSong.song_id=Song.id);

create view AlbumOfPerformer as 
    select performer_id, id as album_id, name as album_name 
    from  Album;

create view SingerInfor as 
    select Singer.id, Singer.name, Singer.gender, Singer.region, Singer.performer_id, Company.name as company_name, Company.id as company_id 
    from  Singer join Performer on (Singer.performer_id=Performer.id)
                 left join Company on (Performer.company_id=Company.id); 

create view BandInfor as 
    select Band.id, Band.name, Band.region, Band.performer_id, Company.name as company_name, Company.id as company_id 
    from  Band join Performer on (Band.performer_id=Performer.id)
                 left join Company on (Performer.company_id=Company.id); 
                    
create view SingerOfBand as 
    select BandMember.band_id, Singer.performer_id as singer_performer_id, Singer.name as singer_name
    from  BandMember join Band on (Band.id=BandMember.band_id)
                     join Singer on (Singer.id=BandMember.singer_id); 

create view SongInfor as 
    select Song.id, Song.name, Song.style, Song.issue_date, Song.duration, 
           lyricist_id, Lyricist.name as lyricist_name, 
           composer_id, Composer.name as composer_name, 
           album_id, Album.name as album_name
    from  Song left outer join Album on (Song.album_id=Album.id)
               left outer join Composer on (Song.composer_id=Composer.id)
               left outer join Lyricist on (Song.lyricist_id=Lyricist.id);

create view SongOfAlbum as 
    select Song.id as song_id, Song.name as song_name, Song.album_id
    from  Song;

create view AlbumInfor as 
    select Album.id, Album.name, Album.issue_date, title_song_id, performer_id, Song.name as title_song_name
    from  Album join Song on (Album.title_song_id=Song.id);
    
create view PerformerOfCompany as 
    select Company.id as company_id, Company.name as company_name, Performer.id as performer_id
    from  Company join Performer on (Company.id=Performer.company_id);

參考文獻(xiàn)


  1. CSDN博客——(七)數(shù)據(jù)庫(kù)ER圖(二) 2017/5/25 http://blog.sina.com.cn/s/blog_68163d080100j6m6.html ?

  2. 數(shù)據(jù)庫(kù)系統(tǒng)概念 第6版侧漓。 ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锅尘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子布蔗,更是在濱河造成了極大的恐慌藤违,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件纵揍,死亡現(xiàn)場(chǎng)離奇詭異顿乒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)泽谨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門璧榄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人吧雹,你說(shuō)我怎么就攤上這事骨杂。” “怎么了雄卷?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵搓蚪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我丁鹉,道長(zhǎng)妒潭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任鳄炉,我火速辦了婚禮,結(jié)果婚禮上搜骡,老公的妹妹穿的比我還像新娘拂盯。我一直安慰自己,他們只是感情好记靡,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布谈竿。 她就那樣靜靜地躺著团驱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪空凸。 梳的紋絲不亂的頭發(fā)上嚎花,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音呀洲,去河邊找鬼紊选。 笑死,一個(gè)胖子當(dāng)著我的面吹牛道逗,可吹牛的內(nèi)容都是我干的兵罢。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼滓窍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼卖词!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起吏夯,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤此蜈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后噪生,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裆赵,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年杠园,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了顾瞪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抛蚁,死狀恐怖陈醒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瞧甩,我是刑警寧澤钉跷,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站肚逸,受9級(jí)特大地震影響爷辙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜朦促,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一膝晾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧务冕,春花似錦血当、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)落恼。三九已至,卻和暖如春离熏,著一層夾襖步出監(jiān)牢的瞬間佳谦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工滋戳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留钻蔑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓胧瓜,卻偏偏與公主長(zhǎng)得像矢棚,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子府喳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容