最新Django2.0.1線上教育零基礎到上線教程(四)5-完結
4-5 user modesl.py設計
迴圈引用:
設計app時每個app都有model
如圖:我們在user中定義usercourse記錄使用者學習的課程。會有兩個外來鍵:user和course。
我們就會import Courses.models
如果使用者對課程的評論:會放在 Courses.models
當中。評論我們需要儲存相應的使用者。
我們就會import User.models
迴圈import會出錯。a與b相互呼叫,造成等待。
解決迴圈引用: 分層設計
目前已有app:users courses organization
另外一個app高於這些app的層級。operation
上節中: 自定義userprofile
覆蓋預設user
表
user中還需要新增的(前提是這些功能比較獨立):
- EmailVerifyRecord - 郵箱驗證碼
- PageBanner - 輪播圖
觀察輪播圖:
- 圖片 2. 點選圖片地址 3. 輪播圖序號(控制前後)
users/models.py中新增程式碼:
from datetime import datetime
# 郵箱驗證碼model
class EmailVerifyRecord(models.Model):
SEND_CHOICES = (
("register" , u"註冊"),
("forget", u"找回密碼")
)
code = models.CharField(max_length=20, verbose_name=u"驗證碼")
# 未設定null = true blank = true 預設不可為空
email = models.EmailField(max_length=50, verbose_name=u"郵箱")
send_type = models.CharField(choices=SEND_CHOICES, max_length=10)
# 這裡的now得去掉(),不去掉會根據編譯時間。而不是根據例項化時間。
send_time = models.DateTimeField(default=datetime.now)
class Meta:
verbose_name = "郵箱驗證碼"
verbose_name_plural = verbose_name
# 輪播圖model
class Banner(models.Model):
title = models.CharField(max_length=100, verbose_name=u"標題")
image = models.ImageField(
upload_to="banner/%Y/%m",
verbose_name=u"輪播圖",
max_length=100)
url = models.URLField(max_length=200, verbose_name=u"訪問地址")
# 預設index很大靠後。想要靠前修改index值。
index = models.IntegerField(default=100, verbose_name=u"順序")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"輪播圖"
verbose_name_plural = verbose_name
從上往下: 第一塊區域import官方包,第二塊import第三方。(PEP8)
如下圖: 我們一共建立了三個資料表: Structure可以檢視到
與使用者相關的評論啊,點贊啊。學習的課程啊並沒有放進來,因為那些獨立性不高。
容易產生迴圈引用。我們把那些放到operation中。
本小節完成,對應commit:
Usermodel新增郵箱驗證碼,首頁輪播圖。對應4-5
4-6 course models.py編寫
點選 Tools 選單下 Run manage.py Task
startapp courses
course中需要那些表:
- 課程本身需要一張表
點進去之後點選開始學習。
課程基本資訊需要一張表, 章節表與課程表存在(一個課程對應多個章節)
- 章節表中:章節的名稱。 章節與視訊(一個章節對應多個視訊)
結構: 課程本身–(一對多)>章節-(一對多)->視訊資訊
資源下載放在課程裡面的。一個課程對應多個資源
共四張表:課程本身–(一對多)>章節-(一對多)->視訊資訊 & 資源表
courses/models.py:
from datetime import datetime
# 課程資訊表
class Course(models.Model):
DEGREE_CHOICES = (
("cj", u"初級"),
("zj", u"中級"),
("gj", u"高階")
)
name = models.CharField(max_length=50, verbose_name=u"課程名")
desc = models.CharField(max_length=300, verbose_name=u"課程描述")
# TextField允許我們不輸入長度。可以輸入到無限大。暫時定義為TextFiled,之後更新為富文字
detail = models.TextField(verbose_name=u"課程詳情")
degree = models.CharField(choices=DEGREE_CHOICES, max_length=2)
# 使用分鐘做後臺記錄(儲存最小單位)前臺轉換
learn_times = models.IntegerField(default=0, verbose_name=u"學習時長(分鐘數)")
# 儲存學習人數:點選開始學習才算
students = models.IntegerField(default=0, verbose_name=u"學習人數")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏人數")
image = models.ImageField(
upload_to="courses/%Y/%m",
verbose_name=u"封面圖",
max_length=100)
# 儲存點選量,點進頁面就算
click_nums = models.IntegerField(default=0, verbose_name=u"點選數")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"課程"
verbose_name_plural = verbose_name
下面來編寫章節 & 視訊 & 課程資源:courses/models.py
一對多, 多對一都可以使用django的外來鍵來完成。
# 章節
class Lesson(models.Model):
# 因為一個課程對應很多章節。所以在章節表中將課程設定為外來鍵。
# 作為一個欄位來讓我們可以知道這個章節對應那個課程
course = models.ForeignKey(Course, verbose_name=u"課程")
name = models.CharField(max_length=100, verbose_name=u"章節名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"章節"
verbose_name_plural = verbose_name
# 每章視訊
class Video(models.Model):
# 因為一個章節對應很多視訊。所以在視訊表中將章節設定為外來鍵。
# 作為一個欄位來儲存讓我們可以知道這個視訊對應哪個章節.
lesson = models.ForeignKey(Lesson, verbose_name=u"章節")
name = models.CharField(max_length=100, verbose_name=u"視訊名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"視訊"
verbose_name_plural = verbose_name
# 課程資源
class CourseResource(models.Model):
# 因為一個課程對應很多資源。所以在課程資源表中將課程設定為外來鍵。
# 作為一個欄位來讓我們可以知道這個資源對應那個課程
course = models.ForeignKey(Course, verbose_name=u"課程")
name = models.CharField(max_length=100, verbose_name=u"名稱")
# 這裡定義成檔案型別的field,後臺管理系統中會直接有上傳的按鈕。
# FileField也是一個字串型別,要指定最大長度。
download = models.FileField(
upload_to="course/resource/%Y/%m",
verbose_name=u"資原始檔",
max_length=100)
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"課程資源"
verbose_name_plural = verbose_name
通過Structure可以看到我們剛才設計的四張表
本小節完畢, 對應commit:
設計完成課程app中四張資料表: 課程,章節,視訊,資源。對應4-6
4-7 organization modesl.py設計
新建課程機構app:
點選Tools 選單下 Run manage.py Task
startapp organization
課程是屬於機構的, 機構有機構類別,城市等欄位。講師實體。
我要學習的提交表單會與使用者關聯,存放在機構。
其中課程數,學習人數可以動態統計。機構地址,機構經典課程。
機構講師,機構課程可以通過外來鍵獲取到, 不儲存到機構中。
講師大概所需要的欄位如圖所示。
organization/models.py 程式碼如下:
# encoding : utf-8
from datetime import datetime
from django.db import models
# Create your models here.
# 城市字典
class CityDict(models.Model):
name = models.CharField(max_length=20, verbose_name=u"城市")
# 城市描述:備用不一定展示出來
desc = models.CharField(max_length=200, verbose_name=u"描述")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"城市"
verbose_name_plural = verbose_name
# 課程機構
class CourseOrg(models.Model):
name = models.CharField(max_length=50, verbose_name=u"機構名稱")
# 機構描述,後面會替換為富文字展示
desc = models.TextField(verbose_name=u"機構描述")
click_nums = models.IntegerField(default=0, verbose_name=u"點選數")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏數")
image = models.ImageField(
upload_to="org/%Y/%m",
verbose_name=u"封面圖",
max_length=100)
address = models.CharField(max_length=150, verbose_name=u"機構地址")
# 一個城市可以有很多課程機構,通過將city設定外來鍵,變成課程機構的一個欄位
# 可以讓我們通過機構找到城市
city = models.ForeignKey(CityDict, verbose_name=u"所在城市")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"課程機構"
verbose_name_plural = verbose_name
# 講師
class Teacher(models.Model):
# 一個機構會有很多老師,所以我們在講師表新增外來鍵並把課程機構名稱儲存下來
# 可以使我們通過講師找到對應的機構
org = models.ForeignKey(CourseOrg, verbose_name=u"所屬機構")
name = models.CharField(max_length=50, verbose_name=u"教師名稱")
work_years = models.IntegerField(default=0, verbose_name=u"工作年限")
work_company = models.CharField(max_length=50, verbose_name=u"就職公司")
work_position = models.CharField(max_length=50, verbose_name=u"公司職位")
points = models.CharField(max_length=50, verbose_name=u"教學特點")
click_nums = models.IntegerField(default=0, verbose_name=u"點選數")
fav_nums = models.IntegerField(default=0, verbose_name=u"收藏數")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"教師"
verbose_name_plural = verbose_name
可以看到我們一共建立了三張表:分別是城市,課程機構,講師。
本小節對應commit:
課程機構app:城市,機構,講師表書寫完畢。對應4-7
4-8 operation models.py設計
分析需要那些表:
- 使用者可以提交我要學習的個人需求。
- 學員的課程評論資訊
- 收藏:可以收藏公開課, 授課講師, 授課機構, 使用者訊息提醒。
- 個人中心:我的課程說明使用者和課程之間的學習關係也需要儲存。
新建操作app:
點選Tools 選單下 Run manage.py Task
startapp operation
operation/models.py新增程式碼:
# encoding: utf-8
from datetime import datetime
# 引入我們CourseComments所需要的外來鍵models
from users.models import UserProfile
from courses.models import Course
# 使用者我要學習表單
class UserAsk(models.Model):
name = models.CharField(max_length=20, verbose_name=u"姓名")
mobile = models.CharField(max_length=11, verbose_name=u"手機")
course_name = models.CharField(max_length=50, verbose_name=u"課程名")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"使用者諮詢"
verbose_name_plural = verbose_name
# 使用者對於課程評論
class CourseComments(models.Model):
# 會涉及兩個外來鍵: 1. 使用者, 2. 課程。import進來
course = models.ForeignKey(Course, verbose_name=u"課程")
user = models.ForeignKey(UserProfile, verbose_name=u"使用者")
comments = models.CharField(max_length=250, verbose_name=u"評論")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"評論時間")
class Meta:
verbose_name = u"課程評論"
verbose_name_plural = verbose_name
# 使用者對於課程,機構,講師的收藏
class UserFavorite(models.Model):
# 會涉及四個外來鍵。使用者,課程,機構,講師import
TYPE_CHOICES = (
(1, u"課程"),
(2, u"課程機構"),
(3, u"講師")
)
user = models.ForeignKey(UserProfile, verbose_name=u"使用者")
# course = models.ForeignKey(Course, verbose_name=u"課程")
# teacher = models.ForeignKey()
# org = models.ForeignKey()
# fav_type =
# 機智版
# 直接儲存使用者的id.
fav_id = models.IntegerField(default=0)
# 表明收藏的是哪種型別。
fav_type = models.IntegerField(
choices=TYPE_CHOICES,
default=1,
verbose_name=u"收藏型別")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"評論時間")
class Meta:
verbose_name = u"使用者收藏"
verbose_name_plural = verbose_name
# 使用者訊息表
class UserMessage(models.Model):
# 因為我們的訊息有兩種:發給全員和發給某一個使用者。
# 所以如果使用外來鍵,每個訊息會對應要有使用者。很難實現全員訊息。
# 機智版 為0發給所有使用者,不為0就是發給使用者的id
user = models.IntegerField(default=0, verbose_name=u"接收使用者")
message = models.CharField(max_length=500, verbose_name=u"訊息內容")
# 是否已讀: 布林型別 BooleanField False未讀,True表示已讀
has_read = models.BooleanField(default=False, verbose_name=u"是否已讀")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"使用者訊息"
verbose_name_plural = verbose_name
# 使用者課程表
class UserCourse(models.Model):
# 會涉及兩個外來鍵: 1. 使用者, 2. 課程。import進來
course = models.ForeignKey(Course, verbose_name=u"課程")
user = models.ForeignKey(UserProfile, verbose_name=u"使用者")
add_time = models.DateTimeField(default=datetime.now, verbose_name=u"新增時間")
class Meta:
verbose_name = u"使用者課程"
verbose_name_plural = verbose_name
至此:我們的五張operation下的資料表models設計完成
setting中配置新增app
本小節對應commit:
operation下的models設計,使用者: 課程&訊息&收藏&評論&我要學習.並在setting中進行了註冊。對應4-8
4-9 資料表生成以及apps目錄建立
學習如何通過剛才設計的models生成資料庫對應的表
點選Tools 選單下 Run manage.py Task
:
Python2與Python3不同:
Python2下可能會報一些noASCII
錯誤:
只需要在對應你寫了中文的第一行加上:
# encoding: utf-8
Python3(django2.0.1)會報錯:
org = models.ForeignKey(CourseOrg, verbose_name=u"所屬機構")
TypeError: __init__() missing 1 required positional argument: 'on_delete'
這是因為在2.0.1中,外來鍵關係必須指明刪除時的操作。
比如:計程車都歸屬於計程車公司。如果計程車公司倒閉了,那這些汽車該怎麼處理。
必須自己指明: 我覺得可以直接進行級聯刪除。
django提供了:
CASCADE
PROTECT
SET_NULL
SET_DEFAULT
等選項。我選擇了CASCADE
刪除。
將(dajngo 2.0.1)專案中所有的外來鍵修改為如下面程式碼所示:
也就是添加了
on_delete=models.CASCADE
使其級聯刪除。
org = models.ForeignKey(CourseOrg, on_delete=models.CASCADE, verbose_name=u"所屬機構")
makemirgration & migrate生成表
makemirgration
migrate
上圖為makemirgration過程中輸出的資訊。可以看到我們做出的改動
此時我們檢視app目錄中migrations資料夾可以看到產生的新檔案。
operation/migrations/0001_initial.py:
可以看到裡面也是Python的語法。他會幫我們生成資料表。
以後每次migrations
時都會生成新的initial檔案。這是很重要的變動檔案,不能隨意刪除。
開啟Navicat可以看到django的資料庫中有它預設的django_migrations表
雙擊django_migrations表可以看到我們migration的記錄。
會記錄哪個app下的哪個initial.py已經運行了。
進入Navicat進行成功性驗證:
可以看到我們的表已經生成成功,命名規則為: app名稱 + 我們的類名變成小寫
把我們的四個app放到一個資料夾下。
- 新建Python的package: apps
- 把四個app都拖進apps中去。
去掉searchfor
的勾選。拖進去之後會報錯,說找不到那些import的模組了。
解決方案:右鍵Mark
為sourceRoot
。根目錄下找不到的,會去apps下搜尋。
但是這時候cmd下還是會報錯。
解決方案(圖來源於我的DjangoGetStarted
教程):
同理,插入第0是希望它先搜尋我們app下東西:
成功性驗證
可以看到Django已經可以正常run成功了。
第四章總結
- 我們設計了app
- 設計了user models.py
- 迴圈引用
得出我們需要建立一個更高層次的app。分層設計,operation在更高層。
- Courses models.py
- organization models.py
- operation models.py
通過makemigrations 生成表的變動 & migrate
每個app下的migration目錄的用途,和資料庫中django_migration
將所有app放到同一個目錄之下。
本章結束對應commit:
資料表全部生成,migration目錄&表django_migration。將app放到apps目錄。對應4-9.
第四章結束!撒花。