數(shù)據(jù)庫與數(shù)據(jù)模型
django框架的設(shè)計也采用了MVC模式送朱,但是基于MVC模式卻更注重模型(Model)娘荡、模板(Template)、視圖(View)驶沼。通過編寫數(shù)據(jù)模型(Model)來完成對所有數(shù)據(jù)有關(guān)的事物炮沐,包括數(shù)據(jù)庫中數(shù)據(jù)的存取等操作。
數(shù)據(jù)庫
?Mysql回怜、SQLserver 2008大年、sqlite3 等數(shù)據(jù)庫都可以在 django 中使用,而默認(rèn)情況下玉雾,django 使用的是輕量級的sqlite3翔试,在項(xiàng)目配置文件中可以進(jìn)行數(shù)據(jù)庫配置
# fbckf/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
?而作為一個小型個人博客,使用 sqlite3 這個數(shù)據(jù)庫就已經(jīng)綽綽有余了复旬,所以不用去更改配置文件
博客數(shù)據(jù)
?博客主要是發(fā)布文章垦缅,文章中包含很多信息,比如標(biāo)題驹碍、作者壁涎、類別、評論等志秃,而類別和評論又包括了各自的信息粹庞。將數(shù)據(jù)分為以下兩部分,也就是洽损,我們將在數(shù)據(jù)庫中建立兩張表庞溜,每一部分中的信息就是各自表中的字段。
1.文章
標(biāo)題 | 作者 | 類別 | 內(nèi)容 | 摘要 | 創(chuàng)建時間 | 喜歡人數(shù) |
---|---|---|---|---|---|---|
《絕望》 | fbckf | 散文 | 絕望啊... | 絕望... | 2018-6-2 | 999+ |
《白云謠》 | 先秦詩人 | 詩詞 | 白云在天... | 白云在天... | 2018-6-8 | 9999+ |
2.類別
名稱 | 簡介 |
---|---|
散文 | 散文是一種抒發(fā)作者真情實(shí)感碑定、寫作方式靈活的記敘類文學(xué)體裁流码。 |
詩詞 | 詩詞,是指以古體詩延刘、近體詩和格律詞為代表的中國古代傳統(tǒng)詩歌漫试。 |
之所以要將類別和評論從文章中分離出來形成另的表格,是因?yàn)檫@樣可以避免數(shù)據(jù)庫中數(shù)據(jù)的重復(fù)存儲
數(shù)據(jù)庫模型
?之前所說過碘赖,需要在數(shù)據(jù)庫中創(chuàng)建三張表驾荣,用來存儲博客的各種數(shù)據(jù)普泡,創(chuàng)建的表就如之前所示的表格一樣播掷。一般情況下對數(shù)據(jù)庫的 SQL語句 不熟悉的話,在進(jìn)行數(shù)據(jù)庫操作時是比較頭疼的撼班,幸運(yùn)的是歧匈,django 已經(jīng)將 SQL語句 轉(zhuǎn)換成相對應(yīng)的 python 語言,只需要在 blog/models.py
中編寫相對應(yīng)的 python 代碼就好了砰嘁,其中類對應(yīng)數(shù)據(jù)庫中的表格件炉,類中的屬性則對應(yīng)數(shù)據(jù)庫中的字段
數(shù)據(jù)
編寫數(shù)據(jù)模型代碼
# blog/models.py
from django.db import models
# auth是django內(nèi)置的一個應(yīng)用
from django.contrib.auth.models import User
# 對應(yīng)數(shù)據(jù)庫中類別的表勘究,類名 Category 就是表的名稱
# 繼承了models.Model
class Category(models.Model):
# 屬性 name 是表中的名稱字段, name 是簡單的字符串所以使用CharField()類型
# max_length=20 表示該字段最長為20字符斟冕,unique=True 表示該字段具有的唯一性
name = models.CharField(max_length=20, unique=True)
# 屬性instructions 對應(yīng)簡介字段口糕,因?yàn)?instructions 是文本,所以使用TextField()類型
# default=“” 表示該字段默認(rèn)內(nèi)容為空
instructions = models.TextField(max_length=100, default="")
class Article(models.Model):
title = models.CharField(max_length=50, unique=True)
# 一個作者有多篇文章磕蛇,但是一篇文章只有一個作者走净,這是一對多的關(guān)系,所以使用 ForeignKey()類型
# ForeignKey() 將 注冊的用戶 User 和文章關(guān)聯(lián)起來
# on_delete=models.CASCADE 表示當(dāng)刪除該用戶時孤里,該用戶關(guān)聯(lián)的文章也會一并刪除
# null=True 表示允許為空 比如從別的平臺轉(zhuǎn)發(fā)文章
author = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
category = models.ForeignKey(Category, null=True, on_delete=models.CASCADE)
body = models.TextField()
abstract = models.TextField(max_length=50, default="")
# create_time 是時間伏伯,所以使用 DateTimeField()類型
# auto_now=True 表示自動添加該字段的值
create_time = models.DateTimeField(auto_now=True)
# PositiveIntegerField() 只允許正整數(shù)和0,因?yàn)閘ikes字段不為負(fù)數(shù)和小數(shù)捌袜,所以使用該類型
likes = models.PositiveIntegerField(default=0)
django 內(nèi)置的應(yīng)用 auth(django.contrib.auth)说搅,負(fù)責(zé)整個網(wǎng)站的用戶注冊、登陸等功能虏等,而 User 是該應(yīng)用中用戶的模型弄唧,就像 Category 類一樣,在這里導(dǎo)入后與文章關(guān)聯(lián)霍衫。
在編寫模型代碼時候引,需要根據(jù)字段的類型選擇對應(yīng)的字段類型函數(shù),常用的有字符串類型(CharField)敦跌、文本類型(TextField)澄干、日期類型(DateField、DateTimeField)柠傍、郵箱(EmailField)麸俘、整數(shù)類型(IntegerField)等。
article 與 category惧笛、author是一對多的關(guān)聯(lián)關(guān)系所以使用 ForeignKey()關(guān)聯(lián)類型从媚,多對多的關(guān)聯(lián)關(guān)系是 MangToManyFiled()。
評論建立另外一個應(yīng)用來完成患整。
數(shù)據(jù)庫遷移
?完成模型代碼編寫事情后還沒有結(jié)束拜效,那只是單純的寫好 python 代碼,就像只是寫策劃書各谚,還沒有真正去執(zhí)行紧憾,所以還需要告訴 django,根據(jù)編寫在models.py
中的代碼嘲碧,去執(zhí)行相應(yīng)的 SQL語句稻励。
$ python manage.py makemigrations
Migrations for 'blog':
blog/migrations/0001_initial.py
- Create model Article
- Create model Category
- Add field category to article
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying blog.0001_initial... OK
Applying sessions.0001_initial... OK
?執(zhí)行以上命令之后父阻,在查看一下項(xiàng)目的變化
$ tree fbckf
fbckf
├── blog
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ ├── 0001_initial.py
│ │ ├── __init__.py
│ │ └── __pycache__
│ │ ├── 0001_initial.cpython-35.pyc
│ │ └── __init__.cpython-35.pyc
│ ├── models.py
│ ├── __pycache__
│ │ ├── admin.cpython-35.pyc
│ │ ├── __init__.cpython-35.pyc
│ │ └── models.cpython-35.pyc
│ ├── tests.py
│ └── views.py
├── db.sqlite3
├── fbckf
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── settings.cpython-35.pyc
│ │ └── urls.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
在項(xiàng)目主目錄中生成了一個新的文件
db.sqlite3
這就是 django 根據(jù)模型創(chuàng)建的數(shù)據(jù)庫文件愈涩,博客的數(shù)據(jù)也將存儲在里面blog/migrations
中的生成了0001_initial.py
文件望抽,其中存放著 django 對數(shù)據(jù)庫的操作記錄,可以使用命令python manage.py sqlmigrate <應(yīng)用名稱> 0001
查看履婉。
$ python manage.py sqlmigrate blog 0001
BEGIN;
--
-- Create model Article
--
CREATE TABLE "blog_article" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(50) NOT NULL UNIQUE, "body" text NOT NULL, "abstract" text NOT NULL, "create_time" datetime NOT NULL, "likes" integer unsigned NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED);
--
-- Create model Category
--
CREATE TABLE "blog_category" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(20) NOT NULL UNIQUE, "instructions" text NOT NULL);
--
-- Add field category to article
--
ALTER TABLE "blog_article" RENAME TO "blog_article__old";
CREATE TABLE "blog_article" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(50) NOT NULL UNIQUE, "body" text NOT NULL, "abstract" text NOT NULL, "create_time" datetime NOT NULL, "likes" integer unsigned NOT NULL, "author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY DEFERRED, "category_id" integer NOT NULL REFERENCES "blog_category" ("id") DEFERRABLE INITIALLY DEFERRED);
INSERT INTO "blog_article" ("author_id", "body", "id", "create_time", "likes", "abstract", "category_id", "title") SELECT "author_id", "body", "id", "create_time", "likes", "abstract", NULL, "title" FROM "blog_article__old";
DROP TABLE "blog_article__old";
CREATE INDEX "blog_article_author_id_905add38" ON "blog_article" ("author_id");
CREATE INDEX "blog_article_category_id_7e38f15e" ON "blog_article" ("category_id");
COMMIT;
可以在輸出中看到詳細(xì)的 SQL語句
數(shù)據(jù)庫操作
?django提供了一個 shell煤篙,可以通過它來進(jìn)行數(shù)據(jù)庫的簡單操作
$ python manage.py shell
Python 3.5.2 (default, Sep 14 2017, 22:51:06)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from blog.models import Category, Article
>>> c = Category(name="古詩", instructions="古詩,是中國古代詩歌的一種體裁毁腿,又稱古體詩或古風(fēng)辑奈,指的是產(chǎn)生于唐代以前并和唐代新出現(xiàn)的近體詩(又名今體詩)相對的一種詩歌體裁")
>>> c.save()
>>> c
<Category: Category object (1)>
>>> c.name
'古詩'
>>> c.instructions
'古詩,是中國古代詩歌的一種體裁已烤,又稱古體詩或古風(fēng)鸠窗,指的是產(chǎn)生于唐代以前并和唐代新出現(xiàn)的近體詩(又名今體詩)相對的一種詩歌體裁'
>>>
從
blog
應(yīng)用的models.py
中導(dǎo)入Category
類,之后通過實(shí)例化一個對象胯究,并調(diào)用save()
方法保存稍计,這樣就已經(jīng)在數(shù)據(jù)庫中插入了一條數(shù)據(jù)save()
方法繼承自models.Model
實(shí)例化后 django 返回的是
<Category: Category object (1)>
這樣不利于觀察代碼的執(zhí)行情況,在每一個models.py
的類中寫一個__str__
用以返回對象的name
屬性
class Category(models.Model):
...
def __str__(self):
return self.name
$ python manage.py shell
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from blog.models import Category
>>> Category.objects.all()
<QuerySet [<Category: 古詩>]>
>>> c = Category.objects.get(name='古詩')
>>> c
<Category: 古詩>
>>>
因?yàn)槲恼骂愋枰P(guān)聯(lián)一個User
對象裕循,所以這里直接使用命令創(chuàng)建一個超級用戶臣嚣,也方便接下來的管理
$ python manage.py createsuperuser
Username (leave blank to use 'csx'): fbckf
Email address: m15220982078@163.com
Password:
Password (again):
Superuser created successfully.
leave blank to use 'csx'
是 django 檢測到當(dāng)前操作系統(tǒng)用戶名稱為 'csx' ,提示默認(rèn)使用 'csx' 作為超級用戶名稱之后郵箱和密碼剥哑,密碼的強(qiáng)度比較嚴(yán)格硅则,所以要好好記住自己設(shè)置的密碼
$ python manage.py shell
>>> from django.utils import timezone
>>> from django.contrib.auth.models import User
>>> from blog.models import Category, Article
>>> auth = User.objects.get(username='fbckf')
>>> c = Category.objects.get(name='古詩')
>>> article = Article(title='白云謠', author=auth, category=c, body='白云在天,丘陵自出株婴。道里悠遠(yuǎn)怎虫, 山川間之。將子無死困介,尚復(fù)能來揪垄。', abstract='白云在天,丘陵自出逻翁。', create_time=timezone.now(), likes=0)
>>> article.save()
>>> article.title
'白云謠'
>>> article.author
<User: fbckf>
>>> article.body
'白云在天饥努,丘陵自出。道里悠遠(yuǎn)八回,山川間之酷愧。將子無死,尚復(fù)能來缠诅。'
>>>
調(diào)用 django 內(nèi)置模塊
timezone
的now()
方法指定時間使用
get()
方法溶浴,指定取出用戶 'fbckf' 和類別 '古詩'實(shí)例化一個 article 對象并保存
delete()
方法用于刪除數(shù)據(jù)
總結(jié)
? 簡單來說,整一個博客應(yīng)用的編寫就是圍繞著對數(shù)據(jù)的操作進(jìn)行的管引,數(shù)據(jù)的重要性不言而喻士败。也因此,數(shù)據(jù)庫的操作也顯的尤為重要,而 django 將SQL語句都封裝起來谅将,就使得可以通過編寫 python 代碼來進(jìn)行數(shù)據(jù)庫操作漾狼,這就意味著即使不懂 SQL語句 也可以使用數(shù)據(jù)庫,極大的降低了 django 的使用門檻(當(dāng)然 SQL語句 也是很重的)