繼上篇我們匆匆遷移數據庫成功之后,又花了一個晚上研究了Django的模型,這里的模型其實就是ORM模型中的Entity,.Net里邊用的比較多的有Entity Framework,SqlSugar,Nhibernate等等
1)字段類型,直接查看上一篇,我們的模型生成的表結構,找一下映射關系。從下面的數據可以看出來,
①表名稱是我們的app名稱hello下划線model類名稱question
②未指定主鍵的時候,默認創建了自增長的id主鍵
③外鍵生成字段的規則是模型屬性_id,下面的Choice類中的外鍵question屬性生成的外鍵字段是question_id,那么我們外鍵屬性命名的時候,一般直接命名為你需要關聯的那個類名
④使用ForeignKey類型的時候,要傳遞你需要關聯的那個model為參數,並且一般主外鍵關系會設置級聯刪除
⑤從模型和表結構的對比可以知道CharField->varchar,DateTimeField->datetime,IntegerField->int,這里就不一一說明了,有編程經驗的同學一看也就明白了
⑥發現一個問題,Choice中的votes屬性指定了默認值,但是在MySql中生成字段的時候,並未生效,我百度了一下,別人也遇到了這個問題,現在我還沒有找到解決辦法,先存疑,找到解決辦法之后再更新
class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') def __str__(self): return self.question_text class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) def __str__(self): return self.choice_text
CREATE TABLE `hello_question` ( `id` int(11) NOT NULL AUTO_INCREMENT, `question_text` varchar(200) NOT NULL, `pub_date` datetime(6) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `hello_choice` ( `id` int(11) NOT NULL AUTO_INCREMENT, `choice_text` varchar(200) NOT NULL, `votes` int(11) NOT NULL, `question_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `hello_choice_question_id_8b790e13_fk_hello_question_id` (`question_id`), CONSTRAINT `hello_choice_question_id_8b790e13_fk_hello_question_id` FOREIGN KEY (`question_id`) REFERENCES `hello_question` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2)新建model,為我們之前開發的微信小程序中用到的C#實體在Django中添加model,先看Category類別與Menu菜單之間的關系:
/// <summary> /// 分類 /// </summary> public class Category { /// <summary> /// 主鍵ID /// </summary> public int CategoryId { get; set; } /// <summary> /// 分類 類別名 /// </summary> public string CategoryName { get; set; } /// <summary> /// 該類別下的菜單 /// </summary> public List<Menu> Menus { get; set; } } /// <summary> /// 菜單表 /// </summary> public class Menu { /// <summary> /// 菜單ID /// </summary> public int MenuId { get; set; } /// <summary> /// 類別ID /// </summary> public int CategoryId { get; set; } /// <summary> /// 菜單名 /// </summary> public string MenuName { get; set; } /// <summary> /// 對應的圖片路徑 /// </summary> public string ImgPath { get; set; } /// <summary> /// 單價 /// </summary> public decimal Price { get; set; } }
我們的Category類中會有多個Menu,但是每個Menu只屬於一個Category,這在關系型數據庫里邊叫做多對一關系,這種關系,在Django中怎么表示呢?其實就是一個外鍵關系,使用ForeignKey表示,另外就是我們的實體中有自己的主鍵,那么,自然不需要框架自動生成的那個id主鍵,我們可以使用primary_key來設置主鍵,使用AutoField來設置自增長,且看代碼:
#類別表 class Category(models.Model): category_id = models.AutoField(primary_key=True,verbose_name='類別ID') category_name = models.CharField(max_length=30,verbose_name='類別名') def __str__(self): return self.category_name class Meta: verbose_name_plural = '類別表' #菜單表 class Menu(models.Model): menu_id = models.AutoField(primary_key=True,verbose_name='菜單ID') category = models.ForeignKey(Category,on_delete=models.CASCADE) menu_name = models.CharField(max_length=50,verbose_name='菜單名') img_path = models.CharField(max_length=100,verbose_name='圖片路徑',default='') price = models.DecimalField(max_digits=5, decimal_places=2)
再看Carts與Orders與Menu的關系:
/// <summary> /// 購物車 /// </summary> public class Carts { /// <summary> /// 主鍵ID /// </summary> public int CartId { get; set; } /// <summary> /// 用戶ID /// </summary> public string OpenId { get; set; } /// <summary> /// 該用戶購物車中的清單 /// </summary> public int MenuId { get; set; } } /// <summary> /// 訂單 /// </summary> public class Orders { /// <summary> /// 訂單ID /// </summary> public int OrderId { get; set; } /// <summary> /// 用戶ID /// </summary> public string OpenId { get; set; } /// <summary> /// 該訂單包含的菜單 /// </summary> public List<Menu> Menus { get; set; } /// <summary> /// 支付狀態 /// </summary> public bool IsPaid { get; set; } /// <summary> /// 收貨地址 /// </summary> public string Address { get; set; } /// <summary> /// 下單時間 /// </summary> public DateTime OrderTime { get; set; } /// <summary> /// 支付時間 /// </summary> public DateTime PayTime { get; set; } /// <summary> /// 總計 /// </summary> public decimal TotalPrice { get { return this.Menus.Sum(x => x.Price); } } }
從之前的設計來看,其實Carts與Menu是一對一的關系,因為最終購物車的呈現是以OpenId為查詢條件來呈現的。而訂單就不一樣了,訂單是以OrderId為查詢條件來呈現的,一個訂單中可以存在多個菜單,一個菜單可以屬於多個訂單,這種關系是屬於多對多的關系,那么這種關系在關系型數據庫中是怎么表示呢?關系型數據庫中要表達這種關系,一定會用到一個橋表,來做關聯,那么,Django中怎么表示多對多的關系呢?是不是也要新建一個橋表的模型呢?答案是否定的!Django提供了一ManyToManyField的類型來滿足這種關系,且看代碼:
#購物車 class Carts(models.Model): cart_id = models.AutoField(primary_key=True,verbose_name='購物車ID') open_id = models.CharField(max_length=50,verbose_name='') menu = models.ForeignKey(Menu,on_delete=models.CASCADE,default=0) #訂單表 class Orders(models.Model): order_id = models.AutoField(primary_key=True) open_id = models.CharField(max_length=50,verbose_name='用戶ID') is_paid = models.BooleanField('是否已支付') address = models.CharField(max_length=100,verbose_name='收貨地址') order_time = models.DateTimeField(verbose_name='下單時間') pay_time = models.DateTimeField('支付時間') menus = models.ManyToManyField(Menu)
那么,我們到這里已經把模型建完了,剩下的就是遷移到數據庫中了,在項目文件上右鍵菜單,選擇Python,然后按K(Django進行遷移),然后再按M(Django遷移)等待完成。遷移成功之后,刷新我們數據庫中的表,有了!!!多對多關系,並且在多對多關系中,框架為我們自動創建了橋表。
3)總結
- 該篇主要介紹Django中的實體對應於數據庫的映射關系,換句話說就是介紹了Django內置的ORM模型
- 對比微信小程序中使用的C#實體,完成了Django中的實體映射,並執行了數據遷移。
今晚就到這里,待續......