Django的懒加载是什么(2023年最新解答)

导读:本篇文章首席CTO笔记来给大家介绍有关Django的懒加载是什么的相关内容,希望对大家有所帮助,一起来看看吧。

Django源码阅读 (一) 项目的生成与启动

诚实的说,直到目前为止,我并不欣赏django。在我的认知它并不是多么精巧的设计。只是由功能堆积起来的\"成熟方案\"。但每一样东西的崛起都是时代的选择。无论你多么不喜欢,但它被需要。希望有一天,python能有更多更丰富的成熟方案,且不再被诟病性能和可维护性。(屁话结束)

取其精华去其糟粕,django的优点是方便,我们这次源码阅读的目的是探究其方便的本质。计划上本次源码阅读不会精细到每一处,而是大体以功能为单位进行解读。

django-admin startproject HelloWorld 即可生成django项目,命令行是exe格式的。

manage.py 把参数交给命令行解析。

execute_from_command_line() 通过命令行参数,创建一个管理类。然后运行他的 execute() 。

如果设置了reload,将会在启动前先 check_errors 。

check_errors() 是个闭包,所以上文结尾是 (django.setup)() 。

直接看最后一句 settings.INSTALLED_APPS 。从settings中抓取app

注意,这个settings还不是我们项目中的settings.py。而是一个对象,位于 django\\conf\\__init__.py

这是个Settings类的懒加载封装类,直到 __getattr__ 取值时才开始初始化。然后从Settings类的实例中取值。且会讲该值赋值到自己的 __dict__ 上(下次会直接在自己身上找到,因为 __getattr__ 优先级较低)

为了方便debug,我们直接写个run.py。不用命令行的方式。

项目下建个run.py,模拟runserver命令

debug抓一下setting_module

回到 setup() 中的最后一句 apps.populate(settings.INSTALLED_APPS)

开始看 apps.populate()

首先看这段

这些App最后都会封装成为AppConfig。且会装载到 self.app_configs 字典中

随后,分别调用每个appConfig的 import_models() 和 ready() 方法。

App的装载部分大体如此

为了方便debug我们改写下最后一句

res的类型是 Command django.contrib.staticfiles.management.commands.runserver.Command object at 0x00000101ED5163A0

重点是第二句,让我们跳到 run_from_argv() 方法,这里对参数进行了若干处理。

用pycharm点这里的handle会进入基类的方法,无法得到正确的走向。实际上子类Commond重写了这个方法。

这里分为两种情况,如果是reload重载时,会直接执行 inner_run() ,而项目启动需要先执行其他逻辑。

django 项目启动时,实际上会启动两次,如果我们在项目入口(manage.py)中设置个print,会发现它会打印两次。

第一次启动时, DJANGO_AUTORELOAD_ENV 为None,无法进入启动逻辑。会进入 restart_with_reloader() 。

在这里会将 DJANGO_AUTORELOAD_ENV 置为True,随后重启。

第二次时,可以进入启动逻辑了。

这里创建了一个django主线程,将 inner_run() 传入。

随后本线程通过 reloader.run(django_main_thread) ,创建一个轮询守护进程。

我们接下来看django的主线程 inner_run() 。

当我们看到wsgi时,django负责的启动逻辑,就此结束了。接下来的工作交由wsgi服务器了

这相当于我们之前在fastapi中说到的,将fastapi的app交由asgi服务器。(asgi也是django提出来的,两者本质同源)

那么这个wsgi是从哪来的?让我们来稍微回溯下

这个settings是一个对象,在之前的操作中已经从 settings.py 配置文件中获得了自身的属性。所以我们只需要去 settings.py 配置文件中寻找。

我们来寻找这个 get_wsgi_application() 。

它会再次调用 setup() ,重要的是,返回一个 WSGIHandler 类的实例。

这就是wsgiapp本身。

load_middleware() 为构建中间件堆栈,这也是wsgiapp获取setting信息的唯一途径。导入settings.py,生成中间件堆栈。

