zoukankan      html  css  js  c++  java
  • VS2019 开发Django(四)------models

    导航:VS2019开发Django系列

    继上篇我们匆匆迁移数据库成功之后,又花了一个晚上研究了Django的模型,这里的模型其实就是ORM模型中的Entity,.Net里边用的比较多的有Entity FrameworkSqlSugarNhibernate等等

    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中的实体映射,并执行了数据迁移。

    今晚就到这里,待续......

  • 相关阅读:
    《精通CSS:高级Web标准解决方案》系列(02):可视化格式模型
    《C#入门经典(第5版)》系列(10):定义类成员
    《C#入门经典(第5版)》系列(11):集合、比较和转换
    《锋利的jQuery》系列(01):jQuery选择器
    《C#入门经典(第5版)》系列(09):定义类
    C# 通过搜狐微博api远程更换壁纸
    C# 联网五子棋
    C# 新浪微博群发器
    C# seo测试小工具1:同时更新多网站的博客(csdn,cnblogs,163,sina)
    MS Ajax 客户端编程 学习笔记 (3)
  • 原文地址:https://www.cnblogs.com/dwBurning/p/Django4.html
Copyright © 2011-2022 走看看