profile模型分析
profile表和user表是一对一的关系,在互联网企业中,一般对于不断增长的这类数据,不使用外键进行关联,比如这里的user用户数据,.因为庞大的数据要进行分表分库处理,否则查询的效率很低,查询的速度很慢,导致数据的传输效率低下,会影响用户的体验,且耗费性能
在以前的项目中,两个一对一的表是采用外键关联,从表的主键在主表中作为外键,但是现在不采用外键关联的方式,自定义一种规则,采用将两个表的id设为同样的值来确定一对一的关系,这样就可以省略profile_id这一列,将两个表关联起来
这样的方法就没有采用物理外键的方式将两个表关联起来,而是使用逻辑外键的方式,减少了物理外键带来的性能开销
profile模型的创建
- 在user文件夹下的models .py文件下创建profile模型
class Profile(models.Model):
"""
location 目标城市
min_distance 最小查找范围
max_distance 最大查找范围
min_dating_age 最小交友年龄
max_dating_age 最大交友年龄
dating_sex 匹配的性别
auto_play 视频自动播放
user.profile.location
"""
location = models.CharField(max_length=16, choices=LOCATIONS, default='gz')
min_distance = models.IntegerField(default=0)
max_distance = models.IntegerField(default=10)
min_dating_age = models.IntegerField(default=18)
max_dating_age = models.IntegerField(default=81)
dating_sex = models.IntegerField(choices=SEXS, default=0)
auto_play = models.BooleanField(default=True)
class Meta:
db_table = 'profiles'
一般情况下,视频自动播放这个功能是存储在本地的,就比如抖音,可以根据用户自己设置视频是否自动播放,这些功能的需求一般都是产品经理和客户提出来的
- 数据迁移
python manage.py makemigrations
python manage.py migrate
- 关联查询
以往根据物理外键的关联,可以使用 user.profile.location 这种方式来访问 location,现在没有了物理外键的关联,还能使用这种方法吗?
其实也可以,前面提到过这个方法,使用装饰器
@property
def profile(self):
_profile, _ = Profile.objects.get_or_create(pk=self.id) # 获取或创建
# 逗号后面这个单独的下划线的作用是占位,下划线是一个标准的python的变量,而这个对应的变量不需要被使用,所以用下划线占位
return _profile
但是这样使用需要进行一些优化,每次访问,都需要进行一次数据库的查询,这样太过耗费性能
将_profile这个变量绑定在self的身上(可以联想将session绑定在request身上)
这里还要用到python中的一个内置函数 hasattr 查看该函数的作用
优化这段代码
@property
def profile(self):
if not hasattr(self, '_profile'):
self._profile, _ = Profile.objects.get_or_create(pk=self.id)
# 没有_profile,就去查找或者创建
# 有_profile,就直接返回
return self._profile
测试效果
没有通过物理外键的关联,通过self,逻辑外键也能实现关联查询,当然,修改也可以,物理外键的操作也都能通过这种关联实现