如果看过我之前那篇fastapi源码的,应该对中间件堆栈不陌生。

app入口→中间件堆栈→路由→路由节点→endpoint

所以,wsgiapp就此构建完毕,服务器传入请求至app入口,即可经过中间件到达路由进行分发。

Django的懒加载是什么(2023年最新解答)  第1张

什么时候用懒加载

1.懒加载基本

懒加载——也称为延迟加载,即在需要的时候才加载(效率低,占用内存小)。所谓懒加载,写的是其get方法.

注意:如果是懒加载的话则一定要注意先判断是否已经有了,如果没有那么再去进行实例化

2.使用懒加载的好处:

(1)不必将创建对象的代码全部写在viewDidLoad方法中,代码的可读性更强

(2)每个控件的getter方法中分别负责各自的实例化处理,代码彼此之间的独立性强,松耦合

3.代码示例

1 //

2 // YYViewController.m

3 // 03-图片浏览器初步

4 //

5 // Created by apple on 14-5-21.

6 // Copyright (c) 2014年 itcase. All rights reserved.

7 //

8

9 #import \"YYViewController.h\"

10

11 #define POTOIMGW 200

12 #define POTOIMGH 300

13 #define POTOIMGX 60

14 #define POTOIMGY 50

15

16 @interface YYViewController ()

17

18 @property(nonatomic,strong)UILabel *firstlab;

19 @property(nonatomic,strong)UILabel *lastlab;

20 @property(nonatomic,strong)UIImageView *icon;

21 @property(nonatomic,strong)UIButton *leftbtn;

22 @property(nonatomic,strong)UIButton *rightbtn;

23 @property(nonatomic,strong)NSArray *array;

24 @property(nonatomic ,assign)int i;

25 -(void)change;

26 @end

27

28

29

30 @implementation YYViewController

31

32 - (void)viewDidLoad

33 {

34 [super viewDidLoad];

35 [self change];

36 }

37

38 -(void)change

