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

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

VS2019 开发Django(四)------models的更多相关文章

  1. VS2019 开发Django(二)------hello world!

    导航:VS2019开发Django系列 第一篇介绍了安装Django,那么,今天的主题内容是使用VS编写第一个Django应用. 1)新建Django Web项目 选择新建Django Web项目,在 ...

  2. VS2019 开发Django(十一)------表单

    导航:VS2019开发Django系列 今天是中华人民共和国成立70周年的日子,普天同庆,看阅兵看得满腔热血,热泪盈眶,祖国都这么优秀了,我要更加努力才行啊! 这个Django系列的文章,没有很深入的 ...

  3. VS2019 开发Django(八)------视图

    导航:VS2019开发Django系列 这几天学习了一下Django的视图和模板,从这几天的学习进度来看,视图这里并没有花很多的时间,相反的,模板花费了大量的时间,主要原因还是因为对Jquery操作d ...

  4. VS2019 开发Django(六)------Admin中图片上传

    导航:VS2019开发Django系列 该篇继续完善在Django的管理界面上传图片,因为LazyOrders小程序中菜单需要展示图片,而不是一个文本路径,所以我们还需要继续改造一下. 1)安装pil ...

  5. VS2019 开发Django(五)------createsuperuser

    导航:VS2019开发Django系列 上篇我们已经把LazyOrders中用到的C#的实体转成了Django中的Entity,并且已经迁移数据库成功,那么,今天继续介绍Django中内置的数据库操作 ...

  6. VS2019 开发Django(三)------连接MySQL

    导航:VS2019开发Django系列 下班回到家,洗漱完毕,夜已深.关于Django这个系列的博文,我心中的想法就是承接之前的微信小程序的内容,做一个服务端的管理中心,上新菜单,调整价格啊!之类的, ...

  7. VS2019 开发Django(一)------环境配置

    导航:VS2019开发Django系列 缘起:学习是我一直在做的一件事情,但是,可怕的是不知道学习什么,然后止步不前,安于现状,曾经很长的一段时间,我是不知道学习什么,工作上的事情,其实是相对固定的, ...

  8. VS2019 开发Django(十)------JavaScript与Django的数据交互

    导航:VS2019开发Django系列 这一篇介绍如何使用BootStrap Table这个组件来绑定渲染数据, 1)先来看一下BootStrap Table是怎么绑定数据的. 通过数据属性 给定da ...

  9. VS2019 开发Django(九)------内置模板和过滤器

    导航:VS2019开发Django系列 紧接上篇,继续介绍Django中的模板,考虑可能篇幅过长,所以分为两部分来讲,今天的主要内容: 1)内置模板和过滤器 母版,继承关系.头部导航和页脚,是需要与其 ...

随机推荐

  1. 4、Docker 镜像构建

    Docker 镜像构建 构建分为两种 手动构建 自动构建dockerfile 手动构建 首先启动一个Centos 容器,然后在容器中安装一个nginx [root@node ~]# docker ru ...

  2. C# partial 关键字分析

    简单的来说 partial是局部类型的意思 就是说有这个关键字的类.结构或接口可以写成几个部分 比如 public partial class Program { static void Main(s ...

  3. xmlhttp.readyState的值及解释

    xmlhttp.readyState的值及解释: 0:请求未初始化(还没有调用 open()). 1:请求已经建立,但是还没有发送(还没有调用 send()). 2:请求已发送,正在处理中(通常现在可 ...

  4. NFS介绍、服务端安装配置、NFS配置选项

    6月21日任务 14.1 NFS介绍14.2 NFS服务端安装配置14.3 NFS配置选项 14.1 NFS介绍 14.2 NFS服务端安装配置 1.首先需要2台机器,一台是服务端,一台是客户端,分别 ...

  5. 【网络流相关】最大流的Dinic算法实现

    Luogu P3376 于\(EK\)算法求最大流时每一次只求一条增广路,时间复杂度会比较高.尽管实际应用中表现比较优秀,但是有一些题目还是无法通过. 那么我们就会使用\(Dinic\)算法实现多路增 ...

  6. Flask 蓝图机制及应用

    我们都知道 flask 是一个轻量级的 web 框架,相对于其他同类型框架更为灵活.轻便.安全且容易上手.开发者可以随意编写自己想要的项目结构,同时还有很多的第三方库供君选择.但是灵活的同时也带来了相 ...

  7. bash中$符号的一般用法

    $一般用于获取变量的内容(字符串或数字等),用以构成命令version=$(uname -r).构成字符串echo "my name is $myname".进行算术运算等tota ...

  8. 地兵布阵 -----------HDU-1166

    C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于 ...

  9. 【Web技术】281- 滴滴开源小程序框架 Mpx2.0

    滴滴Mpx框架负责人@hiyuki,滴滴出行网约车webapp乘客团队的负责人,也是滴滴开源的小程序框架Mpx的负责人和核心作者 Mpx是一款致力于提高小程序开发体验和效率的增强型小程序框架,目前在滴 ...

  10. Jmeter介绍以及脚本制作与调试

    目录 Jmeter介绍 Jmeter安装 Jmeter主要测试组件 Jmeter元件作用域与执行顺序 Jmeter运行原理 Jmeter脚本制作 Jmeter脚本调试 Jmeter介绍 Jmeter ...