Django之Model操作之一对一外键(OneToOneField\ForeignKey)正反调用【ORM篇四】

上一篇:Django之Model常用操作之单表增删改查【ORM篇三】 点击跳转
目录篇:Django之model操作ORM目录篇 点击跳转
下一篇:Django之Model操作之一对多外键(ForeignKey)正反调用【ORM篇五】点击跳转

目录

  • 一对一两种实现方式
  • 1对1应用场景
  • 具体示例
  •      OneToOneField方式
  •      Foreginkey+Unique=True方式

一对一两种实现方式

和一对多都是通过外键字段调用
1对1:OneToOneField == ForeignKEY+唯一约束(推荐)

#假如User表有10个用户-----------UserDetail表id=1 和id=2的数据
用户1:通过user_profile字段选择关联UserDetail表id=1 该数据
用户2:通过user_profile字段选择关联UserDetail表id=2 该数据
用户3:创建不了该数据了,因为该字段是唯一代表不能重复
#所以称之1对1  不一定是1对1 当然用户可以少 最多就可以1多1

1对1应用场景

1.设计角度来说:
解决单表太大问题:一张表字段太多如:有100个 字段
假如你找第59个字段
我们查询就需要从左到右扫需要59次,从上扫到下直到你查询的目标的次数, 
如果拆分成2张表,一张50个字段      
我们查询就需要从左到右扫只需9次,    从上扫到下直到你查询的目标的次数, 
所以明显拆分以后效果的杠杆的
插:所以有人会设计表的时候都会尽量把字段为固定长度的往前面,因为扫描查找的时候是会根据你输入的长度进行扫描

2.业务角度来说:
在表设计过程中,我无意中觉得一对一关系觉得好没道理,直接放到一张表不就可以了吗?真是说,网上信息什么都有,也可以说与我一样困惑的有好多人。感谢大神在网上的活跃,我知道了一对一关系存在的必要性。
    1.首先就是这种关系出现的场景是什么样子,最好可以举个实际中的需求。
这样的场景有很多,比如:就拿最普通的用户信息来说,数据库中有一个表为user,一个表为user_auth.user表主要存放的字段为用户基本的信息(用户ID、真实姓名、昵称、真实头像、性别、职位、教育程度、专业、创建该用户的时间等),而在user_auth为验证表(用户ID、用户密码、邮箱、手机号等)。当涉及到一个具体实体的信息量较多,或者可以分类的时候,就可以使用了1-1,当然只要你能把一个实体的关系拆分成几个有归类的部分也可以适用。
    2.为什么要使用两个表来维护一对一关系,为什么不直接将两个表中的字段全都放在一张表里来展示?
如果都放在一张表里,一:不便于管理(包括查询执行速度),二:也就达不到关系型数据库的特性。三:可更好对业务进行事务隔离操作

    3.提出这种关系的目的是什么,就是为提高我们数据库查询条件吗?
目的:为第二问答案。这与数据库查询条件没有必然的说法。你说查询速度或者为了方便区分查询管理还说得过去。
还有公司和公司地址,总经理和公司,部门经理和部门 都是一对一
对于小字段小数据量的数据库来说,放到一起无所谓了,但是对于大字段的数据库,要添加删除修改某一个字段,由于数据库大,字段多,数据库找到这个字段耗时久,造成锁表等问题。同时分离存储大数据的表时,查询也会节省时间,因为某些框架会映射表里面所有的字段,存在一起查询时会把不需要的字段也映射进来造成耗时过久。还有,大数据量的表分离存储对于索引创建,读写分离,分割等操作都有优势。

具体示例

实战Django之Model操作之一对一外键正反调用 https://blog.csdn.net/Burgess_zheng/article/details/86592519

     OneToOneField方式

表类

  路径:project/app/models.py

from django.db import models
class A(models.Model):
     name = models.CharField(max_length=34)
class B(models.Model):
    name = models.CharField(max_length=34)
    a_key = models.OneToOneField("A", related_name='n' ,on_delete=models.CASCADE)

表数据

A表

B表

外键调用方式

路径:project/app/views.py

from app import models
def models_handle(request):
    A_obj = models.A.objects.filter()#获取全部或者匹配的列表形式
    A_obj = models.A.objects.all()#获取全部列表
    A_obj = models.A.objects.get(id=1)#一个queryset对象 #如果匹配不到,或者匹配的超出一个报错
    A_obj = models.A.objects.first() #获取该表第一个queryset对象
    B_obj = models.B.objects.first()

    #正向调取:(通过表内外键字段 “a_key”)
    B_obj.a_key.name   #得到结果:小红

    #反向调取:(通过外键字段related_name反向操作)
    A_obj.n.name      #得到结果:小强
       #插入:如果创建数据库表B表没有related_name该参数反向调取:(”B表名小写”)
       #A_obj.b.name  #得到结果:小强

     Foreginkey+Unique=True方式

表类

  路径:project/app/models.py

from django.db import models
class A(models.Model):
    name = models.CharField(max_length=34)
class B(models.Model):
    name = models.CharField(max_length=34)
    a_key = models.ForeignKey("A",unique=True,related_name='n',on_delete=models.CASCADE)

表数据

A表

B表

外键调用方式

路径:project/app/views.py

from app import models
def models_handle(request):
    A_obj = models.A.objects.filter()#获取全部或者匹配的列表形式
    A_obj = models.A.objects.all()#获取全部列表
    A_obj = models.A.objects.get(id=1)#一个queryset对象 #如果匹配不到,或者匹配的超出一个报错
    A_obj = models.A.objects.first() #获取该表第一个queryset对象
    B_obj = models.B.objects.first()

    #正向调取:(通过表内外键字段 “a_key”)
    B_obj.a_key.name   #得到结果:小红
    #反向调取:(通过外键字段related_name反向操作)
    A_obj.n.all()[0].name  #得到结果:小强
        #插入:如果创建数据库表B表没有related_name该参数反向调取:(”B表名小写” + “_set”)
        #A_obj.b_set.all()[0].name #得到结果:小强

上一篇:Django之Model常用操作之单表增删改查【ORM篇三】 点击跳转
目录篇:Django之model操作ORM目录篇 点击跳转
下一篇:Django之Model操作之一对多外键(ForeignKey)正反调用【ORM篇五】点击跳转

你可能感兴趣的:(Django)