39 {

40 [self.firstlab setText:[NSString stringWithFormat:@\"%d/5\",self.i+1]];

41 //先get再set

42

43 self.icon.image=[UIImage imageNamed:self.array[self.i][@\"name\"]];

44 self.lastlab.text=self.array[self.i][@\"desc\"];

45

46 self.leftbtn.enabled=(self.i!=0);

47 self.rightbtn.enabled=(self.i!=4);

48 }

49

50 //延迟加载

51 /**1.图片的序号标签*/

52 -(UILabel *)firstlab

53 {

54 //判断是否已经有了,若没有,则进行实例化

55 if (!_firstlab) {

56 _firstlab=[[UILabel alloc]initWithFrame:CGRectMake(20, 10, 300, 30)];

57 [_firstlab setTextAlignment:NSTextAlignmentCenter];

58 [self.view addSubview:_firstlab];

59 }

60 return _firstlab;

61 }

62

63 /**2.图片控件的延迟加载*/

64 -(UIImageView *)icon

65 {

66 //判断是否已经有了,若没有,则进行实例化

67 if (!_icon) {

68 _icon=[[UIImageView alloc]initWithFrame:CGRectMake(POTOIMGX, POTOIMGY, POTOIMGW, POTOIMGH)];

69 UIImage *image=[UIImage imageNamed:@\"biaoqingdi\"];

70 _icon.image=image;

71 [self.view addSubview:_icon];

72 }

73 return _icon;

74 }

75

76 /**3.描述控件的延迟加载*/

77 -(UILabel *)lastlab

78 {

79 //判断是否已经有了,若没有,则进行实例化

80 if (!_lastlab) {

81 _lastlab=[[UILabel alloc]initWithFrame:CGRectMake(20, 400, 300, 30)];

82 [_lastlab setTextAlignment:NSTextAlignmentCenter];

83 [self.view addSubview:_lastlab];

84 }

85 return _lastlab;

86 }

87

88 /**4.左键按钮的延迟加载*/

89 -(UIButton *)leftbtn

90 {

91 //判断是否已经有了,若没有,则进行实例化

92 if (!_leftbtn) {

93 _leftbtn=[UIButton buttonWithType:UIButtonTypeCustom];

94 _leftbtn.frame=CGRectMake(0, self.view.center.y, 40, 40);

95 [_leftbtn setBackgroundImage:[UIImage imageNamed:@\"left_normal\"] forState:UIControlStateNormal];

96 [_leftbtn setBackgroundImage:[UIImage imageNamed:@\"left_highlighted\"] forState:UIControlStateHighlighted];

97 [self.view addSubview:_leftbtn];

98 [_leftbtn addTarget:self action:@selector(leftclick:) forControlEvents:UIControlEventTouchUpInside];

99 }

100 return _leftbtn;

101

102 }

103

104 /**5.右键按钮的延迟加载*/

105 -(UIButton *)rightbtn

106 {

107 if (!_rightbtn) {

108 _rightbtn=[UIButton buttonWithType:UIButtonTypeCustom];

109 _rightbtn.frame=CGRectMake(POTOIMGX+POTOIMGW+10, self.view.center.y, 40, 40);

110 [_rightbtn setBackgroundImage:[UIImage imageNamed:@\"right_normal\"] forState:UIControlStateNormal];

111 [_rightbtn setBackgroundImage:[UIImage imageNamed:@\"right_highlighted\"] forState:UIControlStateHighlighted];

112 [self.view addSubview:_rightbtn];

113 [_rightbtn addTarget:self action:@selector(rightclick:) forControlEvents:UIControlEventTouchUpInside];

114 }

115 return _rightbtn;

116 }

117

118 //array的get方法

119 -(NSArray *)array

120 {

121 if (_array==nil) {

122 NSString *path=[[NSBundle mainBundle] pathForResource:@\"data\" ofType:@\"plist\"];

123 _array=[[NSArray alloc]initWithContentsOfFile:path];

124 }

125 return _array;

126 }

127

128 -(void)rightclick:(UIButton *)btn

129 {

130 self.i++;

131 [self change];

132 }

133

134 -(void)leftclick:(UIButton *)btn

135 {

136 self.i--;

137 [self change];

138 }

139

140 @end

什么是预加载、懒加载

图片先用占位符表示,不要将图片地址放到src属性中,而是放到其它属性(data-original)中

页面加载完成后,监听窗口滚动,当图片出现在视窗中时再给它赋予真实的图片地址,也就是将data-original中的属性拿出来放到src属性中

在滚动页面的过程中,通过给scroll事件绑定lazyload函数,不断的加载出需要的图片

注意:请对lazyload函数使用防抖与节流,不懂这两的可以自己去查

3.可视区加载

这里也分为两种情况

1、页面滚动的时候计算图片的位置与滚动的位置

2、通过新的API: IntersectionObserver API(可以自动\"观察\"元素是否可见)

如上,data- 属于自定义属性, ele.dataset. 可以读取自定义属性集合

img.srcset 属性用于设置不同屏幕密度下,image自动加载不同的图片,比如img src=\"image-128.png\" srcset=\"image-256.png 2x\" /

预加载

提前加载图片,当用户需要查看时可直接从本地缓存中渲染

加载方式目前主要有两种

待到满足触发条件后,再通过JS渲染

结语:以上就是首席CTO笔记为大家整理的关于Django的懒加载是什么的相关内容解答汇总了,希望对您有所帮助!如果解决了您的问题欢迎分享给更多关注此问题的朋友喔~

以上内容为新媒号(sinv.com.cn)为大家提供!新媒号,坚持更新大家所需的互联网后端知识。希望您喜欢!

版权申明:新媒号所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,不声明或保证其内容的正确性,如发现本站有涉嫌抄袭侵权/违法违规的内容。请发送邮件至 k2#88.com(替换@) 举报,一经查实,本站将立刻删除。

(0)
上一篇 2023-09-23 13:19
下一篇 2023-09-23

相关推荐

发表回复

登录后才能评论