Model的字段解析和一对一关系实践

Django进阶,必须深刻了解Django的MTV模式。

M 代表模型(Model):负责业务对象和数据库的关系映射(ORM)。

T 代表模板 (Template):负责如何把页面展示给用户(html)。

V 代表视图(View):负责业务逻辑,并在适当时候调用Model和Template。

1. Django的字段概念解析

Model模型,负责对象和数据库的关系映射,所以Model本质是Python的数据类型,但它代表的是一个数据库的数据表。

数据库表格中有非常多的字段,例如char、varchar、date、datetime、text、int等,那在Model当中,也会有对应的类型,如:CharField、IntegerField、TextField;

以表格形式展示:

类型说明参数
CharField字符串类型max_length、null、blank
IntegerField整数类型int、null、blank
TextField文本类型text、null、blank
BooleanField布尔类型null、blank
EmailField带邮箱检测的字符串类型null、blank

当然还有一些本质和数据库类型是一样的,只是Django对他进行了很好的模拟,让开发者在使用的时候,可以更方便的写业务需求,而撇开本质上的数据类型纠结,如:ImageField、FileField、URLField,如下表格(还有很多):

类型说明参数
ImageField字符串类型upload_to*、height_field、width_field
FileField字符串类型upload_to*
IPAddressField字符串类型null、blank
URLField字符串类型null、blank

数据库里面有外键的一个设置,可供sql的联合查询,但是Django有更强大的一个逻辑查询,一对一、多对一、多对多的关系,下面一个表格介绍下Django 的关系字段:

类型关系说明
OneToOneField一对一直接关联,查询直接返回对象
ForeignKey多对一查询返回对象的列表集合
ManyToManyField多对多查询返回对象的列表集合

2. 博客项目的实践操作

Django自带的UserModel字段有账户、密码、邮箱、FirstName、LastName、用户权限、组、最后登陆时间、注册时间、活跃状态、超级管理员选项、管理员登陆状态这几项,当然这无法满足一些常见的业务需求,所以必须给User表进行一个拓展信息表....

3. 一对一关系的使用

设定一个一一对应的拓展信息表,使用字段是models.OneToOneField(),用来定义一对一关系。

简单理解,它与声明了 unique=True 的 ForeignKey 非常相似,不同的是使用反向关联的时候,得到的不是一个对象列表,而是一个单独的对象。

首先先来看最简单的一个拓展信息定义:

class UserProfile(models.Model):
   belong_to = models.OneToOneField(to=User, related_name='profile')
   address = models.CharField(max_length=500, default="you guess")

   def __str__(self):
       return 'username:'+self.belong_to.username+' address:'+self.address
  • 使用OneToOneField,里面至少需要一个参数,是指定关联的Model类(这里是User)

  • OneToOneField的第二个参数是反向查询的,如果没有,则无法通过User查询到它的拓展信息(加上还是好的)

  • address是额外辅助使用的,User表里面没这个字段

通过makemigrations和migrate后,将Model注册到admin中,从admin界面查看管理,首先是正常关联:

在User已经关联了UserProfile的情况下,再次关联,则会报错,如图:

这也是一一对应的一个特性,无法重复关联。

4. 逻辑上的错误和技术上的方案

当然这点也很容易报错,逻辑出错类型有以下几点:

  • 关联不存在,使用UserProfile查询belong_to或者User反向查询会报错

  • 已经关联,重复创建关联会报错

  • 如果User关联了UserProfile,而此时User注销后删除,UserProfile会出错

不过在OneToOneField定义的时候,也会考虑到这些问题,首先是解决第三个,User关联了UserProfile,这时删了User,UserProfile的关联对象失效,则UserProfile也会被删除,这是Django默认的级联删除。on_delete加不加无所谓,默认值就是None。

当on_delete为None时,Django默认会给on_delete赋值为models.CASCADE,绑定删除是执行级联删除的操作。

如下是一种不执行级联删除的操作,修改默认逻辑。如果User删除,对应的UserProfile改成Null,代码如下:

class UserProfile(models.Model):
   belong_to = models.OneToOneField(to=User, related_name='profile',on_delete=models.SET_NULL, null=True)
   address = models.CharField(max_length=500, default="you guess")

   def __str__(self):
       if self.belong_to:
           return 'username:'+self.belong_to.username+' address:'+self.address
       else:
           return 'address:'+self.address

允许设置NULL,就必须设置null=True。

另外两点,例如User存在,但是在没关联UserProfile使用profile属性是会报错的,这点的解决方案就是在新建User时,自动新建对应的UserProfile并关联。

5. 测试操作

测试结果很简单,登陆Admin界面,新建User、新建UserProfile、删除User,查看UserProfile的操作结果,如果是级联删除,UserProfile也会消失;

如果是设置为NULL,则在UserProfile的界面会出现一个叉叉的图标,点击会问你是否确定删除用户,如下图:

 

 

首发于《Crossin的编程教室》

 

 


以上就是本篇文章的全部介绍内容了


 

!放在最后

 

如果文章中有什么错误或者建议修改的地方,欢迎留言纠正和回复

 

如果你喜欢本篇文章,不妨关注一下我们的公众号,每周更新两篇原创技术文档,都是干货

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值