-
Notifications
You must be signed in to change notification settings - Fork 0
/
bbs.sql
559 lines (520 loc) · 756 KB
/
bbs.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
/*
Navicat Premium Data Transfer
Source Server : wyp1
Source Server Type : MySQL
Source Server Version : 80011
Source Host : localhost:3306
Source Schema : bbs
Target Server Type : MySQL
Target Server Version : 80011
File Encoding : 65001
Date: 30/08/2022 15:03:21
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for app01_article
-- ----------------------------
DROP TABLE IF EXISTS `app01_article`;
CREATE TABLE `app01_article` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`title` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
`desc` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
`content` longtext CHARACTER SET utf8mb4 NOT NULL,
`create_time` date NOT NULL,
`up_num` bigint(20) NOT NULL,
`down_num` bigint(20) NOT NULL,
`comment_num` bigint(20) NOT NULL,
`blog_id` bigint(20) NULL DEFAULT NULL,
`category_id` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `app01_article_blog_id_8dd74ae6_fk_app01_blog_id`(`blog_id`) USING BTREE,
INDEX `app01_article_category_id_acb2c466_fk_app01_category_id`(`category_id`) USING BTREE,
CONSTRAINT `app01_article_blog_id_8dd74ae6_fk_app01_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `app01_blog` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `app01_article_category_id_acb2c466_fk_app01_category_id` FOREIGN KEY (`category_id`) REFERENCES `app01_category` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 22 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_article
-- ----------------------------
INSERT INTO `app01_article` VALUES (1, 'Python企业面试题(系列目录)', '本系列计划把Python面试中出现频率比较高知识点整理出来,以便各位童鞋复习和练习: 【第1题】 Python内存管理以及垃圾回收机制 【第2题】 链表的逆置 【第3题】 两个队列创建一个栈 【第4题】 什么是https? 【第5题】 什么是jwt? 【第6题】什么是websocket?', '<div id=\"cnblogs_post_body\" class=\"blogpost-body blogpost-body-html\">\r\n<p><strong>1、</strong>自定义一个HttpModule,并将其中的方法添加到HttpApplication相应的事件中!即:创建一个实现了IHttpmodule接口的类,并将配置WebConfig。<br><span style=\"color: rgba(136, 136, 136, 1)\"> 在自定义的HttpModule中,可以将一个方法注册到HttpApplication的任意一个事件中,在之后执行HttpApplication一些列事件时,按照事件的顺序(事件又按照添加方法先后的顺序)执行注册在事件中的方法!</span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_833130\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">namespace</code> <code class=\"csharp plain\">MvcStore.Models</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">ExcuteHttpRequestModule:IHttpModule</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">Init(HttpApplication context)</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">context.PostResolveRequestCache+=</code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">EventHandler(</code><code class=\"csharp keyword\">this</code><code class=\"csharp plain\">.context_ExecuteHttpRequst);</code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp spaces\"> </code> </div><div class=\"line number9 index8 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number10 index9 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">Dispose()</code></div><div class=\"line number11 index10 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number12 index11 alt1\"><code class=\"csharp spaces\"> </code> </div><div class=\"line number13 index12 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number14 index13 alt1\"> </div><div class=\"line number15 index14 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">context_ExecuteHttpRequst(</code><code class=\"csharp keyword\">object</code> <code class=\"csharp plain\">sender, EventArgs e)</code></div><div class=\"line number16 index15 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number17 index16 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">HttpRequest httpRequest = HttpContext.Current.Request;</code></div><div class=\"line number18 index17 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">Uri previousUri = httpRequest.UrlReferrer;</code></div><div class=\"line number19 index18 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number20 index19 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number21 index20 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_141852\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp plain\"><?xml version=</code><code class=\"csharp string\">\"1.0\"</code> <code class=\"csharp plain\">encoding=</code><code class=\"csharp string\">\"utf-8\"</code><code class=\"csharp plain\">?></code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\"><!--</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">有关如何配置 ASP.NET 应用程序的详细信息,请访问</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">http:</code><code class=\"csharp comments\">//go.microsoft.com/fwlink/?LinkId=152368</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">--></code></div><div class=\"line number6 index5 alt1\"> </div><div class=\"line number7 index6 alt2\"><code class=\"csharp plain\"><configuration></code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"><appSettings></code></div><div class=\"line number9 index8 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"><add key=</code><code class=\"csharp string\">\"webpages:Version\"</code> <code class=\"csharp plain\">value=</code><code class=\"csharp string\">\"1.0.0.0\"</code><code class=\"csharp plain\">/></code></div><div class=\"line number10 index9 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"><add key=</code><code class=\"csharp string\">\"ClientValidationEnabled\"</code> <code class=\"csharp plain\">value=</code><code class=\"csharp string\">\"true\"</code><code class=\"csharp plain\">/></code></div><div class=\"line number11 index10 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"><add key=</code><code class=\"csharp string\">\"UnobtrusiveJavaScriptEnabled\"</code> <code class=\"csharp plain\">value=</code><code class=\"csharp string\">\"true\"</code><code class=\"csharp plain\">/></code></div><div class=\"line number12 index11 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"></appSettings></code></div><div class=\"line number13 index12 alt2\"><code class=\"csharp spaces\"> </code> </div><div class=\"line number14 index13 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"><system.web></code></div><div class=\"line number15 index14 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"><!--自定义HttpModule,仅添加一下此段代码即可--></code></div><div class=\"line number16 index15 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"><httpModules></code></div><div class=\"line number17 index16 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"><add name=</code><code class=\"csharp string\">\"ExecuteHttpRequestModule\"</code> <code class=\"csharp plain\">type=</code><code class=\"csharp string\">\"MvcStore.Models.ExcuteHttpRequestModule\"</code><code class=\"csharp plain\">/></code></div><div class=\"line number18 index17 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\"></httpModules></code></div><div class=\"line number19 index18 alt2\"><code class=\"csharp spaces\"> </code> </div><div class=\"line number20 index19 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">......等</code></div><div class=\"line number21 index20 alt2\"><code class=\"csharp plain\"></configuration></code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><span style=\"color: rgba(0, 0, 0, 1)\">例:创建一个HttpModule(实现IHttpModule接口),并将一个方法注册到HttpApplication的BeginRequest</span><span style=\"line-height: 1.5; color: rgba(136, 136, 136, 1)\">(HttpAppliaction的第一个事件)</span><span style=\"line-height: 1.5\">事件中,即:由于该方法注册在HttpApplication第一个事件中,所有无论是合法还是非法的请求地址,该方法都会被执行。</span></p>\r\n<p>利用HttpModule扩展知识,并通过NLog来完成写请求日志:<a href=\"https://files.cnblogs.com/wupeiqi/RouteFilter_1.rar\" rel=\"noopener\">源码下载</a></p>\r\n<p><span style=\"color: rgba(153, 153, 153, 1)\">补充:在ASP.NET MVC中,css和js的请求是合并到一起发送给服务端的!</span></p>\r\n<p><strong>2、</strong>添加路由规则</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_6114\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp plain\">routes.MapRoute(</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp string\">\"Default\"</code><code class=\"csharp plain\">, </code><code class=\"csharp comments\">// 路由名称</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp string\">\"{controller}/{action}/{id}\"</code><code class=\"csharp plain\">, </code><code class=\"csharp comments\">// 带有参数的 URL</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">{ controller = </code><code class=\"csharp string\">\"Home\"</code><code class=\"csharp plain\">, action = </code><code class=\"csharp string\">\"Index\"</code><code class=\"csharp plain\">, id = UrlParameter.Optional } </code><code class=\"csharp comments\">// 参数默认值</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">);</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><strong>3、</strong>自定义MapRoute方法</p>\r\n<p> 第一步中MapRoute方法其实就是RouteCollection的扩展方法,我们也可以定义一个。</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_c407c291-2ac0-4749-9001-1013b496ee96\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_c407c291-2ac0-4749-9001-1013b496ee96\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_c407c291-2ac0-4749-9001-1013b496ee96\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">namespace</span><span style=\"color: rgba(0, 0, 0, 1)\"> System.Web.Mvc\r\n{\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> RouteCollectionExtensions\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> Route MapRoute(<span style=\"color: rgba(0, 0, 255, 1)\">this</span> RouteCollection routes, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> name, <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> url)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> routes.MapRoute(name, url, <span style=\"color: rgba(0, 0, 255, 1)\">null</span>, <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> Route MapRoute(<span style=\"color: rgba(0, 0, 255, 1)\">this</span> RouteCollection routes, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> name, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> url, <span style=\"color: rgba(0, 0, 255, 1)\">object</span><span style=\"color: rgba(0, 0, 0, 1)\"> defaults)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> routes.MapRoute(name, url, defaults, <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> Route MapRoute(<span style=\"color: rgba(0, 0, 255, 1)\">this</span> RouteCollection routes, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> name, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> url, <span style=\"color: rgba(0, 0, 255, 1)\">object</span> defaults, <span style=\"color: rgba(0, 0, 255, 1)\">object</span><span style=\"color: rgba(0, 0, 0, 1)\"> constraints)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> routes.MapRoute(name, url, defaults, constraints, <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> Route MapRoute(<span style=\"color: rgba(0, 0, 255, 1)\">this</span> RouteCollection routes, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> name, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> url, <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\">[] namespaces)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> routes.MapRoute(name, url, <span style=\"color: rgba(0, 0, 255, 1)\">null</span>, <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">, namespaces);\r\n }\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> Route MapRoute(<span style=\"color: rgba(0, 0, 255, 1)\">this</span> RouteCollection routes, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> name, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> url, <span style=\"color: rgba(0, 0, 255, 1)\">object</span> defaults, <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\">[] namespaces)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> routes.MapRoute(name, url, defaults, <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">, namespaces);\r\n }\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> Route MapRoute(<span style=\"color: rgba(0, 0, 255, 1)\">this</span> RouteCollection routes, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> name, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> url, <span style=\"color: rgba(0, 0, 255, 1)\">object</span> defaults, <span style=\"color: rgba(0, 0, 255, 1)\">object</span> constraints, <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\">[] namespaces)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (routes == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">routes</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (url == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">url</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n Route route </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span> Route(url, <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> MvcRouteHandler())\r\n {\r\n Defaults </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> RouteValueDictionary(defaults),\r\n Constraints </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> RouteValueDictionary(constraints),\r\n DataTokens </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> RouteValueDictionary()\r\n };\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (namespaces != <span style=\"color: rgba(0, 0, 255, 1)\">null</span> && namespaces.Length > <span style=\"color: rgba(128, 0, 128, 1)\">0</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n route.DataTokens[</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Namespaces</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>] =<span style=\"color: rgba(0, 0, 0, 1)\"> namespaces;\r\n }\r\n routes.Add(name, route);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> route;\r\n }\r\n }\r\n}</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">微软定义的MapRoute方法</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_a70be119-75ac-442c-b06b-88060a2bd4e5\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_a70be119-75ac-442c-b06b-88060a2bd4e5\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_a70be119-75ac-442c-b06b-88060a2bd4e5\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">namespace</span><span style=\"color: rgba(0, 0, 0, 1)\"> MvcExtension.Models\r\n{\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> MyRouteCollectionExtensions\r\n {\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span><span style=\"color: rgba(0, 128, 0, 1)\"> 自定义MapRoute方法\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"routes\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"routeHandler\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"name\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"url\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"defaults\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"constraints\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"namespaces\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><returns></returns></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> Route MyMapRoute(<span style=\"color: rgba(0, 0, 255, 1)\">this</span> RouteCollection routes, IRouteHandler routeHandler, <span style=\"color: rgba(0, 0, 255, 1)\">string</span> name, <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> url,\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">object</span> defaults, <span style=\"color: rgba(0, 0, 255, 1)\">object</span> constraints, <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\">[] namespaces)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (routes == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">routes</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (url == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">url</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (routeHandler == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">routeHandler</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n Route route </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> Route(url, routeHandler)\r\n {\r\n Defaults </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> RouteValueDictionary(defaults),\r\n Constraints </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> RouteValueDictionary(constraints),\r\n DataTokens </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> RouteValueDictionary()\r\n };\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (namespaces != <span style=\"color: rgba(0, 0, 255, 1)\">null</span> && namespaces.Length > <span style=\"color: rgba(128, 0, 128, 1)\">0</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n route.DataTokens[</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Namespaces</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>] =<span style=\"color: rgba(0, 0, 0, 1)\"> namespaces;\r\n }\r\n routes.Add(name, route);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> route;\r\n }\r\n\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span><span style=\"color: rgba(0, 128, 0, 1)\"> 自定义MapRoute方法\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"routes\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"name\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"route\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><returns></returns></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> Route MyMapRoute(<span style=\"color: rgba(0, 0, 255, 1)\">this</span> RouteCollection routes, <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> name, Route route)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (routes == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">routes</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (route == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">route</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n routes.Add(name, route);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> route;\r\n }\r\n }\r\n}</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">自定义的MapRoute方法</span></div>\r\n<p><span style=\"font-size: 13px\">注:在微软提供的MapRoute方法中可以看出,创建Route对象时,其构造函数的参数中有:new MvcRouteHandler。这个MvcRouteHandler用于之后创建HttpHandler对象,HttpHandler就是用来最后处理请求的!</span></p>\r\n<p><strong>4、</strong>自定义MvcRouteHandler<br> 即:实现IRouteHandler接口,MVC默认使用MvcRouteHandler来创建HttpHandler对象,用来处理请求!</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_6b6c7560-5d51-4386-8f9a-1cff9991e440\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_6b6c7560-5d51-4386-8f9a-1cff9991e440\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_6b6c7560-5d51-4386-8f9a-1cff9991e440\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">namespace</span><span style=\"color: rgba(0, 0, 0, 1)\"> System.Web.Mvc\r\n{\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> MvcRouteHandler : IRouteHandler\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span><span style=\"color: rgba(0, 0, 0, 1)\"> IControllerFactory _controllerFactory;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span><span style=\"color: rgba(0, 0, 0, 1)\"> MvcRouteHandler()\r\n {\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span><span style=\"color: rgba(0, 0, 0, 1)\"> MvcRouteHandler(IControllerFactory controllerFactory)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._controllerFactory =<span style=\"color: rgba(0, 0, 0, 1)\"> controllerFactory;\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">protected</span> <span style=\"color: rgba(0, 0, 255, 1)\">virtual</span><span style=\"color: rgba(0, 0, 0, 1)\"> IHttpHandler GetHttpHandler(RequestContext requestContext)\r\n {\r\n requestContext.HttpContext.SetSessionStateBehavior(</span><span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.GetSessionStateBehavior(requestContext));\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> MvcHandler(requestContext);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">protected</span> <span style=\"color: rgba(0, 0, 255, 1)\">virtual</span><span style=\"color: rgba(0, 0, 0, 1)\"> SessionStateBehavior GetSessionStateBehavior(RequestContext requestContext)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">string</span> controllerName = (<span style=\"color: rgba(0, 0, 255, 1)\">string</span>)requestContext.RouteData.Values[<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">controller</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">];\r\n IControllerFactory controllerFactory </span>= <span style=\"color: rgba(0, 0, 255, 1)\">this</span>._controllerFactory ??<span style=\"color: rgba(0, 0, 0, 1)\"> ControllerBuilder.Current.GetControllerFactory();\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);\r\n }\r\n IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.GetHttpHandler(requestContext);\r\n }\r\n }\r\n}</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">微软定义的MvcRouteHandler</span></div>\r\n<p> 定义:我们自定义MvcRouteHandler时只需实现IRouteHandler接口,具体实现参照微软定义的MvcRouteHandler类</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_69441\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyRouteHandler:IRouteHandler</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">MyRouteHandler()</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number6 index5 alt1\"> </div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">protected</code> <code class=\"csharp keyword\">virtual</code> <code class=\"csharp plain\">IHttpHandler GetHttpHandler(RequestContext requestContext)</code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number9 index8 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">MvcHandler(requestContext);</code></div><div class=\"line number10 index9 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number11 index10 alt2\"> </div><div class=\"line number12 index11 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">IHttpHandler IRouteHandler.GetHttpHandler(RequestContext requestContext)</code></div><div class=\"line number13 index12 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number14 index13 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp keyword\">this</code><code class=\"csharp plain\">.GetHttpHandler(requestContext);</code></div><div class=\"line number15 index14 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number16 index15 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p> 使用:结合2中创建的自定义的MapRoute方法,将自己的MvcRouteHandler对象添加到Route对象中!</p>\r\n<p>第2、3、4步骤示例:<a href=\"https://files.cnblogs.com/wupeiqi/MvcExtension_234.rar\" rel=\"noopener\">源码下载</a></p>\r\n<p><strong>5、</strong>自定义MvcHandler</p>\r\n<p> 对于微软的类MvcHandler其实就是一个HttpHandler(实现IHttpHandler接口),在MVC整个处理机制中,MvcHandler接收到请求并激活Controller、执行Action、View的呈现 等。MvcHandler是执行MvcRouteHandler的GetHttpHandler方法得到的!</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_459720\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyMvcHandler : IHttpHandler</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">bool</code> <code class=\"csharp plain\">IsReusable</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">get</code> <code class=\"csharp plain\">{ </code><code class=\"csharp keyword\">return</code> <code class=\"csharp keyword\">false</code><code class=\"csharp plain\">; }</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">ProcessRequest(HttpContext context)</code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number9 index8 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">HttpContext.Current.Response.Write(</code><code class=\"csharp string\">\"自定义的MvcHandler处理请求\"</code><code class=\"csharp plain\">);</code></div><div class=\"line number10 index9 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number11 index10 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>在第2、3、4步骤的基础上,使用自定义MvcHandler处理请求:<a href=\"https://files.cnblogs.com/wupeiqi/MvcExtension_2345.rar\" rel=\"noopener\">源码下载</a></p>\r\n<p><strong>6、</strong>自定义ControllerFactory</p>\r\n<p> ControllerFactory用于Controller的激活,也就是创建Controller对象。对于MVC,这个ControllerFactiory是通过ControllerBuilder.Current.GetControllerFactory();得到,默认得到的ControllerFactory是DefaultControllerFactory对象!</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_b72138ba-94b9-4336-8cab-4bae1a8d8eec\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_b72138ba-94b9-4336-8cab-4bae1a8d8eec\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_b72138ba-94b9-4336-8cab-4bae1a8d8eec\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState\r\n{\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">internal</span><span style=\"color: rgba(0, 0, 0, 1)\"> ControllerBuilder ControllerBuilder\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">get</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (<span style=\"color: rgba(0, 0, 255, 1)\">this</span>._controllerBuilder == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._controllerBuilder =<span style=\"color: rgba(0, 0, 0, 1)\"> ControllerBuilder.Current;\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">._controllerBuilder;\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">set</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._controllerBuilder =<span style=\"color: rgba(0, 0, 0, 1)\"> value;\r\n }\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">protected</span> <span style=\"color: rgba(0, 0, 255, 1)\">virtual</span> <span style=\"color: rgba(0, 0, 255, 1)\">void</span><span style=\"color: rgba(0, 0, 0, 1)\"> ProcessRequest(HttpContext httpContext)\r\n {\r\n HttpContextBase httpContext2 </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> HttpContextWrapper(httpContext);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.ProcessRequest(httpContext2);\r\n }\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">protected</span> <span style=\"color: rgba(0, 0, 255, 1)\">internal</span> <span style=\"color: rgba(0, 0, 255, 1)\">virtual</span> <span style=\"color: rgba(0, 0, 255, 1)\">void</span><span style=\"color: rgba(0, 0, 0, 1)\"> ProcessRequest(HttpContextBase httpContext)\r\n {\r\n SecurityUtil.ProcessInApplicationTrust(</span><span style=\"color: rgba(0, 0, 255, 1)\">delegate</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n IController controller;\r\n IControllerFactory controllerFactory;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>.ProcessRequestInit(httpContext, <span style=\"color: rgba(0, 0, 255, 1)\">out</span> controller, <span style=\"color: rgba(0, 0, 255, 1)\">out</span><span style=\"color: rgba(0, 0, 0, 1)\"> controllerFactory);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">try</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n controller.Execute(</span><span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.RequestContext);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">finally</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n controllerFactory.ReleaseController(controller);\r\n }\r\n });\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">void</span> ProcessRequestInit(HttpContextBase httpContext, <span style=\"color: rgba(0, 0, 255, 1)\">out</span> IController controller, <span style=\"color: rgba(0, 0, 255, 1)\">out</span><span style=\"color: rgba(0, 0, 0, 1)\"> IControllerFactory factory)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (ValidationUtility.IsValidationEnabled(HttpContext.Current) == <span style=\"color: rgba(0, 0, 255, 1)\">true</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n ValidationUtility.EnableDynamicValidation(HttpContext.Current);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.AddVersionHeader(httpContext);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.RemoveOptionalRoutingParameters();\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">string</span> requiredString = <span style=\"color: rgba(0, 0, 255, 1)\">this</span>.RequestContext.RouteData.GetRequiredString(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">controller</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">//</span><span style=\"color: rgba(0, 128, 0, 1)\">获取ControllerFactory</span>\r\n factory = <span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.ControllerBuilder.GetControllerFactory();\r\n controller </span>= factory.CreateController(<span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.RequestContext, requiredString);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (controller == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> InvalidOperationException(<span style=\"color: rgba(0, 0, 255, 1)\">string</span>.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, <span style=\"color: rgba(0, 0, 255, 1)\">new</span> <span style=\"color: rgba(0, 0, 255, 1)\">object</span><span style=\"color: rgba(0, 0, 0, 1)\">[]\r\n {\r\n factory.GetType(),\r\n requiredString\r\n }));\r\n }\r\n }\r\n}</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">MvcHandler </span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_978badd7-db27-4374-9a3a-bd63fd78d06a\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_978badd7-db27-4374-9a3a-bd63fd78d06a\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_978badd7-db27-4374-9a3a-bd63fd78d06a\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> ControllerBuilder\r\n{\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> Func<IControllerFactory> _factoryThunk = () => <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">;\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">//</span><span style=\"color: rgba(0, 128, 0, 1)\">静态变量,自己创建本身对象</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> ControllerBuilder _instance = <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> ControllerBuilder();\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> HashSet<<span style=\"color: rgba(0, 0, 255, 1)\">string</span>> _namespaces = <span style=\"color: rgba(0, 0, 255, 1)\">new</span> HashSet<<span style=\"color: rgba(0, 0, 255, 1)\">string</span>><span style=\"color: rgba(0, 0, 0, 1)\">(StringComparer.OrdinalIgnoreCase);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> IResolver<IControllerFactory><span style=\"color: rgba(0, 0, 0, 1)\"> _serviceResolver;\r\n\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">//</span><span style=\"color: rgba(0, 128, 0, 1)\">Current</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span><span style=\"color: rgba(0, 0, 0, 1)\"> ControllerBuilder Current\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">get</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> ControllerBuilder._instance;\r\n }\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> HashSet<<span style=\"color: rgba(0, 0, 255, 1)\">string</span>><span style=\"color: rgba(0, 0, 0, 1)\"> DefaultNamespaces\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">get</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">._namespaces;\r\n }\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> ControllerBuilder() : <span style=\"color: rgba(0, 0, 255, 1)\">this</span>(<span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">internal</span> ControllerBuilder(IResolver<IControllerFactory><span style=\"color: rgba(0, 0, 0, 1)\"> serviceResolver)\r\n {\r\n IResolver</span><IControllerFactory> arg_6A_1 =<span style=\"color: rgba(0, 0, 0, 1)\"> serviceResolver;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (serviceResolver == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">//</span><span style=\"color: rgba(0, 128, 0, 1)\">默认情况下,_serviceResolver赋值为new DefaultControllerFactory</span>\r\n arg_6A_1 = <span style=\"color: rgba(0, 0, 255, 1)\">new</span> SingleServiceResolver<IControllerFactory>(() => <span style=\"color: rgba(0, 0, 255, 1)\">this</span>._factoryThunk(), <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> DefaultControllerFactory\r\n {\r\n ControllerBuilder </span>= <span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n }, </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">ControllerBuilder.GetControllerFactory</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._serviceResolver =<span style=\"color: rgba(0, 0, 0, 1)\"> arg_6A_1;\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span><span style=\"color: rgba(0, 0, 0, 1)\"> IControllerFactory GetControllerFactory()\r\n {\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">//</span><span style=\"color: rgba(0, 128, 0, 1)\">_serviceResolver.Current得到的是DefaultControllerFactory对象,在构造函数中赋值</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">._serviceResolver.Current;\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">void</span><span style=\"color: rgba(0, 0, 0, 1)\"> SetControllerFactory(IControllerFactory controllerFactory)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (controllerFactory == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">controllerFactory</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._factoryThunk = (() =><span style=\"color: rgba(0, 0, 0, 1)\"> controllerFactory);\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">void</span><span style=\"color: rgba(0, 0, 0, 1)\"> SetControllerFactory(Type controllerFactoryType)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (controllerFactoryType == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">controllerFactoryType</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (!<span style=\"color: rgba(0, 0, 255, 1)\">typeof</span><span style=\"color: rgba(0, 0, 0, 1)\">(IControllerFactory).IsAssignableFrom(controllerFactoryType))\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentException(<span style=\"color: rgba(0, 0, 255, 1)\">string</span>.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_MissingIControllerFactory, <span style=\"color: rgba(0, 0, 255, 1)\">new</span> <span style=\"color: rgba(0, 0, 255, 1)\">object</span><span style=\"color: rgba(0, 0, 0, 1)\">[]\r\n {\r\n controllerFactoryType\r\n }), </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">controllerFactoryType</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._factoryThunk = <span style=\"color: rgba(0, 0, 255, 1)\">delegate</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n IControllerFactory result;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">try</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n result </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> (IControllerFactory)Activator.CreateInstance(controllerFactoryType);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">catch</span><span style=\"color: rgba(0, 0, 0, 1)\"> (Exception innerException)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> InvalidOperationException(<span style=\"color: rgba(0, 0, 255, 1)\">string</span>.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_ErrorCreatingControllerFactory, <span style=\"color: rgba(0, 0, 255, 1)\">new</span> <span style=\"color: rgba(0, 0, 255, 1)\">object</span><span style=\"color: rgba(0, 0, 0, 1)\">[]\r\n {\r\n controllerFactoryType\r\n }), innerException);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> result;\r\n };\r\n }\r\n}</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">ControllerBuilder</span></div>\r\n<p> 上述两个类,MvcHandler中通过GetControllerFactory获取的就是<span style=\"line-height: 1.5\">通过ControllerBuilder的SetControllerFactory方法设置</span><span style=\"line-height: 1.5\">ControllerFactory(没有设置时,默认是DefaultControllerFactory)。这就是我们创建自定义ControllerFactory的入口。</span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_102281\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyControllerFactory:IControllerFactory</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">IController CreateController(System.Web.Routing.RequestContext requestContext, </code><code class=\"csharp keyword\">string</code> <code class=\"csharp plain\">controllerName)</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//根据controllerName和命名空间,通过反射创建Controller对象</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp keyword\">null</code><code class=\"csharp plain\">;</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number8 index7 alt1\"> </div><div class=\"line number9 index8 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext requestContext, </code><code class=\"csharp keyword\">string</code> <code class=\"csharp plain\">controllerName)</code></div><div class=\"line number10 index9 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number11 index10 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//获取控制器的会话行为。</code></div><div class=\"line number12 index11 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp plain\">System.Web.SessionState.SessionStateBehavior.Default;</code><code class=\"csharp comments\">//这里是随便列举的一个</code></div><div class=\"line number13 index12 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number14 index13 alt1\"> </div><div class=\"line number15 index14 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">ReleaseController(IController controller)</code></div><div class=\"line number16 index15 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number17 index16 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//释放Controller</code></div><div class=\"line number18 index17 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number19 index18 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_230889\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div><div class=\"line number27 index26 alt2\">27</div><div class=\"line number28 index27 alt1\">28</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MvcApplication : System.Web.HttpApplication</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">static</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">RegisterGlobalFilters(GlobalFilterCollection filters)</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">filters.Add(</code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">HandleErrorAttribute());</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number7 index6 alt2\"> </div><div class=\"line number8 index7 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">static</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">RegisterRoutes(RouteCollection routes)</code></div><div class=\"line number9 index8 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number10 index9 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">routes.IgnoreRoute(</code><code class=\"csharp string\">\"{resource}.axd/{*pathInfo}\"</code><code class=\"csharp plain\">);</code></div><div class=\"line number11 index10 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">routes.MapRoute(</code></div><div class=\"line number12 index11 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp string\">\"Default\"</code><code class=\"csharp plain\">, </code><code class=\"csharp comments\">// 路由名称</code></div><div class=\"line number13 index12 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp string\">\"{controller}/{action}/{id}\"</code><code class=\"csharp plain\">, </code><code class=\"csharp comments\">// 带有参数的 URL</code></div><div class=\"line number14 index13 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">{controller = </code><code class=\"csharp string\">\"Home\"</code><code class=\"csharp plain\">, action = </code><code class=\"csharp string\">\"Index\"</code><code class=\"csharp plain\">, id = UrlParameter.Optional} </code><code class=\"csharp comments\">// 参数默认值</code></div><div class=\"line number15 index14 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">);</code></div><div class=\"line number16 index15 alt1\"> </div><div class=\"line number17 index16 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number18 index17 alt1\"> </div><div class=\"line number19 index18 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">protected</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">Application_Start()</code></div><div class=\"line number20 index19 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number21 index20 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">AreaRegistration.RegisterAllAreas();</code></div><div class=\"line number22 index21 alt1\"> </div><div class=\"line number23 index22 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">RegisterGlobalFilters(GlobalFilters.Filters);</code></div><div class=\"line number24 index23 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">RegisterRoutes(RouteTable.Routes);</code></div><div class=\"line number25 index24 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//设置MyControllerFactory,让MyControllerFactory完成controller的激活</code></div><div class=\"line number26 index25 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">ControllerBuilder.Current.SetControllerFactory(</code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">MyControllerFactory());</code></div><div class=\"line number27 index26 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number28 index27 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p> 上面就是简单的列举了执行流程,不再进行过多的介绍,因为在实际开发中,一般不会使用自定义一个ControllerFactory,因为其中包含的功能,我们自己来定义时可能考虑的不够全面,如果项目需求必须使用的话,要细看微软在DefaultControllerFactory中各种功能!!!既然不用自定义的ContollerFactory,那么就只能用DefaultControllerFactory了,DefaultControllerFactory中也有扩展点让我们利用,就是下面第7中介绍的!</p>\r\n<p><strong>7、</strong>自定义ControllerActivator</p>\r\n<p> 在6中我们讲到,DefaultControllerFactory用于创建Controller对象,而这个ControllerActivator实际上就是DefaultControllerFactory中负责创建Controller对象“组件”。默认情况下,使用的是微软提供的DefaultControllerActivator(DefaultControllerFactory的构造函数中设置)。</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_c20494d5-0f1b-42a1-8d4f-c97986676aa3\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_c20494d5-0f1b-42a1-8d4f-c97986676aa3\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_c20494d5-0f1b-42a1-8d4f-c97986676aa3\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> DefaultControllerActivator : IControllerActivator\r\n{\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> Func<IDependencyResolver><span style=\"color: rgba(0, 0, 0, 1)\"> _resolverThunk;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> DefaultControllerActivator() : <span style=\"color: rgba(0, 0, 255, 1)\">this</span>(<span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span><span style=\"color: rgba(0, 0, 0, 1)\"> DefaultControllerActivator(IDependencyResolver resolver)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (resolver == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._resolverThunk = (() =><span style=\"color: rgba(0, 0, 0, 1)\"> DependencyResolver.Current);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\">;\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._resolverThunk = (() =><span style=\"color: rgba(0, 0, 0, 1)\"> resolver);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span><span style=\"color: rgba(0, 0, 0, 1)\"> IController Create(RequestContext requestContext, Type controllerType)\r\n {\r\n IController result;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">try</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n result </span>= (IController)(<span style=\"color: rgba(0, 0, 255, 1)\">this</span>._resolverThunk().GetService(controllerType) ??<span style=\"color: rgba(0, 0, 0, 1)\"> Activator.CreateInstance(controllerType));\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">catch</span><span style=\"color: rgba(0, 0, 0, 1)\"> (Exception innerException)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> InvalidOperationException(<span style=\"color: rgba(0, 0, 255, 1)\">string</span>.Format(CultureInfo.CurrentCulture, MvcResources.DefaultControllerFactory_ErrorCreatingController, <span style=\"color: rgba(0, 0, 255, 1)\">new</span> <span style=\"color: rgba(0, 0, 255, 1)\">object</span><span style=\"color: rgba(0, 0, 0, 1)\">[]\r\n {\r\n controllerType\r\n }), innerException);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> result;\r\n }\r\n}</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">微软:DefaultControllerActivator</span></div>\r\n<p>自定义:<br> 定义:实现IControllerActivator接口<br> 使用:通过DefaultControllerFactory的构造函数将自定义ControllerActivator “注入”。<br> 在Global.asax中添加 ---> ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new MyControllerActivator()));</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_228992\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyControllerActivator:IControllerActivator</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">IController Create(System.Web.Routing.RequestContext requestContext, Type controllerType)</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp plain\">(IController)Activator.CreateInstance(controllerType);</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_309489\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">protected</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">Application_Start()</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">AreaRegistration.RegisterAllAreas();</code></div><div class=\"line number4 index3 alt1\"> </div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">RegisterGlobalFilters(GlobalFilters.Filters);</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">RegisterRoutes(RouteTable.Routes);</code></div><div class=\"line number7 index6 alt2\"> </div><div class=\"line number8 index7 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">ControllerBuilder.Current.SetControllerFactory(</code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">DefaultControllerFactory(</code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">MyControllerActivator()));</code></div><div class=\"line number9 index8 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p> 应用场景1:在Controller激活之前做一些操作<br> 应用场景2:通过Controller的构造函数实现在创建Controller对象时“注入”值!<em>因为默认情况下,激活Controller的时候是执行的其无参数构造函数!</em></p>\r\n<p>应用场景2+依赖注入:<a href=\"https://files.cnblogs.com/wupeiqi/MvcExtension_7.rar\" rel=\"noopener\">源码下载</a></p>\r\n<p><strong>8、</strong>自定义ActionInvoker</p>\r\n<p> ActionInvoker用于去执行被请求的Action方法,这过程中包含了 View的呈现 以及执行各种应用在Action上的特性(HttpMethod、Filter、DisplayName...等),由于功能忒多,所以不到不得已也不建议自己重写ActionInvoker。不过如果项目需要,可以继承微软默认使用的 ControllerActionInvoker,从而在已有功能的基础上添加自己的需要的功能!</p>\r\n<p> 自定义:<br> 定义:实现IActionInvoker接口<br> 使用:在Controller的构造函数中设置自己的ActionInvoker</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_700357\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyActionInvoker:IActionInvoker</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">bool</code> <code class=\"csharp plain\">InvokeAction(ControllerContext controllerContext, </code><code class=\"csharp keyword\">string</code> <code class=\"csharp plain\">actionName)</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//根据action名称去找Action并执行,其中包括了 View的呈现 以及 应用在Action上的各种特性的执行</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//return false; //执行失败</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp keyword\">true</code><code class=\"csharp plain\">; </code><code class=\"csharp comments\">//执行成功</code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number9 index8 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_219508\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">HomeController : Controller</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//微软的ControllerActivator激活Controller时,执行的就是无参数的构造函数!</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">HomeController()</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">base</code><code class=\"csharp plain\">.ActionInvoker = </code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">MyActionInvoker();</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number8 index7 alt1\"> </div><div class=\"line number9 index8 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">ActionResult Index()</code></div><div class=\"line number10 index9 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number11 index10 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp plain\">Content(</code><code class=\"csharp string\">\"ddd\"</code><code class=\"csharp plain\">);</code></div><div class=\"line number12 index11 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number13 index12 alt2\"> </div><div class=\"line number14 index13 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>仅第8步骤示例:<a href=\"https://files.cnblogs.com/wupeiqi/MvcExtension_8.rar\" rel=\"noopener\">源码下载</a></p>\r\n<p>下面的9、10、11讲的是和特性相关的扩展,所以在介绍它们之前先来复习下MVC中使用的特性种类和处理流程:</p>\r\n<p> 种类:</p>\r\n<p> ActionNameSelectorAttribute <br> ActionNameAttribute<br> ActionMethodSelectorAttribute<br> AcceptVerbsAttribute<br> HttpDeleteAttribute<br> HttpGetAttribute<br> HttpPostAttribute<br> HttpPutAttribute<br> NonActionAttribute<br><span style=\"color: rgba(153, 153, 153, 1)\"> HttpHeadAttribute</span><br><span style=\"color: rgba(153, 153, 153, 1)\"> HttpOptionsAttribute</span><br><span style=\"color: rgba(153, 153, 153, 1)\"> HttpPatchAttribute //灰色字体的是MVC4中新增的!</span><br> FilterAttribute、IActionFilter或IAuthorizationFilter或IExceptionFilter或IResultFilter<br> 自定义类去实现相应接口</p>\r\n<p> 处理流程:<span style=\"color: rgba(51, 51, 51, 1)\">Contrller激活之后,要从Controller对象的方法中查找当前请求的Action,那么其流程为 ----> 先获取所有应用了ActionName特性并且ActionName特性设置的name=当前请求的Action名称<em>(将符合条件的添加的List<MethodInfo>中)</em>,之后去获取所有没有应用ActionName特性的方法并且方法名=当前请求的Action名称,<em>(再将符合条件的添加到之前创建的List<MethodInfo>尾部)</em></span>;<span style=\"color: rgba(153, 153, 153, 1)\">再之后对符合名称条件的Action方法集合处理,判断应用在Action方法上的NonAction、AcceptVerbs、HttpGet等6个特性(MVC4有9个特性)是否和当前请求一致</span><span style=\"color: rgba(0, 0, 0, 1)\">;</span><span style=\"color: rgba(51, 51, 51, 1)\">再再之后执行第三种过滤器,需要自己定义且实现接口,并应用在Action上,他们的执行顺序为:【IAuthorizationFilter】--->【IActionFilter】--->【Action方法内部代码】--->【IResultFilter】,如果上述4个过程中有异常抛出,则执行【IExceptionFilter】。个更多处理流程的介绍请<a href=\"http://www.cnblogs.com/wupeiqi/p/3405170.html\" rel=\"noopener\">猛击这里</a>!</span></p>\r\n<p><strong>9、</strong>继承自ActionNameSelectorAttribute 的特性:ActionNameAttribute</p>\r\n<p> 用于对Controller类中Action方法的重命名!当请求指定的 Controller/Action时,将用重命名后的名称去和请求的Action名称匹配。</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_ea641911-592f-461a-8e66-919a29878821\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_ea641911-592f-461a-8e66-919a29878821\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_ea641911-592f-461a-8e66-919a29878821\" class=\"cnblogs_code_hide\">\r\n<pre>[AttributeUsage(AttributeTargets.Method, AllowMultiple = <span style=\"color: rgba(0, 0, 255, 1)\">false</span>, Inherited = <span style=\"color: rgba(0, 0, 255, 1)\">true</span><span style=\"color: rgba(0, 0, 0, 1)\">)]\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">sealed</span> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> ActionNameAttribute : ActionNameSelectorAttribute\r\n{\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> Name\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">get</span><span style=\"color: rgba(0, 0, 0, 1)\">;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">set</span><span style=\"color: rgba(0, 0, 0, 1)\">;\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> ActionNameAttribute(<span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> name)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (<span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\">.IsNullOrEmpty(name))\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentException(MvcResources.Common_NullOrEmpty, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">name</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>.Name =<span style=\"color: rgba(0, 0, 0, 1)\"> name;\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">override</span> <span style=\"color: rgba(0, 0, 255, 1)\">bool</span> IsValidName(ControllerContext controllerContext, <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> actionName, MethodInfo methodInfo)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span>.Equals(actionName, <span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.Name, StringComparison.OrdinalIgnoreCase);\r\n }\r\n}</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">微软定义的ActionNameAttribute </span></div>\r\n<p>使用:</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_6232\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">HomeController : Controller</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">[ActionName(</code><code class=\"csharp string\">\"OtherName\"</code><code class=\"csharp plain\">)]</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">ActionResult Index()</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp plain\">Content(</code><code class=\"csharp string\">\"ddd\"</code><code class=\"csharp plain\">);</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">} </code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p> 如上设置ActionName后,当请求Home/Index就提示找不到无法找到资源,当请求Home/OtherName时,就会去执行这个Index方法!</p>\r\n<p><strong>10、</strong>继承自<span>ActionMethodSelectorAttribute的特性:AcceptVerbsAttribute...等</span></p>\r\n<p><span> 该类特性中仅NonAction用于指示该方法不作为Action来使用,而其他的5个则都是用于判断Http请求的方式!</span></p>\r\n<p><span> HttpGet 只有客户端发送的是Get请求才能执行该Action<br> HttpPost 只有客户端发送的是Post请求才能执行该Action ...Post请求<br> HttpDelete 只有客户端发送的是Delete请求才能执行该Action<br> HttpPut 只有客户端发送的是Put请求才能执行该Action<br> AcceptVerbs 参数是一个枚举(Get、Post等),其功能和以上四个相同<br><span style=\"color: rgba(153, 153, 153, 1)\">注:由于以上的特性类都应用了: [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)],所以这些特性只能应用在Action方法上并且每个只能使用一个。</span></span></p>\r\n<p>使用:仅列出HttpPost,其他使用方法相同,不再列举。</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_134615\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">HomeController : Controller</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">[HttpPost]</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">ActionResult Index()</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp plain\">Content(</code><code class=\"csharp string\">\"ddd\"</code><code class=\"csharp plain\">);</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">} </code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p> 如上所示,只有客户端发送的是Post请求时,才能执行该Action。</p>\r\n<p><strong>11、</strong>FilterAttribute、IActionFilter或IAuthorizationFilter或IExceptionFilter或IResultFilter</p>\r\n<p> 该类过滤器执行的顺序为:<span>【IAuthorizationFilter】--->【IActionFilter】--->【Action方法内部代码】--->【IResultFilter】,如果上述4个过程中有异常抛出,则执行【IExceptionFilter】。<br> 由于FilterAttribute类应用了 [<span>AttributeUsage</span>(AttributeTargets.Class | AttributeTargets.Method, Inherited = <span>true</span>, AllowMultiple = <span style=\"color: rgba(255, 0, 0, 1)\">false</span>)],所以该类特性可以应用在 类 或 方法 上且默认也只能使用一次,如果想要使用多个同样的特性,可以在自定义的特性上添加: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = <span style=\"color: rgba(255, 0, 0, 1)\">true</span>)]即可。<br> 该类过滤器有 4 种添加</span><span style=\"line-height: 1.5\">方式</span><span style=\"line-height: 1.5\">:以特性应用在Action方法上、以特性应用在Controller类上、</span><span style=\"line-height: 1.5\">Global.asax文件中</span><span style=\"line-height: 1.5\">RegisterGlobalFilters方法中添加、在Controller中重写各个过滤器方法(因为Controller类都实现各个接口),区别是这4种方式的作用域不同!</span></p>\r\n<p> 11-1、IAuthorizationFilter</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_595137\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyAuthroizeFilter : FilterAttribute, IAuthorizationFilter</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">OnAuthorization(AuthorizationContext filterContext)</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{ </code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果此处为filterContext.Result赋一个ActionResult对象,则MVC不会再继续执行下面的过滤器和Action放,而是直接根据这个ActionResult对象进行View的呈现。</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果filterContext.Result为null,则MVC继续执行之后的各个过滤器和Action方法!</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p> 微软定义的该类过滤器有:ChildActionOnlyAttribute、AuthorizeAttribute,可以参考这两个类来定义自己的IAuthorizationFilter过滤器。</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_db629008-c4d9-4011-9c22-cf967076df8e\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_db629008-c4d9-4011-9c22-cf967076df8e\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_db629008-c4d9-4011-9c22-cf967076df8e\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">using</span><span style=\"color: rgba(0, 0, 0, 1)\"> System;\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">namespace</span><span style=\"color: rgba(0, 0, 0, 1)\"> System.Web.Mvc\r\n{\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">Represents an attribute that is used to indicate that an action method should be called only as a child action.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = <span style=\"color: rgba(0, 0, 255, 1)\">false</span>, Inherited = <span style=\"color: rgba(0, 0, 255, 1)\">true</span><span style=\"color: rgba(0, 0, 0, 1)\">)]\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">sealed</span> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> ChildActionOnlyAttribute : FilterAttribute, IAuthorizationFilter\r\n {\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">Called when authorization is required.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"filterContext\"></span><span style=\"color: rgba(0, 128, 0, 1)\">An object that encapsulates the information that is required in order to authorize access to the child action.</span><span style=\"color: rgba(128, 128, 128, 1)\"></param></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">void</span><span style=\"color: rgba(0, 0, 0, 1)\"> OnAuthorization(AuthorizationContext filterContext)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (filterContext == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">filterContext</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (!<span style=\"color: rgba(0, 0, 0, 1)\">filterContext.IsChildAction)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span><span style=\"color: rgba(0, 0, 0, 1)\"> Error.ChildActionOnlyAttribute_MustBeInChildRequest(filterContext.ActionDescriptor);\r\n }\r\n }\r\n }\r\n}</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">ChildActionOnlyAttribute </span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_856987db-a933-4157-abeb-3f57f1c5a3c5\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_856987db-a933-4157-abeb-3f57f1c5a3c5\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_856987db-a933-4157-abeb-3f57f1c5a3c5\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">using</span><span style=\"color: rgba(0, 0, 0, 1)\"> System;\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">using</span><span style=\"color: rgba(0, 0, 0, 1)\"> System.Collections.Generic;\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">using</span><span style=\"color: rgba(0, 0, 0, 1)\"> System.Linq;\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">using</span><span style=\"color: rgba(0, 0, 0, 1)\"> System.Security.Principal;\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">using</span><span style=\"color: rgba(0, 0, 0, 1)\"> System.Web.Mvc.Resources;\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">namespace</span><span style=\"color: rgba(0, 0, 0, 1)\"> System.Web.Mvc\r\n{\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">Represents an attribute that is used to restrict access by callers to an action method.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = <span style=\"color: rgba(0, 0, 255, 1)\">true</span>, AllowMultiple = <span style=\"color: rgba(0, 0, 255, 1)\">true</span><span style=\"color: rgba(0, 0, 0, 1)\">)]\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> AuthorizeAttribute : FilterAttribute, IAuthorizationFilter\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">readonly</span> <span style=\"color: rgba(0, 0, 255, 1)\">object</span> _typeId = <span style=\"color: rgba(0, 0, 255, 1)\">new</span> <span style=\"color: rgba(0, 0, 255, 1)\">object</span><span style=\"color: rgba(0, 0, 0, 1)\">();\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> _roles;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span>[] _rolesSplit = <span style=\"color: rgba(0, 0, 255, 1)\">new</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span>[<span style=\"color: rgba(128, 0, 128, 1)\">0</span><span style=\"color: rgba(0, 0, 0, 1)\">];\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> _users;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span>[] _usersSplit = <span style=\"color: rgba(0, 0, 255, 1)\">new</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span>[<span style=\"color: rgba(128, 0, 128, 1)\">0</span><span style=\"color: rgba(0, 0, 0, 1)\">];\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">Gets or sets the user roles.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><returns></span><span style=\"color: rgba(0, 128, 0, 1)\">The user roles.</span><span style=\"color: rgba(128, 128, 128, 1)\"></returns></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> Roles\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">get</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">this</span>._roles ?? <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\">.Empty;\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">set</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._roles =<span style=\"color: rgba(0, 0, 0, 1)\"> value;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._rolesSplit =<span style=\"color: rgba(0, 0, 0, 1)\"> AuthorizeAttribute.SplitString(value);\r\n }\r\n }\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">Gets the unique identifier for this attribute.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><returns></span><span style=\"color: rgba(0, 128, 0, 1)\">The unique identifier for this attribute.</span><span style=\"color: rgba(128, 128, 128, 1)\"></returns></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">override</span> <span style=\"color: rgba(0, 0, 255, 1)\">object</span><span style=\"color: rgba(0, 0, 0, 1)\"> TypeId\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">get</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">._typeId;\r\n }\r\n }\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">Gets or sets the authorized users.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><returns></span><span style=\"color: rgba(0, 128, 0, 1)\">The authorized users.</span><span style=\"color: rgba(128, 128, 128, 1)\"></returns></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> Users\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">get</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">this</span>._users ?? <span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\">.Empty;\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">set</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._users =<span style=\"color: rgba(0, 0, 0, 1)\"> value;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span>._usersSplit =<span style=\"color: rgba(0, 0, 0, 1)\"> AuthorizeAttribute.SplitString(value);\r\n }\r\n }\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">When overridden, provides an entry point for custom authorization checks.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><returns></span><span style=\"color: rgba(0, 128, 0, 1)\">true if the user is authorized; otherwise, false.</span><span style=\"color: rgba(128, 128, 128, 1)\"></returns></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"httpContext\"></span><span style=\"color: rgba(0, 128, 0, 1)\">The HTTP context, which encapsulates all HTTP-specific information about an individual HTTP request.</span><span style=\"color: rgba(128, 128, 128, 1)\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><exception cref=\"T:System.ArgumentNullException\"></span><span style=\"color: rgba(0, 128, 0, 1)\">The </span><span style=\"color: rgba(128, 128, 128, 1)\"><paramref name=\"httpContext\" /></span><span style=\"color: rgba(0, 128, 0, 1)\"> parameter is null.</span><span style=\"color: rgba(128, 128, 128, 1)\"></exception></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">protected</span> <span style=\"color: rgba(0, 0, 255, 1)\">virtual</span> <span style=\"color: rgba(0, 0, 255, 1)\">bool</span><span style=\"color: rgba(0, 0, 0, 1)\"> AuthorizeCore(HttpContextBase httpContext)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (httpContext == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">httpContext</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n IPrincipal user </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> httpContext.User;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> user.Identity.IsAuthenticated && (<span style=\"color: rgba(0, 0, 255, 1)\">this</span>._usersSplit.Length <= <span style=\"color: rgba(128, 0, 128, 1)\">0</span> || <span style=\"color: rgba(0, 0, 255, 1)\">this</span>._usersSplit.Contains(user.Identity.Name, StringComparer.OrdinalIgnoreCase)) && (<span style=\"color: rgba(0, 0, 255, 1)\">this</span>._rolesSplit.Length <= <span style=\"color: rgba(128, 0, 128, 1)\">0</span> || <span style=\"color: rgba(0, 0, 255, 1)\">this</span>._rolesSplit.Any(<span style=\"color: rgba(0, 0, 255, 1)\">new</span> Func<<span style=\"color: rgba(0, 0, 255, 1)\">string</span>, <span style=\"color: rgba(0, 0, 255, 1)\">bool</span>><span style=\"color: rgba(0, 0, 0, 1)\">(user.IsInRole)));\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">private</span> <span style=\"color: rgba(0, 0, 255, 1)\">void</span> CacheValidateHandler(HttpContext context, <span style=\"color: rgba(0, 0, 255, 1)\">object</span> data, <span style=\"color: rgba(0, 0, 255, 1)\">ref</span><span style=\"color: rgba(0, 0, 0, 1)\"> HttpValidationStatus validationStatus)\r\n {\r\n validationStatus </span>= <span style=\"color: rgba(0, 0, 255, 1)\">this</span>.OnCacheAuthorization(<span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> HttpContextWrapper(context));\r\n }\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">Called when a process requests authorization.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"filterContext\"></span><span style=\"color: rgba(0, 128, 0, 1)\">The filter context, which encapsulates information for using </span><span style=\"color: rgba(128, 128, 128, 1)\"><see cref=\"T:System.Web.Mvc.AuthorizeAttribute\" /></span><span style=\"color: rgba(0, 128, 0, 1)\">.</span><span style=\"color: rgba(128, 128, 128, 1)\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><exception cref=\"T:System.ArgumentNullException\"></span><span style=\"color: rgba(0, 128, 0, 1)\">The </span><span style=\"color: rgba(128, 128, 128, 1)\"><paramref name=\"filterContext\" /></span><span style=\"color: rgba(0, 128, 0, 1)\"> parameter is null.</span><span style=\"color: rgba(128, 128, 128, 1)\"></exception></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">public</span> <span style=\"color: rgba(0, 0, 255, 1)\">virtual</span> <span style=\"color: rgba(0, 0, 255, 1)\">void</span><span style=\"color: rgba(0, 0, 0, 1)\"> OnAuthorization(AuthorizationContext filterContext)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (filterContext == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">filterContext</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> (OutputCacheAttribute.IsChildActionCacheActive(filterContext))\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (<span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.AuthorizeCore(filterContext.HttpContext))\r\n {\r\n HttpCachePolicyBase cache </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> filterContext.HttpContext.Response.Cache;\r\n cache.SetProxyMaxAge(</span><span style=\"color: rgba(0, 0, 255, 1)\">new</span> TimeSpan(<span style=\"color: rgba(128, 0, 128, 1)\">0L</span><span style=\"color: rgba(0, 0, 0, 1)\">));\r\n cache.AddValidationCallback(</span><span style=\"color: rgba(0, 0, 255, 1)\">new</span> HttpCacheValidateHandler(<span style=\"color: rgba(0, 0, 255, 1)\">this</span>.CacheValidateHandler), <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\">;\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.HandleUnauthorizedRequest(filterContext);\r\n }\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">Processes HTTP requests that fail authorization.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"filterContext\"></span><span style=\"color: rgba(0, 128, 0, 1)\">Encapsulates the information for using </span><span style=\"color: rgba(128, 128, 128, 1)\"><see cref=\"T:System.Web.Mvc.AuthorizeAttribute\" /></span><span style=\"color: rgba(0, 128, 0, 1)\">. The </span><span style=\"color: rgba(128, 128, 128, 1)\"><paramref name=\"filterContext\" /></span><span style=\"color: rgba(0, 128, 0, 1)\"> object contains the controller, HTTP context, request context, action result, and route data.</span><span style=\"color: rgba(128, 128, 128, 1)\"></param></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">protected</span> <span style=\"color: rgba(0, 0, 255, 1)\">virtual</span> <span style=\"color: rgba(0, 0, 255, 1)\">void</span><span style=\"color: rgba(0, 0, 0, 1)\"> HandleUnauthorizedRequest(AuthorizationContext filterContext)\r\n {\r\n filterContext.Result </span>= <span style=\"color: rgba(0, 0, 255, 1)\">new</span><span style=\"color: rgba(0, 0, 0, 1)\"> HttpUnauthorizedResult();\r\n }\r\n </span><span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><summary></span><span style=\"color: rgba(0, 128, 0, 1)\">Called when the caching module requests authorization.</span><span style=\"color: rgba(128, 128, 128, 1)\"></summary></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><returns></span><span style=\"color: rgba(0, 128, 0, 1)\">A reference to the validation status.</span><span style=\"color: rgba(128, 128, 128, 1)\"></returns></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><param name=\"httpContext\"></span><span style=\"color: rgba(0, 128, 0, 1)\">The HTTP context, which encapsulates all HTTP-specific information about an individual HTTP request.</span><span style=\"color: rgba(128, 128, 128, 1)\"></param></span>\r\n <span style=\"color: rgba(128, 128, 128, 1)\">///</span> <span style=\"color: rgba(128, 128, 128, 1)\"><exception cref=\"T:System.ArgumentNullException\"></span><span style=\"color: rgba(0, 128, 0, 1)\">The </span><span style=\"color: rgba(128, 128, 128, 1)\"><paramref name=\"httpContext\" /></span><span style=\"color: rgba(0, 128, 0, 1)\"> parameter is null.</span><span style=\"color: rgba(128, 128, 128, 1)\"></exception></span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">protected</span> <span style=\"color: rgba(0, 0, 255, 1)\">virtual</span><span style=\"color: rgba(0, 0, 0, 1)\"> HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (httpContext == <span style=\"color: rgba(0, 0, 255, 1)\">null</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">throw</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> ArgumentNullException(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">httpContext</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">);\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (!<span style=\"color: rgba(0, 0, 255, 1)\">this</span><span style=\"color: rgba(0, 0, 0, 1)\">.AuthorizeCore(httpContext))\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> HttpValidationStatus.IgnoreThisRequest;\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> HttpValidationStatus.Valid;\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">internal</span> <span style=\"color: rgba(0, 0, 255, 1)\">static</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span>[] SplitString(<span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\"> original)\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> (<span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\">.IsNullOrEmpty(original))\r\n {\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> <span style=\"color: rgba(0, 0, 255, 1)\">new</span> <span style=\"color: rgba(0, 0, 255, 1)\">string</span>[<span style=\"color: rgba(128, 0, 128, 1)\">0</span><span style=\"color: rgba(0, 0, 0, 1)\">];\r\n }\r\n IEnumerable</span><<span style=\"color: rgba(0, 0, 255, 1)\">string</span>> source = \r\n <span style=\"color: rgba(0, 0, 255, 1)\">from</span> piece <span style=\"color: rgba(0, 0, 255, 1)\">in</span> original.Split(<span style=\"color: rgba(0, 0, 255, 1)\">new</span> <span style=\"color: rgba(0, 0, 255, 1)\">char</span><span style=\"color: rgba(0, 0, 0, 1)\">[]\r\n {\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">,</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n })\r\n let trimmed </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> piece.Trim()\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">where</span> !<span style=\"color: rgba(0, 0, 255, 1)\">string</span><span style=\"color: rgba(0, 0, 0, 1)\">.IsNullOrEmpty(trimmed)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">select</span><span style=\"color: rgba(0, 0, 0, 1)\"> trimmed;\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> source.ToArray<<span style=\"color: rgba(0, 0, 255, 1)\">string</span>><span style=\"color: rgba(0, 0, 0, 1)\">();\r\n }\r\n }\r\n}</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">AuthorizeAttribute</span></div>\r\n<p><span style=\"color: rgba(136, 136, 136, 1)\">==注意:如果在Controller上应用多个不同的IAuthorizationFilter过滤器,他们执行的顺序:</span>由下向上。</p>\r\n<p> 11-2、IActionFilter--->Action方法内部代码--->IResultFilter</p>\r\n<p> IActionFilter有两个方法OnActionExecuting(在执行操作方法之前调用)、OnActionExecuted(在执行操作方法后调用)。IResultFilter也有两个方法OnResultExecuting(在操作结果执行之前调用)、OnResultExecuted(在操作结果执行后调用),由于这里说的【在执行操作方法后调用】和【在操作结果执行之前调用】容易造成混淆,这里我们就来确定的说明一下其执行流程为:OnActionExecuting--->OnActionExecuted--->Action方法内的代码--->OnResultExecuting--->OnResultExecuted</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_552063\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div><div class=\"line number27 index26 alt2\">27</div><div class=\"line number28 index27 alt1\">28</div><div class=\"line number29 index28 alt2\">29</div><div class=\"line number30 index29 alt1\">30</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyActionFilter :FilterAttribute, IActionFilter</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">OnActionExecuted(ActionExecutedContext filterContext)</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果此处为filterContext.Result赋一个ActionResult对象,则MVC不会再继续执行下面的过滤器,而是直接根据这个ActionResult对象进行View的呈现。</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果filterContext.Result为null,则MVC按照 Action方法内返回的ActionResult进行View的呈现</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number8 index7 alt1\"> </div><div class=\"line number9 index8 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">OnActionExecuting(ActionExecutingContext filterContext)</code></div><div class=\"line number10 index9 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number11 index10 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果此处为filterContext.Result赋一个ActionResult对象,则MVC不会再继续执行下面的过滤器和Action方法,而是直接根据这个ActionResult对象进行View的呈现。</code></div><div class=\"line number12 index11 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果filterContext.Result为null,则MVC继续执行之后的各个过滤器和Action方法!</code></div><div class=\"line number13 index12 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number14 index13 alt1\"><code class=\"csharp plain\">}</code></div><div class=\"line number15 index14 alt2\"> </div><div class=\"line number16 index15 alt1\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyResultFilter : FilterAttribute,IResultFilter</code></div><div class=\"line number17 index16 alt2\"><code class=\"csharp plain\">{</code></div><div class=\"line number18 index17 alt1\"> </div><div class=\"line number19 index18 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">OnResultExecuted(ResultExecutedContext filterContext)</code></div><div class=\"line number20 index19 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number21 index20 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果此处为filterContext.Result赋一个ActionResult对象,MVC会直接根据这个ActionResult对象进行View的呈现。</code></div><div class=\"line number22 index21 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果filterContext.Result为null,则MVC按照 Action方法内返回的ActionResult进行View的呈现</code></div><div class=\"line number23 index22 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number24 index23 alt1\"> </div><div class=\"line number25 index24 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">OnResultExecuting(ResultExecutingContext filterContext)</code></div><div class=\"line number26 index25 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number27 index26 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果此处为filterContext.Result赋一个ActionResult对象,MVC会直接根据这个ActionResult对象进行View的呈现。</code></div><div class=\"line number28 index27 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果filterContext.Result为null,则MVC按照 Action方法内返回的ActionResult进行View的呈现</code></div><div class=\"line number29 index28 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number30 index29 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p> 11-3、IExceptionFilter</p>\r\n<p> Action方法上应用该特性后,如果执行:IAuthorizationFilter过滤器、IActionFilter过滤器、Action方法内的代码、IResultFilter过滤器,抛出了异常,则会执行该方法!(只要出现有异常,则不会再继续往下执行后面的过滤器)</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_890137\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyExceptionFilter : FilterAttribute, IExceptionFilter</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">OnException(ExceptionContext filterContext)</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//如果filterContext.ExceptionHandled = false(默认),则直接抛出异常。(filterContext.ExceptionHandled表示是否已经处理异常)</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp comments\">//否则,为filterContext.Result赋一个ActionResult,使用这个ActionResult执行View的呈现!</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><strong>12、</strong>自定义ActionResult</p>\r\n<p> 自定义一个ActionResult,只需要继承抽象类ActionResult,并实现其抽象方法ExecuteResult即可!微软中已经定义很多ActionResult(EmptyResult、ContentResult、JsonResult、ViewResult等)。</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_493419\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyActionResult : ActionResult</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">override</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">ExecuteResult(ControllerContext context)</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">HttpContext.Current.Response.Write(</code><code class=\"csharp string\">\"自定义的ActionResult\"</code><code class=\"csharp plain\">);</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>使用时,只需要创建一个MyActionResult对象并让Action方法将其返回,或者在第11中任何一个过滤器中创建一个MyActionResult对象并赋值给filterContext.Result。下面是两个使用MyActionResult的例子:</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_926460\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">HomeController : Controller</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">ActionResult Index()</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">MyActionResult();</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">} </code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_957601\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">HomeController : Controller</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">[MyAuthroizeFilter]</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">ActionResult Index()</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp plain\">Content(</code><code class=\"csharp string\">\"123\"</code><code class=\"csharp plain\">);</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">} </code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp plain\">}</code></div><div class=\"line number9 index8 alt2\"> </div><div class=\"line number10 index9 alt1\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyAuthroizeFilter : FilterAttribute, IAuthorizationFilter</code></div><div class=\"line number11 index10 alt2\"><code class=\"csharp plain\">{</code></div><div class=\"line number12 index11 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">OnAuthorization(AuthorizationContext filterContext)</code></div><div class=\"line number13 index12 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number14 index13 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">filterContext.Result = </code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">MyActionResult();</code></div><div class=\"line number15 index14 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number16 index15 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>定义一个生成验证码的VerifyCodeResult示例:<a href=\"https://files.cnblogs.com/wupeiqi/MvcExtension_12.rar\" rel=\"noopener\">源码下载</a></p>\r\n<p><strong>13、</strong>自定义HtmlHelper</p>\r\n<p> 在 .cshtml 文件中 使用的 @Html.TextBox(...)等,他们都是HtmlHelper类的扩展方法(定义在System.Web.Mvc.Html.InputExtensions中),更多关于@Html.xxx()方法的详细介绍请:<a href=\"http://www.cnblogs.com/wupeiqi/p/3511526.html\" rel=\"noopener\">猛击这里</a></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_769831\" class=\"syntaxhighlighter collapsed csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">static</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MyHtmlHelperExtensions</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">static</code> <code class=\"csharp plain\">MvcHtmlString MyControl(</code><code class=\"csharp keyword\">this</code> <code class=\"csharp plain\">HtmlHelper html, </code><code class=\"csharp keyword\">string</code> <code class=\"csharp plain\">str)</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp plain\">MvcHtmlString.Create(</code><code class=\"csharp string\">\"自定义Html标签\"</code><code class=\"csharp plain\">);</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number7 index6 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>使用HtmlHelper扩展开发一个【分页功能】:<a href=\"https://files.cnblogs.com/wupeiqi/MvcExtension_13_MvcPage.rar\" rel=\"noopener\">源码下载</a></p>\r\n<p><strong>14、</strong>自定义ModelBinder</p>\r\n<p><strong>15、</strong>自定义ValueProvider</p>\r\n<p> 在学习 第14、15 扩展点之前,先来思考下! 在我们定义的Action方法中,他们的参数值是如何得到的呢? <br> 答:通过这第14、15个扩展点会让你对参数值的得到有个清楚的认识!在我的《白话学习MVC系列》的模型绑定一篇中已经做了详细的介绍!<a href=\"http://www.cnblogs.com/wupeiqi/p/3377854.html\" rel=\"noopener\">【猛击这里】</a></p>\r\n<p>下面的第16、17扩展点是【View呈现】步骤中,寻找【视图页】过程中用到的,详细介绍:<a href=\"http://www.cnblogs.com/wupeiqi/p/3597845.html\" rel=\"noopener\">猛击这里</a></p>\r\n<p><strong>16、</strong><span>指定DefaultDisplayMode<br><span>模拟需求:对Phone端用户的某个Action请求,返回电脑版网页。</span><br></span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_762277\" class=\"syntaxhighlighter csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp plain\">ActionResult Index()</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">this</code><code class=\"csharp plain\">.ControllerContext.DisplayMode = DisplayModeProvider.Instance.Modes[1];</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">DisplayModeProvider.Instance.RequireConsistentDisplayMode = </code><code class=\"csharp keyword\">true</code><code class=\"csharp plain\">;</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">return</code> <code class=\"csharp plain\">View();</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><span> 根据上述设置,即使是Phone端的请求并且还存在Index.Mobile.cshtml文件,也会去执行Index.cshtml,即:实现Phone用户访问电脑版网页。</span></p>\r\n<p><span><strong>17、</strong><span>自定义DefaultDisplayMode<br><span>模拟需求:为Android 2.3用户设置特定的页面</span><br><span>先创建一个类似于Index.Android23.cshtml 的页面,然后在Global.asax中做如下设置即可:</span><br></span></span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_883823\" class=\"syntaxhighlighter csharp\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"csharp keyword\">public</code> <code class=\"csharp keyword\">class</code> <code class=\"csharp plain\">MvcApplication : System.Web.HttpApplication</code></div><div class=\"line number2 index1 alt1\"><code class=\"csharp plain\">{</code></div><div class=\"line number3 index2 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp keyword\">protected</code> <code class=\"csharp keyword\">void</code> <code class=\"csharp plain\">Application_Start()</code></div><div class=\"line number4 index3 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number5 index4 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">AreaRegistration.RegisterAllAreas();</code></div><div class=\"line number6 index5 alt1\"><code class=\"csharp spaces\"> </code> </div><div class=\"line number7 index6 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">WebApiConfig.Register(GlobalConfiguration.Configuration);</code></div><div class=\"line number8 index7 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);</code></div><div class=\"line number9 index8 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">RouteConfig.RegisterRoutes(RouteTable.Routes);</code></div><div class=\"line number10 index9 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">BundleConfig.RegisterBundles(BundleTable.Bundles);</code></div><div class=\"line number11 index10 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">AuthConfig.RegisterAuth();</code></div><div class=\"line number12 index11 alt1\"><code class=\"csharp spaces\"> </code> </div><div class=\"line number13 index12 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">DisplayModeProvider.Instance.Modes.Insert(0, </code><code class=\"csharp keyword\">new</code> <code class=\"csharp plain\">DefaultDisplayMode(</code><code class=\"csharp string\">\"Android23\"</code><code class=\"csharp plain\">)</code></div><div class=\"line number14 index13 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">{</code></div><div class=\"line number15 index14 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">ContextCondition = (context => context.GetOverriddenUserAgent().IndexOf</code></div><div class=\"line number16 index15 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">(</code><code class=\"csharp string\">\"Android 2.3\"</code><code class=\"csharp plain\">, StringComparison.OrdinalIgnoreCase) >= 0)</code></div><div class=\"line number17 index16 alt2\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">});</code></div><div class=\"line number18 index17 alt1\"><code class=\"csharp spaces\"> </code><code class=\"csharp plain\">}</code></div><div class=\"line number19 index18 alt2\"><code class=\"csharp plain\">}</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p> </p>\r\n<p><span><span>如果还有没提到的扩展点,请指出!!!</span></span></p>\r\n<p> </p>\r\n</div>', '2022-08-01', 2, 0, 20, 1, 1);
INSERT INTO `app01_article` VALUES (2, '路过面了个试就拿到2个offer。是运气吗?', '路过随便面个试就拿到2个offer。是运气吗? #复习很重要#看看面试问的问题,再瞧瞧师兄的学习态度,你就明白 机会为何总与你擦肩而过了。[玫瑰] 以下是我和师兄的聊天记录,你会几个?', '<div id=\"cnblogs_post_body\" class=\"blogpost-body blogpost-body-html\">\r\n<p><span style=\"font-size: 13px\">上一篇<a href=\"http://www.cnblogs.com/wupeiqi/p/4375610.html\" target=\"_blank\" rel=\"noopener\">《白话tornado源码之待请求阶段》</a>中介绍了tornado框架在客户端请求之前所做的准备(下图1、2部分),本质上就是创建了一个socket服务端,并进行了IP和端口的绑定,但是未执行 socket的accept方法,也就是未获取客户端请求信息。</span></p>\r\n<h3>概述<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><img src=\"https://images0.cnblogs.com/blog2015/425762/201506/171124357959505.png\" alt=\"\" width=\"881\" height=\"442\" class=\"medium-zoom-image\"></p>\r\n<p><span style=\"font-size: 13px\">本篇就来详细介绍tornado服务器(socket服务端)是如何接收用户请求数据以及如果根据用户请求的URL处理并返回数据,也就是上图的3系列所有步骤,如上图【start】是一个死循环,其中利用epoll监听服务端socket句柄,一旦客户端发送请求,则立即调用HttpServer对象的_handle_events方法来进行请求的处理。</span></p>\r\n<p><span style=\"font-size: 13px\">对于整个3系列按照功能可以划分为四大部分:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\">获取用户请求数据(上图3.4)</span></li>\r\n<li><span style=\"font-size: 13px\">根据用户请求URL进行路由匹配,从而使得某个方法处理具体的请求(上图3.5~3.19)</span></li>\r\n<li><span style=\"font-size: 13px\">将处理后的数据返回给客户端(上图3.21~3.23)</span></li>\r\n<li><span style=\"font-size: 13px\">关闭客户端socket(上图3.24~3.26)</span></li>\r\n</ul>\r\n<h3>3.1、HTTPServer对象的_handle_events方法<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>此处代码主要有三项任务:</p>\r\n<p> 1、 socket.accept() 接收了客户端请求。<br> 2、创建封装了客户端socket对象和IOLoop对象的IOStream实例(用于之后获取或输出数据)。<br> 3、创建HTTPConnection对象,其内容是实现整个功能的逻辑。</p>\r\n<div class=\"cnblogs_code\"><div class=\"cnblogs_code_toolbar\"><span class=\"cnblogs_code_copy\"><a href=\"javascript:void(0);\" onclick=\"copyCnblogsCode(this)\" title=\"复制代码\"><img src=\"//common.cnblogs.com/images/copycode.gif\" alt=\"复制代码\"></a></span></div>\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> HTTPServer(object):\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> _handle_events(self, fd, events):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">while</span><span style=\"color: rgba(0, 0, 0, 1)\"> True:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">try</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">======== 获取客户端请求 =========#</span>\r\n <span style=\"color: rgba(0, 0, 0, 1)\"><strong>connection, address = self._socket.accept()\r\n </strong></span><span style=\"color: rgba(136, 136, 136, 1)\">except socket.error, e:\r\n if e.args[0] in (errno.EWOULDBLOCK, errno.EAGAIN):\r\n return\r\n raise\r\n if self.ssl_options is not None:\r\n assert ssl, \"Python 2.6+ and OpenSSL required for SSL\"\r\n try:\r\n connection = ssl.wrap_socket(connection,\r\n server_side=True,\r\n do_handshake_on_connect=False,\r\n **self.ssl_options)\r\n except ssl.SSLError, err:\r\n if err.args[0] == ssl.SSL_ERROR_EOF:\r\n return connection.close()\r\n else:\r\n raise\r\n except socket.error, err:\r\n if err.args[0] == errno.ECONNABORTED:\r\n return connection.close()\r\n else:\r\n raise</span>\r\n <span style=\"color: rgba(136, 136, 136, 1)\"> try:\r\n #这是的条件是选择https和http请求方式\r\n if self.ssl_options is not None:\r\n stream = iostream.SSLIOStream(connection, io_loop=self.io_loop)\r\n else:\r\n #将客户端socket对象和IOLoop对象封装到IOStream对象中\r\n #IOStream用于从客户端socket中读取请求信息</span>\r\n <strong>stream = iostream.IOStream(connection, io_loop=<span style=\"color: rgba(0, 0, 0, 1)\">self.io_loop)\r\n </span></strong><span style=\"color: rgba(136, 136, 136, 1)\">#创建HTTPConnection对象\r\n #address是客户端IPdizhi\r\n #self.request_callback是Application对象,其中包含了:url映射关系和配置文件等..\r\n #so,HTTPConnection的构造函数就是下一步处理请求的位置了..\r\n<span style=\"color: rgba(255, 0, 0, 1)\"><strong> HTTPConnection(stream, address, self.request_callback,self.no_keep_alive, self.xheaders)\r\n </strong></span></span><span style=\"color: rgba(128, 128, 128, 1)\">except:\r\n logging.error(\"Error in connection callback\", exc_info=True)</span></pre>\r\n<div class=\"cnblogs_code_toolbar\"><span class=\"cnblogs_code_copy\"><a href=\"javascript:void(0);\" onclick=\"copyCnblogsCode(this)\" title=\"复制代码\"><img src=\"//common.cnblogs.com/images/copycode.gif\" alt=\"复制代码\"></a></span></div></div>\r\n<h3>3.2、IOStream的__init__方法<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>此处代码主要两项目任务:</p>\r\n<ul>\r\n<li>封装客户端socket和其他信息,以便之后执行该对象的其他方法获取客户端请求的数据和响应客户信息</li>\r\n<li>将客户端socket对象添加到epoll,并且指定当客户端socket对象变化时,就去执行 IOStream的_handle_events方法(调用socket.send给用户响应数据)</li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_687380\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">IOStream(</code><code class=\"python functions\">object</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">__init__(</code><code class=\"python color1\">self</code><code class=\"python plain\">, socket, io_loop</code><code class=\"python keyword\">=</code><code class=\"python color1\">None</code><code class=\"python plain\">, max_buffer_size</code><code class=\"python keyword\">=</code><code class=\"python value\">104857600</code><code class=\"python plain\">,</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">read_chunk_size</code><code class=\"python keyword\">=</code><code class=\"python value\">4096</code><code class=\"python plain\">):</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#客户端socket对象</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.socket </code><code class=\"python keyword\">=</code> <code class=\"python plain\">socket</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.socket.setblocking(</code><code class=\"python color1\">False</code><code class=\"python plain\">)</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop </code><code class=\"python keyword\">=</code> <code class=\"python plain\">io_loop </code><code class=\"python keyword\">or</code> <code class=\"python plain\">ioloop.IOLoop.instance()</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.max_buffer_size </code><code class=\"python keyword\">=</code> <code class=\"python plain\">max_buffer_size</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.read_chunk_size </code><code class=\"python keyword\">=</code> <code class=\"python plain\">read_chunk_size</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._read_buffer </code><code class=\"python keyword\">=</code> <code class=\"python plain\">collections.deque()</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer </code><code class=\"python keyword\">=</code> <code class=\"python plain\">collections.deque()</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer_frozen </code><code class=\"python keyword\">=</code> <code class=\"python color1\">False</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._read_delimiter </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._read_bytes </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._read_callback </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._write_callback </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._close_callback </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._connect_callback </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._connecting </code><code class=\"python keyword\">=</code> <code class=\"python color1\">False</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._state </code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.ERROR</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">with stack_context.NullContext():</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#将客户端socket句柄添加的epoll中,并将IOStream的_handle_events方法添加到 Start 的While循环中</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#Start 的While循环中监听客户端socket句柄的状态,以便再最后调用IOStream的_handle_events方法把处理后的信息响应给用户</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.add_handler(</code><code class=\"python color1\">self</code><code class=\"python plain\">.socket.fileno(), </code><code class=\"python color1\">self</code><code class=\"python plain\">._handle_events, </code><code class=\"python color1\">self</code><code class=\"python plain\">._state)</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<h3>3.3、HTTPConnections的__init__方法<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>此处代码主要两项任务:</p>\r\n<ul>\r\n<li>获取请求数据</li>\r\n<li>调用 _on_headers 继续处理请求</li>\r\n</ul>\r\n<p>对于获取请求数据,其实就是执行IOStream的read_until函数来完成,其内部通过socket.recv(4096)方法获取客户端请求的数据,并以 【\\r\\n\\r\\n】作为请求信息结束符<span style=\"color: rgba(136, 136, 136, 1)\">(http请求头和内容通过\\r\\n\\r\\n分割)</span>。</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_332027\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">HTTPConnection(</code><code class=\"python functions\">object</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code> </div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">__init__(</code><code class=\"python color1\">self</code><code class=\"python plain\">, stream, address, request_callback, no_keep_alive</code><code class=\"python keyword\">=</code><code class=\"python color1\">False</code><code class=\"python plain\">,xheaders</code><code class=\"python keyword\">=</code><code class=\"python color1\">False</code><code class=\"python plain\">):</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code> </div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.stream </code><code class=\"python keyword\">=</code> <code class=\"python plain\">stream </code><code class=\"python comments\">#stream是封装了客户端socket和IOLoop实例的IOStream对象</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.address </code><code class=\"python keyword\">=</code> <code class=\"python plain\">address </code><code class=\"python comments\">#address是客户端IP地址</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.request_callback </code><code class=\"python keyword\">=</code> <code class=\"python plain\">request_callback </code><code class=\"python comments\">#request_callback是封装了URL映射和配置文件的Application对象。</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.no_keep_alive </code><code class=\"python keyword\">=</code> <code class=\"python plain\">no_keep_alive</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.xheaders </code><code class=\"python keyword\">=</code> <code class=\"python plain\">xheaders</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._request </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._request_finished </code><code class=\"python keyword\">=</code> <code class=\"python color1\">False</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#获取请求信息(请求头和内容),然后执行 HTTPConnection的_on_headers方法继续处理请求</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._header_callback </code><code class=\"python keyword\">=</code> <code class=\"python plain\">stack_context.wrap(</code><code class=\"python color1\">self</code><code class=\"python plain\">._on_headers)</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.stream.read_until(</code><code class=\"python string\">\"\\r\\n\\r\\n\"</code><code class=\"python plain\">, </code><code class=\"python color1\">self</code><code class=\"python plain\">._header_callback)</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><strong><span style=\"font-size: 13px\">请求数据格式:</span></strong></p>\r\n<blockquote>\r\n<p><span style=\"color: rgba(153, 153, 153, 1)\"><em><span style=\"font-size: 12px\">GET / HTTP/1.1</span></em></span><br><span style=\"color: rgba(153, 153, 153, 1)\"><em><span style=\"font-size: 12px\">Host: localhost:8888</span></em></span><br><span style=\"color: rgba(153, 153, 153, 1)\"><em><span style=\"font-size: 12px\">Connection: keep-alive</span></em></span><br><span style=\"color: rgba(153, 153, 153, 1)\"><em><span style=\"font-size: 12px\">Cache-Control: max-age=0</span></em></span><br><span style=\"color: rgba(153, 153, 153, 1)\"><em><span style=\"font-size: 12px\">Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8</span></em></span><br><span style=\"color: rgba(153, 153, 153, 1)\"><em><span style=\"font-size: 12px\">User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36</span></em></span><br><span style=\"color: rgba(153, 153, 153, 1)\"><em><span style=\"font-size: 12px\">Accept-Encoding: gzip, deflate, sdch</span></em></span><br><span style=\"color: rgba(153, 153, 153, 1)\"><em><span style=\"font-size: 12px\">Accept-Language: zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4</span></em></span><br><span style=\"color: rgba(153, 153, 153, 1)\"><em><span style=\"font-size: 12px\">If-None-Match: \"e02aa1b106d5c7c6a98def2b13005d5b84fd8dc8\"</span></em></span></p>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n</blockquote>\r\n<p><strong><span style=\"font-size: 13px\">详细代码解析:</span></strong></p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_1112aa83-0599-4b55-9d8a-64b8e96d5563\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_1112aa83-0599-4b55-9d8a-64b8e96d5563\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_1112aa83-0599-4b55-9d8a-64b8e96d5563\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> read_until(self, delimiter, callback):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Call callback when we read the given delimiter.</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">assert</span> <span style=\"color: rgba(0, 0, 255, 1)\">not</span> self._read_callback, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Already reading</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">终止界定 \\r\\n\\r\\n</span>\r\n self._read_delimiter =<span style=\"color: rgba(0, 0, 0, 1)\"> delimiter\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">回调函数,即:HTTPConnection的 _on_headers 方法</span>\r\n self._read_callback =<span style=\"color: rgba(0, 0, 0, 1)\"> stack_context.wrap(callback)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">while</span><span style=\"color: rgba(0, 0, 0, 1)\"> True:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">代码概述:</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">先从socket中读取信息并保存到buffer中</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">然后再读取buffer中的数据,以其为参数执行回调函数(HTTPConnection的 _on_headers 方法)</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">buffer其实是一个线程安装的双端队列collections.deque</span>\r\n \r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">从buffer中读取数据,并执行回调函数。</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">注意:首次执行时buffer中没有数据</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> self._read_from_buffer():\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n self._check_closed()\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">从socket中读取信息到buffer(线程安全的一个双向消息队列)</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span> self._read_to_buffer() ==<span style=\"color: rgba(0, 0, 0, 1)\"> 0:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">break</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n \r\n self._add_io_state(self.io_loop.READ)</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream.read_until</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_bc03fcdf-5b1f-4f07-b432-f1294d634cd3\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_bc03fcdf-5b1f-4f07-b432-f1294d634cd3\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_bc03fcdf-5b1f-4f07-b432-f1294d634cd3\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> _read_to_buffer(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">省略部分代码</span>\r\n chunk =<span style=\"color: rgba(0, 0, 0, 1)\"> self._read_from_socket()\r\n self._read_buffer.append(chunk)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> len(chunk)\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> _read_from_socket(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">socket对象的recv函数接收数据</span>\r\n \r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">read_chunk_size在构造函数中默认设置为:4096</span>\r\n chunk =<span style=\"color: rgba(0, 0, 0, 1)\"> self.socket.recv(self.read_chunk_size)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> <span style=\"color: rgba(0, 0, 255, 1)\">not</span><span style=\"color: rgba(0, 0, 0, 1)\"> chunk:\r\n self.close()\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> None\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> chunk</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream._read_to_buffer</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_273264bf-ee29-4076-8cf9-a7eb9ea7bec0\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_273264bf-ee29-4076-8cf9-a7eb9ea7bec0\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_273264bf-ee29-4076-8cf9-a7eb9ea7bec0\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> _read_from_buffer(self):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Attempts to complete the currently-pending read from the buffer.\r\n\r\n Returns True if the read was completed.\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">构造函数中默认设置为None</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> self._read_bytes:\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> self._read_buffer_size() >=<span style=\"color: rgba(0, 0, 0, 1)\"> self._read_bytes:\r\n num_bytes </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> self._read_bytes\r\n callback </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> self._read_callback\r\n self._read_callback </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> None\r\n self._read_bytes </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> None\r\n self._run_callback(callback, self._consume(num_bytes))\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> True\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">_read_delimiter的值为 \\r\\n\\r\\n</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">elif</span><span style=\"color: rgba(0, 0, 0, 1)\"> self._read_delimiter:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">buffer列表首元素合并,合并详细见_merge_prefix函数</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\"> _merge_prefix(self._read_buffer, sys.maxint)\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">获取 \\r\\n\\r\\n 所在 buffer 首元素的位置索引</span>\r\n loc =<span style=\"color: rgba(0, 0, 0, 1)\"> self._read_buffer[0].find(self._read_delimiter)\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> loc != -1<span style=\"color: rgba(0, 0, 0, 1)\">:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">如果在请求中找到了 \\r\\n\\r\\n</span>\r\n \r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">self._read_callback 是HTTPConnection对象的 _on_headers 方法</span>\r\n callback =<span style=\"color: rgba(0, 0, 0, 1)\"> self._read_callback\r\n delimiter_len </span>= len(self._read_delimiter) <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">获取 \\r\\n\\r\\n 的长度</span>\r\n self._read_callback =<span style=\"color: rgba(0, 0, 0, 1)\"> None\r\n self._read_delimiter </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> None\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">============ 执行HTTPConnection对象的 _on_headers 方法 =============</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">self._consume(loc + delimiter_len)用来获取 buffer 的首元素(请求的信息其实就被封装到了buffer的首个元素中)</span>\r\n self._run_callback(callback,self._consume(loc +<span style=\"color: rgba(0, 0, 0, 1)\"> delimiter_len))\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> True\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> False</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream._read_from_buffer</span></div>\r\n<h3>3.4、HTTPConnnection的 _on_headers 方法(含3.5)<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>上述代码主要有两个任务:</p>\r\n<ul>\r\n<li>根据获取的请求信息生成响应的请求头键值对,并把信息封装到HttpRequest对象中</li>\r\n<li>调用Application的__call__方法,继续处理请求</li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_227144\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div><div class=\"line number27 index26 alt2\">27</div><div class=\"line number28 index27 alt1\">28</div><div class=\"line number29 index28 alt2\">29</div><div class=\"line number30 index29 alt1\">30</div><div class=\"line number31 index30 alt2\">31</div><div class=\"line number32 index31 alt1\">32</div><div class=\"line number33 index32 alt2\">33</div><div class=\"line number34 index33 alt1\">34</div><div class=\"line number35 index34 alt2\">35</div><div class=\"line number36 index35 alt1\">36</div><div class=\"line number37 index36 alt2\">37</div><div class=\"line number38 index37 alt1\">38</div><div class=\"line number39 index38 alt2\">39</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">HTTPConnection(</code><code class=\"python functions\">object</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">_on_headers(</code><code class=\"python color1\">self</code><code class=\"python plain\">, data):</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">try</code><code class=\"python plain\">:</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">data </code><code class=\"python keyword\">=</code> <code class=\"python plain\">native_str(data.decode(</code><code class=\"python string\">\'latin1\'</code><code class=\"python plain\">))</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">eol </code><code class=\"python keyword\">=</code> <code class=\"python plain\">data.find(</code><code class=\"python string\">\"\\r\\n\"</code><code class=\"python plain\">)</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#获取请求的起始行数据,例如:GET / HTTP/1.1</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">start_line </code><code class=\"python keyword\">=</code> <code class=\"python plain\">data[:eol]</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">try</code><code class=\"python plain\">:</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#请求方式、请求地址、http版本号</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">method, uri, version </code><code class=\"python keyword\">=</code> <code class=\"python plain\">start_line.split(</code><code class=\"python string\">\" \"</code><code class=\"python plain\">)</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">except</code> <code class=\"python plain\">ValueError:</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">raise</code> <code class=\"python plain\">_BadRequestException(</code><code class=\"python string\">\"Malformed HTTP request line\"</code><code class=\"python plain\">)</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python plain\">version.startswith(</code><code class=\"python string\">\"HTTP/\"</code><code class=\"python plain\">):</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">raise</code> <code class=\"python plain\">_BadRequestException(</code><code class=\"python string\">\"Malformed HTTP version in HTTP Request-Line\"</code><code class=\"python plain\">)</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#把请求头信息包装到一个字典中。(不包括第一行)</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">headers </code><code class=\"python keyword\">=</code> <code class=\"python plain\">httputil.HTTPHeaders.parse(data[eol:])</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code> </div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#把请求信息封装到一个HTTPRequest对象中</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#注意:self._request = HTTPRequest,</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#HTTPRequest中封装了HTTPConnection</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#HTTPConnection中封装了stream和application</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._request </code><code class=\"python keyword\">=</code> <code class=\"python plain\">HTTPRequest(connection</code><code class=\"python keyword\">=</code><code class=\"python color1\">self</code><code class=\"python plain\">, method</code><code class=\"python keyword\">=</code><code class=\"python plain\">method, uri</code><code class=\"python keyword\">=</code><code class=\"python plain\">uri, version</code><code class=\"python keyword\">=</code><code class=\"python plain\">version,headers</code><code class=\"python keyword\">=</code><code class=\"python plain\">headers, remote_ip</code><code class=\"python keyword\">=</code><code class=\"python color1\">self</code><code class=\"python plain\">.address[</code><code class=\"python value\">0</code><code class=\"python plain\">])</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#从请求头中获取 Content-Length</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">content_length </code><code class=\"python keyword\">=</code> <code class=\"python plain\">headers.get(</code><code class=\"python string\">\"Content-Length\"</code><code class=\"python plain\">)</code></div><div class=\"line number25 index24 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">content_length:</code></div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">content_length </code><code class=\"python keyword\">=</code> <code class=\"python functions\">int</code><code class=\"python plain\">(content_length)</code></div><div class=\"line number27 index26 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">content_length > </code><code class=\"python color1\">self</code><code class=\"python plain\">.stream.max_buffer_size:</code></div><div class=\"line number28 index27 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">raise</code> <code class=\"python plain\">_BadRequestException(</code><code class=\"python string\">\"Content-Length too long\"</code><code class=\"python plain\">)</code></div><div class=\"line number29 index28 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">headers.get(</code><code class=\"python string\">\"Expect\"</code><code class=\"python plain\">) </code><code class=\"python keyword\">=</code><code class=\"python keyword\">=</code> <code class=\"python string\">\"100-continue\"</code><code class=\"python plain\">:</code></div><div class=\"line number30 index29 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.stream.write(</code><code class=\"python string\">\"HTTP/1.1 100 (Continue)\\r\\n\\r\\n\"</code><code class=\"python plain\">)</code></div><div class=\"line number31 index30 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.stream.read_bytes(content_length, </code><code class=\"python color1\">self</code><code class=\"python plain\">._on_request_body)</code></div><div class=\"line number32 index31 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number33 index32 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#**************** 执行Application对象的 __call__ 方法,也就是路由系统的入口 *******************</code></div><div class=\"line number34 index33 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.request_callback(</code><code class=\"python color1\">self</code><code class=\"python plain\">._request)</code></div><div class=\"line number35 index34 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">except</code> <code class=\"python plain\">_BadRequestException, e:</code></div><div class=\"line number36 index35 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">logging.info(</code><code class=\"python string\">\"Malformed HTTP request from %s: %s\"</code><code class=\"python plain\">,</code></div><div class=\"line number37 index36 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.address[</code><code class=\"python value\">0</code><code class=\"python plain\">], e)</code></div><div class=\"line number38 index37 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.stream.close()</code></div><div class=\"line number39 index38 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_7b5a3cb2-41fc-4beb-a255-a86db79b2034\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_7b5a3cb2-41fc-4beb-a255-a86db79b2034\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_7b5a3cb2-41fc-4beb-a255-a86db79b2034\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> HTTPRequest(object):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span>(self, method, uri, version=<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">HTTP/1.0</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, headers=<span style=\"color: rgba(0, 0, 0, 1)\">None,\r\n body</span>=None, remote_ip=None, protocol=None, host=<span style=\"color: rgba(0, 0, 0, 1)\">None,\r\n files</span>=None, connection=<span style=\"color: rgba(0, 0, 0, 1)\">None):\r\n self.method </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> method\r\n self.uri </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> uri\r\n self.version </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> version\r\n self.headers </span>= headers <span style=\"color: rgba(0, 0, 255, 1)\">or</span><span style=\"color: rgba(0, 0, 0, 1)\"> httputil.HTTPHeaders()\r\n self.body </span>= body <span style=\"color: rgba(0, 0, 255, 1)\">or</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"\"</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span> connection <span style=\"color: rgba(0, 0, 255, 1)\">and</span><span style=\"color: rgba(0, 0, 0, 1)\"> connection.xheaders:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> Squid uses X-Forwarded-For, others use X-Real-Ip</span>\r\n self.remote_ip =<span style=\"color: rgba(0, 0, 0, 1)\"> self.headers.get(\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">X-Real-Ip</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, self.headers.get(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">X-Forwarded-For</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">, remote_ip))\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> AWS uses X-Forwarded-Proto</span>\r\n self.protocol =<span style=\"color: rgba(0, 0, 0, 1)\"> self.headers.get(\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">X-Scheme</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, self.headers.get(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">X-Forwarded-Proto</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">, protocol))\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> self.protocol <span style=\"color: rgba(0, 0, 255, 1)\">not</span> <span style=\"color: rgba(0, 0, 255, 1)\">in</span> (<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">http</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">https</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">):\r\n self.protocol </span>= <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">http</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">else</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n self.remote_ip </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> remote_ip\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> protocol:\r\n self.protocol </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> protocol\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">elif</span> connection <span style=\"color: rgba(0, 0, 255, 1)\">and</span><span style=\"color: rgba(0, 0, 0, 1)\"> isinstance(connection.stream, \r\n iostream.SSLIOStream):\r\n self.protocol </span>= <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">https</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">else</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n self.protocol </span>= <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">http</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n self.host </span>= host <span style=\"color: rgba(0, 0, 255, 1)\">or</span> self.headers.get(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Host</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>) <span style=\"color: rgba(0, 0, 255, 1)\">or</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">127.0.0.1</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n self.files </span>= files <span style=\"color: rgba(0, 0, 255, 1)\">or</span><span style=\"color: rgba(0, 0, 0, 1)\"> {}\r\n self.connection </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> connection\r\n self._start_time </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> time.time()\r\n self._finish_time </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> None\r\n\r\n scheme, netloc, path, query, fragment </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> urlparse.urlsplit(uri)\r\n self.path </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> path\r\n self.query </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> query\r\n arguments </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> cgi.parse_qs(query)\r\n self.arguments </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> {}\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">for</span> name, values <span style=\"color: rgba(0, 0, 255, 1)\">in</span><span style=\"color: rgba(0, 0, 0, 1)\"> arguments.iteritems():\r\n values </span>= [v <span style=\"color: rgba(0, 0, 255, 1)\">for</span> v <span style=\"color: rgba(0, 0, 255, 1)\">in</span> values <span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> v]\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> values: self.arguments[name] = values</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">HTTPRequest.__init__</span></div>\r\n<h3>3.6、Application的__call__方法(含3.7、3.8、3.9)<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><span style=\"font-size: 13px; line-height: 19.5px\">此处代码主要有三个项任务:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px; line-height: 19.5px\">根据请求的url和封装在Application对象中的url映射做匹配,获取url所对应的Handler对象。<span style=\"color: rgba(136, 136, 136, 1)\">ps:Handlers泛指继承RequestHandler的类</span></span></li>\r\n<li><span style=\"font-size: 13px; line-height: 19.5px\">创建Handler对象,即:执行Handler的__init__方法</span></li>\r\n<li><span style=\"font-size: 13px; line-height: 19.5px\">执行Handler对象的 _execute 方法</span></li>\r\n</ul>\r\n<p><span style=\"font-size: 13px; color: rgba(136, 136, 136, 1)\">注意:</span></p>\r\n<p><span style=\"font-size: 13px; color: rgba(136, 136, 136, 1)\">1、执行Application的 __call__ 方法时,其参数request是HTTPRequest对象(其中封装HTTPConnetion、Stream、Application对象、请求头信息)</span></p>\r\n<p><span style=\"font-size: 13px; color: rgba(136, 136, 136, 1)\">2、Handler泛指就是我们定义的用于处理请求的类并且她还继承自RequestHandler</span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_416983\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div><div class=\"line number27 index26 alt2\">27</div><div class=\"line number28 index27 alt1\">28</div><div class=\"line number29 index28 alt2\">29</div><div class=\"line number30 index29 alt1\">30</div><div class=\"line number31 index30 alt2\">31</div><div class=\"line number32 index31 alt1\">32</div><div class=\"line number33 index32 alt2\">33</div><div class=\"line number34 index33 alt1\">34</div><div class=\"line number35 index34 alt2\">35</div><div class=\"line number36 index35 alt1\">36</div><div class=\"line number37 index36 alt2\">37</div><div class=\"line number38 index37 alt1\">38</div><div class=\"line number39 index38 alt2\">39</div><div class=\"line number40 index39 alt1\">40</div><div class=\"line number41 index40 alt2\">41</div><div class=\"line number42 index41 alt1\">42</div><div class=\"line number43 index42 alt2\">43</div><div class=\"line number44 index43 alt1\">44</div><div class=\"line number45 index44 alt2\">45</div><div class=\"line number46 index45 alt1\">46</div><div class=\"line number47 index46 alt2\">47</div><div class=\"line number48 index47 alt1\">48</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">Application(</code><code class=\"python functions\">object</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"> </div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">__call__(</code><code class=\"python color1\">self</code><code class=\"python plain\">, request):</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">\"\"\"Called by HTTPServer to execute the request.\"\"\"</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">transforms </code><code class=\"python keyword\">=</code> <code class=\"python plain\">[t(request) </code><code class=\"python keyword\">for</code> <code class=\"python plain\">t </code><code class=\"python keyword\">in</code> <code class=\"python color1\">self</code><code class=\"python plain\">.transforms]</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">handler </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">args </code><code class=\"python keyword\">=</code> <code class=\"python plain\">[]</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">kwargs </code><code class=\"python keyword\">=</code> <code class=\"python plain\">{}</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#根据请求的目标主机,匹配主机模版对应的正则表达式和Handlers</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">handlers </code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">._get_host_handlers(request)</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python plain\">handlers:</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">handler </code><code class=\"python keyword\">=</code> <code class=\"python plain\">RedirectHandler(</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">, request, url</code><code class=\"python keyword\">=</code><code class=\"python string\">\"http://\"</code> <code class=\"python keyword\">+</code> <code class=\"python color1\">self</code><code class=\"python plain\">.default_host </code><code class=\"python keyword\">+</code> <code class=\"python string\">\"/\"</code><code class=\"python plain\">)</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">else</code><code class=\"python plain\">:</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">for</code> <code class=\"python plain\">spec </code><code class=\"python keyword\">in</code> <code class=\"python plain\">handlers:</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">match </code><code class=\"python keyword\">=</code> <code class=\"python plain\">spec.regex.match(request.path)</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">match:</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\"># None-safe wrapper around url_unescape to handle</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\"># unmatched optional groups correctly</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">unquote(s):</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">s </code><code class=\"python keyword\">is</code> <code class=\"python color1\">None</code><code class=\"python plain\">: </code><code class=\"python keyword\">return</code> <code class=\"python plain\">s</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code> <code class=\"python plain\">escape.url_unescape(s, encoding</code><code class=\"python keyword\">=</code><code class=\"python color1\">None</code><code class=\"python plain\">)</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">handler </code><code class=\"python keyword\">=</code> <code class=\"python plain\">spec.handler_class(</code><code class=\"python color1\">self</code><code class=\"python plain\">, request, </code><code class=\"python keyword\">*</code><code class=\"python keyword\">*</code><code class=\"python plain\">spec.kwargs) </code><code class=\"python comments\">#创建RquestHandler对象</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\"># Pass matched groups to the handler. Since</code></div><div class=\"line number25 index24 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\"># match.groups() includes both named and unnamed groups,</code></div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\"># we want to use either groups or groupdict but not both.</code></div><div class=\"line number27 index26 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\"># Note that args are passed as bytes so the handler can</code></div><div class=\"line number28 index27 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\"># decide what encoding to use.</code></div><div class=\"line number29 index28 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">kwargs </code><code class=\"python keyword\">=</code> <code class=\"python functions\">dict</code><code class=\"python plain\">((k, unquote(v))</code></div><div class=\"line number30 index29 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">for</code> <code class=\"python plain\">(k, v) </code><code class=\"python keyword\">in</code> <code class=\"python plain\">match.groupdict().iteritems())</code></div><div class=\"line number31 index30 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">kwargs:</code></div><div class=\"line number32 index31 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">args </code><code class=\"python keyword\">=</code> <code class=\"python plain\">[]</code></div><div class=\"line number33 index32 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">else</code><code class=\"python plain\">:</code></div><div class=\"line number34 index33 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">args </code><code class=\"python keyword\">=</code> <code class=\"python plain\">[unquote(s) </code><code class=\"python keyword\">for</code> <code class=\"python plain\">s </code><code class=\"python keyword\">in</code> <code class=\"python plain\">match.groups()]</code></div><div class=\"line number35 index34 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">break</code></div><div class=\"line number36 index35 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python plain\">handler:</code></div><div class=\"line number37 index36 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">handler </code><code class=\"python keyword\">=</code> <code class=\"python plain\">ErrorHandler(</code><code class=\"python color1\">self</code><code class=\"python plain\">, request, status_code</code><code class=\"python keyword\">=</code><code class=\"python value\">404</code><code class=\"python plain\">)</code></div><div class=\"line number38 index37 alt1\"> </div><div class=\"line number39 index38 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\"># In debug mode, re-compile templates and reload static files on every</code></div><div class=\"line number40 index39 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\"># request so you don\'t need to restart to see changes</code></div><div class=\"line number41 index40 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.settings.get(</code><code class=\"python string\">\"debug\"</code><code class=\"python plain\">):</code></div><div class=\"line number42 index41 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python functions\">getattr</code><code class=\"python plain\">(RequestHandler, </code><code class=\"python string\">\"_templates\"</code><code class=\"python plain\">, </code><code class=\"python color1\">None</code><code class=\"python plain\">):</code></div><div class=\"line number43 index42 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">for</code> <code class=\"python plain\">loader </code><code class=\"python keyword\">in</code> <code class=\"python plain\">RequestHandler._templates.values():</code></div><div class=\"line number44 index43 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">loader.reset()</code></div><div class=\"line number45 index44 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">RequestHandler._static_hashes </code><code class=\"python keyword\">=</code> <code class=\"python plain\">{}</code></div><div class=\"line number46 index45 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#==== 执行RequestHandler的_execute方法 ====</code></div><div class=\"line number47 index46 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">handler._execute(transforms, </code><code class=\"python keyword\">*</code><code class=\"python plain\">args, </code><code class=\"python keyword\">*</code><code class=\"python keyword\">*</code><code class=\"python plain\">kwargs)</code></div><div class=\"line number48 index47 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code> <code class=\"python plain\">handler</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_2c4451d3-fc7e-4e1d-813e-b61138708292\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_2c4451d3-fc7e-4e1d-813e-b61138708292\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_2c4451d3-fc7e-4e1d-813e-b61138708292\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Application(object):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> _get_host_handlers(self, request):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">将请求的host和handlers中的主机模型进行匹配</span>\r\n host = request.host.lower().split(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">:</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)[0]\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">for</span> pattern, handlers <span style=\"color: rgba(0, 0, 255, 1)\">in</span><span style=\"color: rgba(0, 0, 0, 1)\"> self.handlers:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> pattern.match(host):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> handlers\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> Look for default host if not behind load balancer (for debugging)</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">X-Real-Ip</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> <span style=\"color: rgba(0, 0, 255, 1)\">not</span> <span style=\"color: rgba(0, 0, 255, 1)\">in</span><span style=\"color: rgba(0, 0, 0, 1)\"> request.headers:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">for</span> pattern, handlers <span style=\"color: rgba(0, 0, 255, 1)\">in</span><span style=\"color: rgba(0, 0, 0, 1)\"> self.handlers:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> pattern.match(self.default_host):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> handlers\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> None</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">Application._get_host_handlers</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_a47e3d1d-bbb8-4613-ad2d-e66d556b6d03\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_a47e3d1d-bbb8-4613-ad2d-e66d556b6d03\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_a47e3d1d-bbb8-4613-ad2d-e66d556b6d03\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> RequestHandler(object):\r\n SUPPORTED_METHODS </span>= (<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">GET</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">HEAD</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">POST</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">DELETE</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">PUT</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">OPTIONS</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span>(self, application, request, **<span style=\"color: rgba(0, 0, 0, 1)\">kwargs):\r\n self.application </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> application\r\n self.request </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> request\r\n self._headers_written </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> False\r\n self._finished </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> False\r\n self._auto_finish </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> True\r\n self._transforms </span>= None <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> will be set in _execute</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">获取在application中设置的 ui_modules 和ui_method</span>\r\n self.ui = _O((n, self._ui_method(m)) <span style=\"color: rgba(0, 0, 255, 1)\">for</span> n, m <span style=\"color: rgba(0, 0, 255, 1)\">in</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n application.ui_methods.iteritems())\r\n self.ui[</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">modules</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>] = _O((n, self._ui_module(n, m)) <span style=\"color: rgba(0, 0, 255, 1)\">for</span> n, m <span style=\"color: rgba(0, 0, 255, 1)\">in</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n application.ui_modules.iteritems())\r\n self.clear() </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">设置服务器、内容类型编码和连接</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> Check since connection is not available in WSGI</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">检查连接是否可用,应该是长短连接有关。</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span> hasattr(self.request, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">connection</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">):\r\n self.request.connection.stream.set_close_callback(self.on_connection_close)\r\n self.initialize(</span>**<span style=\"color: rgba(0, 0, 0, 1)\">kwargs)\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> initialize(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">pass</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> clear(self):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Resets all headers and content for this response.</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n self._headers </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> {\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Server</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">TornadoServer/%s</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\"> tornado.version,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Content-Type</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">text/html; charset=UTF-8</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">,\r\n }\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> <span style=\"color: rgba(0, 0, 255, 1)\">not</span><span style=\"color: rgba(0, 0, 0, 1)\"> self.request.supports_http_1_1():\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> self.request.headers.get(<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Connection</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>) == <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Keep-Alive</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n self.set_header(</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Connection</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Keep-Alive</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n self._write_buffer </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> []\r\n self._status_code </span>= 200</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">RequestHandler.__init__</span></div>\r\n<p><span style=\"font-size: 13px\">上述过程中,首先根据请求的URL去路由规则中匹配,一旦匹配成功,则创建路由相对应的handler的实例。例如:如果请求 的url是【/index/11】则会创建IndexHandler实例,然后再执行该对象的 _execute 方法。由于所有的 xxxHandler 类是RequestHandler的派生类,所以会默认执行 RequestHandler的 _execute 方法。</span></p>\r\n<p><img style=\"display: block; margin-left: auto; margin-right: auto\" src=\"//images0.cnblogs.com/blog2015/425762/201503/292228582243341.png\" alt=\"\" width=\"324\" height=\"204\" class=\"medium-zoom-image\"></p>\r\n<h3><span style=\"line-height: 1.5\">3.10 </span><span style=\"line-height: 1.5\">RequestHandler的_execute方法 (含有3.11、3.12、3.13)</span><button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><span style=\"font-size: 13px\">此处代码主要有三项任务:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\">扩展点,因为self.prepare默认是空方法,所有可以在这里被重写</span></li>\r\n<li><span style=\"font-size: 13px\">通过反射执行Handler的get/post/put/delete等方法</span></li>\r\n<li><span style=\"font-size: 13px\">完成请求处理后,执行finish方法</span></li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_825352\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">RequestHandler(</code><code class=\"python functions\">object</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"> </div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">_execute(</code><code class=\"python color1\">self</code><code class=\"python plain\">, transforms, </code><code class=\"python keyword\">*</code><code class=\"python plain\">args, </code><code class=\"python keyword\">*</code><code class=\"python keyword\">*</code><code class=\"python plain\">kwargs):</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">\"\"\"Executes this request with the given output transforms.\"\"\"</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._transforms </code><code class=\"python keyword\">=</code> <code class=\"python plain\">transforms</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">with stack_context.ExceptionStackContext(</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._stack_context_handle_exception):</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.request.method </code><code class=\"python keyword\">not</code> <code class=\"python keyword\">in</code> <code class=\"python color1\">self</code><code class=\"python plain\">.SUPPORTED_METHODS:</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">raise</code> <code class=\"python plain\">HTTPError(</code><code class=\"python value\">405</code><code class=\"python plain\">)</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\"># If XSRF cookies are turned on, reject form submissions without</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\"># the proper cookie</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.request.method </code><code class=\"python keyword\">not</code> <code class=\"python keyword\">in</code> <code class=\"python plain\">(</code><code class=\"python string\">\"GET\"</code><code class=\"python plain\">, </code><code class=\"python string\">\"HEAD\"</code><code class=\"python plain\">) </code><code class=\"python keyword\">and</code> <code class=\"python plain\">\\</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.application.settings.get(</code><code class=\"python string\">\"xsrf_cookies\"</code><code class=\"python plain\">):</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.check_xsrf_cookie()</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.prepare()</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">._finished:</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#通过反射的方法,执行 RequestHandler 派生类的的 get、post、put方法</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python functions\">getattr</code><code class=\"python plain\">(</code><code class=\"python color1\">self</code><code class=\"python plain\">, </code><code class=\"python color1\">self</code><code class=\"python plain\">.request.method.lower())(</code><code class=\"python keyword\">*</code><code class=\"python plain\">args, </code><code class=\"python keyword\">*</code><code class=\"python keyword\">*</code><code class=\"python plain\">kwargs)</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">._auto_finish </code><code class=\"python keyword\">and</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">._finished:</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.finish()</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>例:用户发送get请求</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_f45cb750-1bb5-434e-9486-b5a193133c45\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_f45cb750-1bb5-434e-9486-b5a193133c45\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_f45cb750-1bb5-434e-9486-b5a193133c45\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> MyHandler(tornado.web.RequestHandler):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> get(self):\r\n self.write(</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Hello, world</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">MyHandler.get</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_4ee9c7fb-30e7-4b32-ba82-d7d629e9b723\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_4ee9c7fb-30e7-4b32-ba82-d7d629e9b723\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_4ee9c7fb-30e7-4b32-ba82-d7d629e9b723\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> RequestHandler(object):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> write(self, chunk):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">assert</span> <span style=\"color: rgba(0, 0, 255, 1)\">not</span><span style=\"color: rgba(0, 0, 0, 1)\"> self._finished\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> isinstance(chunk, dict):\r\n chunk </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> escape.json_encode(chunk)\r\n self.set_header(</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Content-Type</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">text/javascript; charset=UTF-8</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n chunk </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> _utf8(chunk)\r\n self._write_buffer.append(chunk)</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">RequestHandler.write</span></div>\r\n<p><span style=\"font-size: 13px\">上述在执行RequestHandler的write方法时,讲数据保存在Handler对象的 _write_buffer 列表中,在之后执行finish时再讲数据写到IOStream对象的_write_buffer字段中,其类型是双向队列collections.deque()。</span></p>\r\n<h3>3.14、执行RequestHandler的finish<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><span style=\"font-size: 13px\">此段代码主要有两项任务:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\">将用户处理请求后返回的数据发送到IOStream的_write_buffer队列中</span></li>\r\n<li><span style=\"font-size: 13px\">纪录操作日志</span></li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_581793\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div><div class=\"line number27 index26 alt2\">27</div><div class=\"line number28 index27 alt1\">28</div><div class=\"line number29 index28 alt2\">29</div><div class=\"line number30 index29 alt1\">30</div><div class=\"line number31 index30 alt2\">31</div><div class=\"line number32 index31 alt1\">32</div><div class=\"line number33 index32 alt2\">33</div><div class=\"line number34 index33 alt1\">34</div><div class=\"line number35 index34 alt2\">35</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">RequestHandler:</code></div><div class=\"line number2 index1 alt1\"> </div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">finish(</code><code class=\"python color1\">self</code><code class=\"python plain\">, chunk</code><code class=\"python keyword\">=</code><code class=\"python color1\">None</code><code class=\"python plain\">):</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">\"\"\"Finishes this response, ending the HTTP request.\"\"\"</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">assert</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">._finished</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">chunk </code><code class=\"python keyword\">is</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">None</code><code class=\"python plain\">: </code><code class=\"python color1\">self</code><code class=\"python plain\">.write(chunk)</code></div><div class=\"line number7 index6 alt2\"> </div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">._headers_written:</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">(</code><code class=\"python color1\">self</code><code class=\"python plain\">._status_code </code><code class=\"python keyword\">=</code><code class=\"python keyword\">=</code> <code class=\"python value\">200</code> <code class=\"python keyword\">and</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.request.method </code><code class=\"python keyword\">in</code> <code class=\"python plain\">(</code><code class=\"python string\">\"GET\"</code><code class=\"python plain\">, </code><code class=\"python string\">\"HEAD\"</code><code class=\"python plain\">) </code><code class=\"python keyword\">and</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python string\">\"Etag\"</code> <code class=\"python keyword\">not</code> <code class=\"python keyword\">in</code> <code class=\"python color1\">self</code><code class=\"python plain\">._headers):</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">hasher </code><code class=\"python keyword\">=</code> <code class=\"python plain\">hashlib.sha1()</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">for</code> <code class=\"python plain\">part </code><code class=\"python keyword\">in</code> <code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer:</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">hasher.update(part)</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">etag </code><code class=\"python keyword\">=</code> <code class=\"python string\">\'\"%s\"\'</code> <code class=\"python keyword\">%</code> <code class=\"python plain\">hasher.hexdigest()</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">inm </code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">.request.headers.get(</code><code class=\"python string\">\"If-None-Match\"</code><code class=\"python plain\">)</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">inm </code><code class=\"python keyword\">and</code> <code class=\"python plain\">inm.find(etag) !</code><code class=\"python keyword\">=</code> <code class=\"python keyword\">-</code><code class=\"python value\">1</code><code class=\"python plain\">:</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer </code><code class=\"python keyword\">=</code> <code class=\"python plain\">[]</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.set_status(</code><code class=\"python value\">304</code><code class=\"python plain\">)</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">else</code><code class=\"python plain\">:</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.set_header(</code><code class=\"python string\">\"Etag\"</code><code class=\"python plain\">, etag)</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python string\">\"Content-Length\"</code> <code class=\"python keyword\">not</code> <code class=\"python keyword\">in</code> <code class=\"python color1\">self</code><code class=\"python plain\">._headers:</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">content_length </code><code class=\"python keyword\">=</code> <code class=\"python functions\">sum</code><code class=\"python plain\">(</code><code class=\"python functions\">len</code><code class=\"python plain\">(part) </code><code class=\"python keyword\">for</code> <code class=\"python plain\">part </code><code class=\"python keyword\">in</code> <code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer)</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.set_header(</code><code class=\"python string\">\"Content-Length\"</code><code class=\"python plain\">, content_length)</code></div><div class=\"line number25 index24 alt2\"> </div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python functions\">hasattr</code><code class=\"python plain\">(</code><code class=\"python color1\">self</code><code class=\"python plain\">.request, </code><code class=\"python string\">\"connection\"</code><code class=\"python plain\">):</code></div><div class=\"line number27 index26 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.request.connection.stream.set_close_callback(</code><code class=\"python color1\">None</code><code class=\"python plain\">)</code></div><div class=\"line number28 index27 alt1\"> </div><div class=\"line number29 index28 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">.application._wsgi:</code></div><div class=\"line number30 index29 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">#将处理请求返回的数据发送到IOStream的_write_buffer队列中</code></div><div class=\"line number31 index30 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.flush(include_footers</code><code class=\"python keyword\">=</code><code class=\"python color1\">True</code><code class=\"python plain\">)</code></div><div class=\"line number32 index31 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.request.finish()</code></div><div class=\"line number33 index32 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">#纪录日志</code></div><div class=\"line number34 index33 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._log()</code></div><div class=\"line number35 index34 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._finished </code><code class=\"python keyword\">=</code> <code class=\"python color1\">True</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<h3>3.15、执行RequestHandler的flush方法<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><span style=\"font-size: 13px\">此处代码主要有一项任务:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\">将处理请求返回的数据发送到IOStream的_write_buffer队列中</span></li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_260886\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">def</code> <code class=\"python plain\">flush(</code><code class=\"python color1\">self</code><code class=\"python plain\">, include_footers</code><code class=\"python keyword\">=</code><code class=\"python color1\">False</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">\"\"\"Flushes the current output buffer to the network.\"\"\"</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.application._wsgi:</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">raise</code> <code class=\"python plain\">Exception(</code><code class=\"python string\">\"WSGI applications do not support flush()\"</code><code class=\"python plain\">)</code></div><div class=\"line number5 index4 alt2\"> </div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">chunk </code><code class=\"python keyword\">=</code> <code class=\"python plain\">\"\".join(</code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer)</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer </code><code class=\"python keyword\">=</code> <code class=\"python plain\">[]</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">._headers_written:</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._headers_written </code><code class=\"python keyword\">=</code> <code class=\"python color1\">True</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">for</code> <code class=\"python plain\">transform </code><code class=\"python keyword\">in</code> <code class=\"python color1\">self</code><code class=\"python plain\">._transforms:</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._headers, chunk </code><code class=\"python keyword\">=</code> <code class=\"python plain\">transform.transform_first_chunk(</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._headers, chunk, include_footers)</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">headers </code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">._generate_headers()</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">else</code><code class=\"python plain\">:</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">for</code> <code class=\"python plain\">transform </code><code class=\"python keyword\">in</code> <code class=\"python color1\">self</code><code class=\"python plain\">._transforms:</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">chunk </code><code class=\"python keyword\">=</code> <code class=\"python plain\">transform.transform_chunk(chunk, include_footers)</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">headers </code><code class=\"python keyword\">=</code> <code class=\"python plain\">\"\"</code></div><div class=\"line number18 index17 alt1\"> </div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\"># Ignore the chunk and only write the headers for HEAD requests</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.request.method </code><code class=\"python keyword\">=</code><code class=\"python keyword\">=</code> <code class=\"python string\">\"HEAD\"</code><code class=\"python plain\">:</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">headers: </code><code class=\"python color1\">self</code><code class=\"python plain\">.request.write(headers)</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number23 index22 alt2\"> </div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">headers </code><code class=\"python keyword\">or</code> <code class=\"python plain\">chunk:</code></div><div class=\"line number25 index24 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#执行HTTPReqeust的write方法</code></div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.request.write(headers </code><code class=\"python keyword\">+</code> <code class=\"python plain\">chunk)</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_2b0f95fc-66e8-409d-a433-f995b9628e68\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_2b0f95fc-66e8-409d-a433-f995b9628e68\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_2b0f95fc-66e8-409d-a433-f995b9628e68\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> HTTPRequest(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> write(self, chunk):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Writes the given chunk to the response stream.</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">assert</span><span style=\"color: rgba(0, 0, 0, 1)\"> isinstance(chunk, str)\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">执行HTTPConnection的write方法</span>\r\n self.connection.write(chunk)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">HTTPRequest.write</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_d781f65e-5879-440b-b976-d6e62fd6e76e\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_d781f65e-5879-440b-b976-d6e62fd6e76e\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_d781f65e-5879-440b-b976-d6e62fd6e76e\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> write(self, data, callback=<span style=\"color: rgba(0, 0, 0, 1)\">None):\r\n \r\n self._check_closed()\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">将数据保存到collections.deque()类型的双向队列中_write_buffer中</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\"> self._write_buffer.append(data)\r\n self._add_io_state(self.io_loop.WRITE)\r\n self._write_callback </span>= stack_context.wrap(callback)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream.write</span></div>\r\n<p><span style=\"font-size: 13px\">以上代码执行完成之后,请求的处理基本上就完成了。下面就是等待监听客户端socket句柄的epoll触发,然后执行IOStream的_handle_event方法来将 响应数据发送给客户端。</span></p>\r\n<h3><span style=\"line-height: 1.5\">3.20、执行RequestHandler的_log方法</span><button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><span style=\"line-height: 1.5; font-size: 13px\">此处代码主要有一项任务:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\"><span style=\"line-height: 1.5\">记录操作日志(利用logging模块)</span></span></li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_747054\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">RequestHandler:</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">_log(</code><code class=\"python color1\">self</code><code class=\"python plain\">):</code></div><div class=\"line number3 index2 alt2\"> </div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.application.log_request(</code><code class=\"python color1\">self</code><code class=\"python plain\">)</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_44c2e05c-a17f-4667-9478-26298296e8d9\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_44c2e05c-a17f-4667-9478-26298296e8d9\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_44c2e05c-a17f-4667-9478-26298296e8d9\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Application:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> log_request(self, handler):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">log_function</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> <span style=\"color: rgba(0, 0, 255, 1)\">in</span><span style=\"color: rgba(0, 0, 0, 1)\"> self.settings:\r\n self.settings[</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">log_function</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">](handler)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span> handler.get_status() < 400<span style=\"color: rgba(0, 0, 0, 1)\">:\r\n log_method </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> logging.info\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">elif</span> handler.get_status() < 500<span style=\"color: rgba(0, 0, 0, 1)\">:\r\n log_method </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> logging.warning\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">else</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n log_method </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> logging.error\r\n request_time </span>= 1000.0 *<span style=\"color: rgba(0, 0, 0, 1)\"> handler.request.request_time()\r\n log_method(</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%d %s %.2fms</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">, handler.get_status(),\r\n handler._request_summary(), request_time)</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">Application.log_request</span></div>\r\n<h3>3.21、IOStream的Handle_event方法<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>由于epoll中不但监听了服务器socket句柄还监听了客户端sokcet句柄,所以当客户端socket对象变化时,就会去调用之前指定的IOStream的_handler_events方法。</p>\r\n<p>此段代码主要有一项任务:</p>\r\n<ul>\r\n<li>将处理之后的响应数据发送给客户端</li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_488762\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div><div class=\"line number27 index26 alt2\">27</div><div class=\"line number28 index27 alt1\">28</div><div class=\"line number29 index28 alt2\">29</div><div class=\"line number30 index29 alt1\">30</div><div class=\"line number31 index30 alt2\">31</div><div class=\"line number32 index31 alt1\">32</div><div class=\"line number33 index32 alt2\">33</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">IOStream(</code><code class=\"python functions\">object</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">_handle_events(</code><code class=\"python color1\">self</code><code class=\"python plain\">, fd, events):</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">.socket:</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">logging.warning(</code><code class=\"python string\">\"Got events for closed stream %d\"</code><code class=\"python plain\">, fd)</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">try</code><code class=\"python plain\">:</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">events & </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.READ:</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._handle_read()</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">.socket:</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">events & </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.WRITE:</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">._connecting:</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._handle_connect()</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#执行_handle_write方法,内部调用socket.send将数据响应给客户端</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._handle_write()</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">.socket:</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">events & </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.ERROR:</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.close()</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">state </code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.ERROR</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.reading():</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">state |</code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.READ</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.writing():</code></div><div class=\"line number25 index24 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">state |</code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.WRITE</code></div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">state !</code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">._state:</code></div><div class=\"line number27 index26 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._state </code><code class=\"python keyword\">=</code> <code class=\"python plain\">state</code></div><div class=\"line number28 index27 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.update_handler(</code><code class=\"python color1\">self</code><code class=\"python plain\">.socket.fileno(), </code><code class=\"python color1\">self</code><code class=\"python plain\">._state)</code></div><div class=\"line number29 index28 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">except</code><code class=\"python plain\">:</code></div><div class=\"line number30 index29 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">logging.error(</code><code class=\"python string\">\"Uncaught exception, closing connection.\"</code><code class=\"python plain\">,</code></div><div class=\"line number31 index30 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">exc_info</code><code class=\"python keyword\">=</code><code class=\"python color1\">True</code><code class=\"python plain\">)</code></div><div class=\"line number32 index31 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.close()</code></div><div class=\"line number33 index32 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">raise</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<h3>3.22、IOStream的_handle_write方法<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>此段代码主要有两项任务:</p>\r\n<ul>\r\n<li>调用socket.send给客户端发送响应数据</li>\r\n<li>执行回调函数HTTPConnection的_on_write_complete方法</li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_368809\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">IOStream(</code><code class=\"python functions\">object</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">_handle_write(</code><code class=\"python color1\">self</code><code class=\"python plain\">):</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">while</code> <code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer:</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">try</code><code class=\"python plain\">:</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer_frozen:</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">_merge_prefix(</code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer, </code><code class=\"python value\">128</code> <code class=\"python keyword\">*</code> <code class=\"python value\">1024</code><code class=\"python plain\">)</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#调用客户端socket对象的send方法发送数据</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">num_bytes </code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">.socket.send(</code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer[</code><code class=\"python value\">0</code><code class=\"python plain\">])</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer_frozen </code><code class=\"python keyword\">=</code> <code class=\"python color1\">False</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">_merge_prefix(</code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer, num_bytes)</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer.popleft()</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">except</code> <code class=\"python plain\">socket.error, e:</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">e.args[</code><code class=\"python value\">0</code><code class=\"python plain\">] </code><code class=\"python keyword\">in</code> <code class=\"python plain\">(errno.EWOULDBLOCK, errno.EAGAIN):</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer_frozen </code><code class=\"python keyword\">=</code> <code class=\"python color1\">True</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">break</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">else</code><code class=\"python plain\">:</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">logging.warning(</code><code class=\"python string\">\"Write error on %d: %s\"</code><code class=\"python plain\">,</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.socket.fileno(), e)</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.close()</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">._write_buffer </code><code class=\"python keyword\">and</code> <code class=\"python color1\">self</code><code class=\"python plain\">._write_callback:</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">callback </code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">._write_callback</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._write_callback </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#执行回调函数关闭客户端socket连接(HTTPConnection的_on_write_complete方法)</code></div><div class=\"line number25 index24 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._run_callback(callback)</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_619e3298-f697-4dba-85a1-326dadf3344c\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_619e3298-f697-4dba-85a1-326dadf3344c\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_619e3298-f697-4dba-85a1-326dadf3344c\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> _run_callback(self, callback, *args, **<span style=\"color: rgba(0, 0, 0, 1)\">kwargs):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">try</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n with stack_context.NullContext():\r\n callback(</span>*args, **<span style=\"color: rgba(0, 0, 0, 1)\">kwargs)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">except</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n logging.error(</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Uncaught exception, closing connection.</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">,\r\n exc_info</span>=<span style=\"color: rgba(0, 0, 0, 1)\">True)\r\n self.close()\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">raise</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream._run_callback</span></div>\r\n<p><span style=\"color: rgba(136, 136, 136, 1); font-size: 13px\">注:IOStream的_run_callback方法内部调用了HTTPConnection的_on_write_complete方法</span></p>\r\n<h3><span style=\"line-height: 1.5\">3.23、执行HTTPConnection的_on_write_complete方法</span><button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><span style=\"line-height: 1.5; font-size: 13px\">此处代码主要有一项任务:</span></p>\r\n<ul>\r\n<li><span style=\"line-height: 1.5; font-size: 13px\">更新客户端socket所在epoll中的状态为【READ】,以便之后执行3.24时关闭socket客户端。</span></li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_935093\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">HTTPConnection(</code><code class=\"python functions\">object</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"> </div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">_on_write_complete(</code><code class=\"python color1\">self</code><code class=\"python plain\">):</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">._request_finished:</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._finish_request()</code></div><div class=\"line number6 index5 alt1\"> </div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">_finish_request(</code><code class=\"python color1\">self</code><code class=\"python plain\">):</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.no_keep_alive:</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">disconnect </code><code class=\"python keyword\">=</code> <code class=\"python color1\">True</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">else</code><code class=\"python plain\">:</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">connection_header </code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">._request.headers.get(</code><code class=\"python string\">\"Connection\"</code><code class=\"python plain\">)</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">._request.supports_http_1_1():</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">disconnect </code><code class=\"python keyword\">=</code> <code class=\"python plain\">connection_header </code><code class=\"python keyword\">=</code><code class=\"python keyword\">=</code> <code class=\"python string\">\"close\"</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">elif</code> <code class=\"python plain\">(</code><code class=\"python string\">\"Content-Length\"</code> <code class=\"python keyword\">in</code> <code class=\"python color1\">self</code><code class=\"python plain\">._request.headers</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">or</code> <code class=\"python color1\">self</code><code class=\"python plain\">._request.method </code><code class=\"python keyword\">in</code> <code class=\"python plain\">(</code><code class=\"python string\">\"HEAD\"</code><code class=\"python plain\">, </code><code class=\"python string\">\"GET\"</code><code class=\"python plain\">)):</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">disconnect </code><code class=\"python keyword\">=</code> <code class=\"python plain\">connection_header !</code><code class=\"python keyword\">=</code> <code class=\"python string\">\"Keep-Alive\"</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">else</code><code class=\"python plain\">:</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">disconnect </code><code class=\"python keyword\">=</code> <code class=\"python color1\">True</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._request </code><code class=\"python keyword\">=</code> <code class=\"python color1\">None</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._request_finished </code><code class=\"python keyword\">=</code> <code class=\"python color1\">False</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">disconnect:</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.stream.close()</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.stream.read_until(</code><code class=\"python string\">\"\\r\\n\\r\\n\"</code><code class=\"python plain\">, </code><code class=\"python color1\">self</code><code class=\"python plain\">._header_callback)</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_30e9d3f4-d3b1-4676-bf91-581b04ee74be\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_30e9d3f4-d3b1-4676-bf91-581b04ee74be\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_30e9d3f4-d3b1-4676-bf91-581b04ee74be\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> read_until(self, delimiter, callback):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Call callback when we read the given delimiter.</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">assert</span> <span style=\"color: rgba(0, 0, 255, 1)\">not</span> self._read_callback, <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Already reading</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n self._read_delimiter </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> delimiter\r\n self._read_callback </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> stack_context.wrap(callback)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">while</span><span style=\"color: rgba(0, 0, 0, 1)\"> True:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> See if we\'ve already got the data from a previous read</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> self._read_from_buffer():\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n self._check_closed()\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> self._read_to_buffer() ==<span style=\"color: rgba(0, 0, 0, 1)\"> 0:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">break</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">更新为READ</span>\r\n self._add_io_state(self.io_loop.READ)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream.read_until</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_b520a264-96c6-4ba1-b767-ac1285c72945\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_b520a264-96c6-4ba1-b767-ac1285c72945\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_b520a264-96c6-4ba1-b767-ac1285c72945\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> _add_io_state(self, state):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> self.socket <span style=\"color: rgba(0, 0, 255, 1)\">is</span><span style=\"color: rgba(0, 0, 0, 1)\"> None:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> connection has been closed, so there can be no future events</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">return</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span> <span style=\"color: rgba(0, 0, 255, 1)\">not</span> self._state &<span style=\"color: rgba(0, 0, 0, 1)\"> state:\r\n self._state </span>= self._state |<span style=\"color: rgba(0, 0, 0, 1)\"> state\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">执行IOLoop对象的update_handler方法</span>\r\n self.io_loop.update_handler(self.socket.fileno(), self._state)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream._add_io_state</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_11927d5a-83d1-4cbc-846b-f245cbbbca5e\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_11927d5a-83d1-4cbc-846b-f245cbbbca5e\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_11927d5a-83d1-4cbc-846b-f245cbbbca5e\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOLoop(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> update_handler(self, fd, events):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Changes the events we listen for fd.</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">self._impl就是epoll对象</span>\r\n self._impl.modify(fd, events | self.ERROR)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOLoop.update_handler</span></div>\r\n<h3>3.24、IOStream的_handle_write方法(含3.25、3.26)<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>此段代码主要有一项任务:</p>\r\n<ul>\r\n<li>关闭客户端socket</li>\r\n</ul>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_613303\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div><div class=\"line number27 index26 alt2\">27</div><div class=\"line number28 index27 alt1\">28</div><div class=\"line number29 index28 alt2\">29</div><div class=\"line number30 index29 alt1\">30</div><div class=\"line number31 index30 alt2\">31</div><div class=\"line number32 index31 alt1\">32</div><div class=\"line number33 index32 alt2\">33</div><div class=\"line number34 index33 alt1\">34</div><div class=\"line number35 index34 alt2\">35</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">IOStream(</code><code class=\"python functions\">object</code><code class=\"python plain\">):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">_handle_events(</code><code class=\"python color1\">self</code><code class=\"python plain\">, fd, events):</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">.socket:</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">logging.warning(</code><code class=\"python string\">\"Got events for closed stream %d\"</code><code class=\"python plain\">, fd)</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">try</code><code class=\"python plain\">:</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#由于在 2.23 步骤中已经将epoll的状态更新为READ,所以这次会执行_handle_read方法</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">events & </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.READ:</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._handle_read()</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#执行完_handle_read后,客户端socket被关闭且置空,所有此处就会执行return</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">.socket:</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#===============================终止===========================</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">events & </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.WRITE:</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">._connecting:</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._handle_connect()</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._handle_write()</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python keyword\">not</code> <code class=\"python color1\">self</code><code class=\"python plain\">.socket:</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">events & </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.ERROR:</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.close()</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">return</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">state </code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.ERROR</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.reading():</code></div><div class=\"line number25 index24 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">state |</code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.READ</code></div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python color1\">self</code><code class=\"python plain\">.writing():</code></div><div class=\"line number27 index26 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">state |</code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.WRITE</code></div><div class=\"line number28 index27 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">state !</code><code class=\"python keyword\">=</code> <code class=\"python color1\">self</code><code class=\"python plain\">._state:</code></div><div class=\"line number29 index28 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">._state </code><code class=\"python keyword\">=</code> <code class=\"python plain\">state</code></div><div class=\"line number30 index29 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.io_loop.update_handler(</code><code class=\"python color1\">self</code><code class=\"python plain\">.socket.fileno(), </code><code class=\"python color1\">self</code><code class=\"python plain\">._state)</code></div><div class=\"line number31 index30 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">except</code><code class=\"python plain\">:</code></div><div class=\"line number32 index31 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">logging.error(</code><code class=\"python string\">\"Uncaught exception, closing connection.\"</code><code class=\"python plain\">,</code></div><div class=\"line number33 index32 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">exc_info</code><code class=\"python keyword\">=</code><code class=\"python color1\">True</code><code class=\"python plain\">)</code></div><div class=\"line number34 index33 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.close()</code></div><div class=\"line number35 index34 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">raise</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_df99d4e9-34ab-4450-a728-d24f201a4e4f\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_df99d4e9-34ab-4450-a728-d24f201a4e4f\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_df99d4e9-34ab-4450-a728-d24f201a4e4f\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> _handle_read(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">while</span><span style=\"color: rgba(0, 0, 0, 1)\"> True:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">try</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> Read from the socket until we get EWOULDBLOCK or equivalent.</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> SSL sockets do some internal buffering, and if the data is</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> sitting in the SSL object\'s buffer select() and friends</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> can\'t see it; the only way to find out if it\'s there is to</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> try to read it.</span>\r\n result =<span style=\"color: rgba(0, 0, 0, 1)\"> self._read_to_buffer()\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">except</span><span style=\"color: rgba(0, 0, 0, 1)\"> Exception:\r\n self.close()\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span> result ==<span style=\"color: rgba(0, 0, 0, 1)\"> 0:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">break</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">else</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> self._read_from_buffer():\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream._handle_read</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_33a2c3fe-3f3b-490b-a2aa-a51f4fb3f760\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_33a2c3fe-3f3b-490b-a2aa-a51f4fb3f760\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_33a2c3fe-3f3b-490b-a2aa-a51f4fb3f760\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> _read_from_socket(self):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Attempts to read from the socket.\r\n\r\n Returns the data read or None if there is nothing to read.\r\n May be overridden in subclasses.\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">try</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n chunk </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> self.socket.recv(self.read_chunk_size)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">except</span><span style=\"color: rgba(0, 0, 0, 1)\"> socket.error, e:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span> e.args[0] <span style=\"color: rgba(0, 0, 255, 1)\">in</span><span style=\"color: rgba(0, 0, 0, 1)\"> (errno.EWOULDBLOCK, errno.EAGAIN):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> None\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">else</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">raise</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span> <span style=\"color: rgba(0, 0, 255, 1)\">not</span><span style=\"color: rgba(0, 0, 0, 1)\"> chunk:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">执行close方法</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\"> self.close()\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span><span style=\"color: rgba(0, 0, 0, 1)\"> None\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">return</span> chunk</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream._read_from_socket</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_3cb8e76d-99fd-4e75-90cd-ed9fb5ecfec3\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_3cb8e76d-99fd-4e75-90cd-ed9fb5ecfec3\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_3cb8e76d-99fd-4e75-90cd-ed9fb5ecfec3\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOStream(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> close(self):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Close this stream.</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span>\r\n <span style=\"color: rgba(0, 0, 255, 1)\">if</span> self.socket <span style=\"color: rgba(0, 0, 255, 1)\">is</span> <span style=\"color: rgba(0, 0, 255, 1)\">not</span><span style=\"color: rgba(0, 0, 0, 1)\"> None:\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">将客户端socket句柄在epoll中的移除,即:不再监听此客户端请求。</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\"> self.io_loop.remove_handler(self.socket.fileno())\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">关闭客户端socket</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\"> self.socket.close()\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">将socket置空</span>\r\n self.socket =<span style=\"color: rgba(0, 0, 0, 1)\"> None\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">if</span><span style=\"color: rgba(0, 0, 0, 1)\"> self._close_callback:\r\n self._run_callback(self._close_callback)</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOStream.close</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_26ebef3d-745a-4e51-9c74-a4b274fc54ef\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_26ebef3d-745a-4e51-9c74-a4b274fc54ef\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_26ebef3d-745a-4e51-9c74-a4b274fc54ef\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> IOLoop(object):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> remove_handler(self, fd):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Stop listening for events on fd.</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n self._handlers.pop(fd, None)\r\n self._events.pop(fd, None)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">try</span><span style=\"color: rgba(0, 0, 0, 1)\">:\r\n self._impl.unregister(fd)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">except</span><span style=\"color: rgba(0, 0, 0, 1)\"> (OSError, IOError):\r\n logging.debug(</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Error deleting fd from IOLoop</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>, exc_info=True)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">IOLoop.remove_handler</span></div>\r\n<h3>结束语<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>以上就是tornado源码针对请求的主要内容,另外,大家可能注意到我们返回给用户的只是一个简单的“hello world”,tornado返回复杂的内容时又需要使用模板语言,至于如何生成复杂的页面,我们会在下一篇再会剖析。</p>\r\n<p>读者如果觉得那里错误或不适,请与我联系!!!</p>\r\n<p> </p>\r\n<p></p>\r\n<p><audio controls=\"controls\" style=\"display: none\"></audio></p>\r\n</div>', '2022-07-01', 0, 0, 13, 1, 1);
INSERT INTO `app01_article` VALUES (3, '人生没有白走的路,每一步都算数', '看了一位新同学的自我介绍,看完后让人沉思,有多少人也跟他一样,不是不想努力,而是一直找不到方向,只能在底层兜兜转转消磨殆尽美好青春年华。 他叫车融,在深圳工作,我去深圳分校时,他正好去咨询,他跟我聊过很多,感觉是个很有想法的人,今天看完他写的这个东西,感觉有些沉重,但人生的路, 每一步都算数', '<div id=\"cnblogs_post_body\" class=\"blogpost-body blogpost-body-html\">\r\n<p><span>51CTO同步发布地址:<a href=\"http://3060674.blog.51cto.com/3050674/1689163\" target=\"_blank\" rel=\"noopener\">http://3060674.blog.51cto.com/3050674/1689163</a></span></p>\r\n<h3>概述<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<ul>\r\n<li>面向过程:根据业务逻辑从上到下写垒代码</li>\r\n<li>函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可</li>\r\n<li>面向对象:对函数进行分类和封装,让开发“更快更好更强...”</li>\r\n</ul>\r\n<p>面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_510638\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">while</code> <code class=\"python color1\">True</code><code class=\"python plain\">:</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">cpu利用率 > </code><code class=\"python value\">90</code><code class=\"python keyword\">%</code><code class=\"python plain\">:</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#发送邮件提醒</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">连接邮箱服务器</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">发送邮件</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">关闭连接</code></div><div class=\"line number7 index6 alt2\"> </div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">硬盘使用空间 > </code><code class=\"python value\">90</code><code class=\"python keyword\">%</code><code class=\"python plain\">:</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#发送邮件提醒</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">连接邮箱服务器</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">发送邮件</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">关闭连接</code></div><div class=\"line number13 index12 alt2\"> </div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">内存占用 > </code><code class=\"python value\">80</code><code class=\"python keyword\">%</code><code class=\"python plain\">:</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">#发送邮件提醒</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">连接邮箱服务器</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">发送邮件</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">关闭连接</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>随着时间的推移,开始使用了函数式编程,增强代码的重用性和可读性,就变成了这样:</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_854753\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">def</code> <code class=\"python plain\">发送邮件(内容)</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">#发送邮件提醒</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">连接邮箱服务器</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">发送邮件</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">关闭连接</code></div><div class=\"line number6 index5 alt1\"> </div><div class=\"line number7 index6 alt2\"><code class=\"python keyword\">while</code> <code class=\"python color1\">True</code><code class=\"python plain\">:</code></div><div class=\"line number8 index7 alt1\"> </div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">cpu利用率 > </code><code class=\"python value\">90</code><code class=\"python keyword\">%</code><code class=\"python plain\">:</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">发送邮件(</code><code class=\"python string\">\'CPU报警\'</code><code class=\"python plain\">)</code></div><div class=\"line number11 index10 alt2\"> </div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">硬盘使用空间 > </code><code class=\"python value\">90</code><code class=\"python keyword\">%</code><code class=\"python plain\">:</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">发送邮件(</code><code class=\"python string\">\'硬盘报警\'</code><code class=\"python plain\">)</code></div><div class=\"line number14 index13 alt1\"> </div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">内存占用 > </code><code class=\"python value\">80</code><code class=\"python keyword\">%</code><code class=\"python plain\">:</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">发送邮件(</code><code class=\"python string\">\'内存报警\'</code><code class=\"python plain\">) </code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><span style=\"font-size: 13px\">今天我们来学习一种新的编程方式:面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)</span><br><span style=\"font-size: 13px\"><em><span style=\"color: rgba(136, 136, 136, 1)\">注:Java和C#来说只支持面向对象编程,而python比较灵活即支持面向对象编程也支持函数式编程</span></em></span></p>\r\n<h3>创建类和对象<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。</p>\r\n<p> 类就是一个模板,模板里可以包含多个函数,函数里实现一些功能</p>\r\n<p> 对象则是根据模板创建的实例,通过实例对象可以执行类中的函数</p>\r\n<p><span style=\"font-size: 18px\"><strong><img src=\"https://images0.cnblogs.com/blog2015/425762/201508/271420286872390.jpg\" alt=\"\" width=\"491\" height=\"188\" class=\"medium-zoom-image\"></strong></span></p>\r\n<ul>\r\n<li>class是关键字,表示类</li>\r\n<li><span style=\"color: rgba(0, 0, 0, 1)\">创建对象,类名称后加括号即可</span></li>\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n</ul>\r\n<p><em><span style=\"color: rgba(136, 136, 136, 1); font-size: 13px\">ps:类中的函数第一个参数必须是self(详细见:类的三大特性之封装)</span></em><br><em><span style=\"color: rgba(136, 136, 136, 1); font-size: 13px\"> 类中定义的函数叫做 “方法”</span></em></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_545997\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python comments\"># 创建类</code></div><div class=\"line number2 index1 alt1\"><code class=\"python keyword\">class</code> <code class=\"python plain\">Foo:</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code> </div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">Bar(</code><code class=\"python color1\">self</code><code class=\"python plain\">):</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python functions\">print</code> <code class=\"python string\">\'Bar\'</code></div><div class=\"line number6 index5 alt1\"> </div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">Hello(</code><code class=\"python color1\">self</code><code class=\"python plain\">, name):</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python functions\">print</code> <code class=\"python string\">\'i am %s\'</code> <code class=\"python keyword\">%</code><code class=\"python plain\">name</code></div><div class=\"line number9 index8 alt2\"> </div><div class=\"line number10 index9 alt1\"><code class=\"python comments\"># 根据类Foo创建对象obj</code></div><div class=\"line number11 index10 alt2\"><code class=\"python plain\">obj </code><code class=\"python keyword\">=</code> <code class=\"python plain\">Foo()</code></div><div class=\"line number12 index11 alt1\"><code class=\"python plain\">obj.Bar() </code><code class=\"python comments\">#执行Bar方法</code></div><div class=\"line number13 index12 alt2\"><code class=\"python plain\">obj.Hello(</code><code class=\"python string\">\'wupeiqi\'</code><code class=\"python plain\">) </code><code class=\"python comments\">#执行Hello方法 </code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><em><strong>诶,</strong>你在这里是不是有疑问了?使用函数式编程和面向对象编程方式来执行一个“方法”时函数要比面向对象简便</em></p>\r\n<ul>\r\n<li><em>面向对象:【创建对象】【通过对象执行方法】</em></li>\r\n<li><em>函数编程:【执行函数】</em></li>\r\n</ul>\r\n<p>观察上述对比答案则是肯定的,然后并非绝对,场景的不同适合其的编程方式也不同。</p>\r\n<p>总结:函数式的应用场景 --> 各个函数之间是独立且无共用的数据</p>\r\n<h3>面向对象三大特性<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><span style=\"line-height: 28px\">面向对象的三大特性是指:封装、继承和多态。</span></p>\r\n<p><span style=\"font-size: 14pt\"><strong>一、封装</strong></span></p>\r\n<p>封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。</p>\r\n<p>所以,在使用面向对象的封装特性时,需要:</p>\r\n<ul>\r\n<li>将内容封装到某处</li>\r\n<li>从某处调用被封装的内容</li>\r\n</ul>\r\n<p><span style=\"font-size: 18px\"><strong>第一步:将内容封装到某处</strong></span></p>\r\n<p><img src=\"https://images0.cnblogs.com/blog2015/425762/201508/271641407509817.jpg\" alt=\"\" width=\"579\" height=\"219\" class=\"medium-zoom-image\"></p>\r\n<p> self 是一个形式参数,当执行 obj1 = Foo(\'wupeiqi\', 18 ) 时,self 等于 obj1</p>\r\n<p> 当执行 obj2 = Foo(\'alex\', 78 ) 时,self 等于 obj2</p>\r\n<p>所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性,在内存里类似于下图来保存。</p>\r\n<p><img src=\"https://images0.cnblogs.com/blog2015/425762/201508/271653303446704.jpg\" alt=\"\" width=\"248\" height=\"106\" class=\"medium-zoom-image\"></p>\r\n<p><span style=\"font-size: 18px\"><strong>第二步:从某处调用被封装的内容</strong></span></p>\r\n<p>调用被封装的内容时,有两种情况:</p>\r\n<ul>\r\n<li>通过对象直接调用</li>\r\n<li>通过self间接调用</li>\r\n</ul>\r\n<p>1、通过对象直接调用被封装的内容</p>\r\n<p>上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_288545\" class=\"syntaxhighlighter collapsed python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">Foo:</code></div><div class=\"line number2 index1 alt1\"> </div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">__init__(</code><code class=\"python color1\">self</code><code class=\"python plain\">, name, age):</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.name </code><code class=\"python keyword\">=</code> <code class=\"python plain\">name</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.age </code><code class=\"python keyword\">=</code> <code class=\"python plain\">age</code></div><div class=\"line number6 index5 alt1\"> </div><div class=\"line number7 index6 alt2\"><code class=\"python plain\">obj1 </code><code class=\"python keyword\">=</code> <code class=\"python plain\">Foo(</code><code class=\"python string\">\'wupeiqi\'</code><code class=\"python plain\">, </code><code class=\"python value\">18</code><code class=\"python plain\">) </code></div><div class=\"line number8 index7 alt1\"><code class=\"python functions\">print</code> <code class=\"python plain\">obj1.name </code><code class=\"python comments\"># 直接调用obj1对象的name属性</code></div><div class=\"line number9 index8 alt2\"><code class=\"python functions\">print</code> <code class=\"python plain\">obj1.age </code><code class=\"python comments\"># 直接调用obj1对象的age属性</code></div><div class=\"line number10 index9 alt1\"> </div><div class=\"line number11 index10 alt2\"><code class=\"python plain\">obj2 </code><code class=\"python keyword\">=</code> <code class=\"python plain\">Foo(</code><code class=\"python string\">\'alex\'</code><code class=\"python plain\">, </code><code class=\"python value\">73</code><code class=\"python plain\">)</code></div><div class=\"line number12 index11 alt1\"><code class=\"python functions\">print</code> <code class=\"python plain\">obj2.name </code><code class=\"python comments\"># 直接调用obj2对象的name属性</code></div><div class=\"line number13 index12 alt2\"><code class=\"python functions\">print</code> <code class=\"python plain\">obj2.age </code><code class=\"python comments\"># 直接调用obj2对象的age属性</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>2、通过self间接调用被封装的内容</p>\r\n<p>执行类中的方法时,需要通过self间接调用被封装的内容</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_987427\" class=\"syntaxhighlighter collapsed python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">Foo:</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code> </div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">__init__(</code><code class=\"python color1\">self</code><code class=\"python plain\">, name, age):</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.name </code><code class=\"python keyword\">=</code> <code class=\"python plain\">name</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.age </code><code class=\"python keyword\">=</code> <code class=\"python plain\">age</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code> </div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">detail(</code><code class=\"python color1\">self</code><code class=\"python plain\">):</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python functions\">print</code> <code class=\"python color1\">self</code><code class=\"python plain\">.name</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python functions\">print</code> <code class=\"python color1\">self</code><code class=\"python plain\">.age</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code> </div><div class=\"line number11 index10 alt2\"><code class=\"python plain\">obj1 </code><code class=\"python keyword\">=</code> <code class=\"python plain\">Foo(</code><code class=\"python string\">\'wupeiqi\'</code><code class=\"python plain\">, </code><code class=\"python value\">18</code><code class=\"python plain\">)</code></div><div class=\"line number12 index11 alt1\"><code class=\"python plain\">obj1.detail() </code><code class=\"python comments\"># Python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code> </div><div class=\"line number14 index13 alt1\"><code class=\"python plain\">obj2 </code><code class=\"python keyword\">=</code> <code class=\"python plain\">Foo(</code><code class=\"python string\">\'alex\'</code><code class=\"python plain\">, </code><code class=\"python value\">73</code><code class=\"python plain\">)</code></div><div class=\"line number15 index14 alt2\"><code class=\"python plain\">obj2.detail() </code><code class=\"python comments\"># Python默认会将obj2传给self参数,即:obj1.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 alex ; self.age 是 78</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><span style=\"color: rgba(255, 0, 0, 1)\"><strong><span style=\"font-size: 13px\"><span style=\"background-color: rgba(255, 255, 255, 1)\">综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。</span></span></strong></span></p>\r\n<blockquote>\r\n<p><span style=\"font-size: 13px\"><strong>练习一</strong>:在终端输出如下信息</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\">小明,10岁,男,上山去砍柴</span></li>\r\n<li><span style=\"font-size: 13px\">小明,10岁,男,开车去东北</span></li>\r\n<li><span style=\"font-size: 13px\">小明,10岁,男,最爱大保健</span></li>\r\n<li></li>\r\n<li><span style=\"font-size: 13px\">老李,90岁,男,上山去砍柴</span></li>\r\n<li><span style=\"font-size: 13px\">老李,90岁,男,开车去东北</span></li>\r\n<li><span style=\"font-size: 13px\">老李,90岁,男,最爱大保健</span></li>\r\n<li></li>\r\n<li><span style=\"font-size: 13px\">老张...</span></li>\r\n</ul>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_c0615c27-88a6-449e-bbc3-d6b0c03bb5f3\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_c0615c27-88a6-449e-bbc3-d6b0c03bb5f3\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_c0615c27-88a6-449e-bbc3-d6b0c03bb5f3\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> kanchai(name, age, gender):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s,%s岁,%s,上山去砍柴</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">(name, age, gender)\r\n\r\n\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> qudongbei(name, age, gender):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s,%s岁,%s,开车去东北</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">(name, age, gender)\r\n\r\n\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> dabaojian(name, age, gender):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s,%s岁,%s,最爱大保健</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">(name, age, gender)\r\n\r\n\r\nkanchai(</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">小明</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 10, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nqudongbei(</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">小明</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 10, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\ndabaojian(</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">小明</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 10, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\n\r\n\r\nkanchai(</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">老李</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 90, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nqudongbei(</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">老李</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 90, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\ndabaojian(</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">老李</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 90, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">函数式编程</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_b38a68c1-2b43-4492-869e-b8ac5270e6ce\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_b38a68c1-2b43-4492-869e-b8ac5270e6ce\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_b38a68c1-2b43-4492-869e-b8ac5270e6ce\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Foo:\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span><span style=\"color: rgba(0, 0, 0, 1)\">(self, name, age ,gender):\r\n self.name </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> name\r\n self.age </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> age\r\n self.gender </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> gender\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> kanchai(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s,%s岁,%s,上山去砍柴</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">(self.name, self.age, self.gender)\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> qudongbei(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s,%s岁,%s,开车去东北</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">(self.name, self.age, self.gender)\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> dabaojian(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s,%s岁,%s,最爱大保健</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">(self.name, self.age, self.gender)\r\n\r\n\r\nxiaoming </span>= Foo(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">小明</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 10, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nxiaoming.kanchai()\r\nxiaoming.qudongbei()\r\nxiaoming.dabaojian()\r\n\r\nlaoli </span>= Foo(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">老李</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 90, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nlaoli.kanchai()\r\nlaoli.qudongbei()\r\nlaoli.dabaojian()</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">面向对象</span></div>\r\n<p><span style=\"font-size: 13px\"><em><span style=\"color: rgba(136, 136, 136, 1)\">上述对比可以看出,如果使用函数式编程,需要在每次执行函数时传入相同的参数,如果参数多的话,又需要粘贴复制了... ;而对于面向对象只需要在创建对象时,将所有需要的参数封装到当前对象中,之后再次使用时,通过self间接去当前对象中取值即可。</span></em></span></p>\r\n</blockquote>\r\n<p><span style=\"font-size: 13px\"><strong> </strong></span></p>\r\n<blockquote>\r\n<p><strong>练习二</strong>:游戏人生程序</p>\r\n<p><span style=\"font-size: 13px\">1、创建三个游戏人物,分别是:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\">苍井井,女,18,初始战斗力1000</span></li>\r\n<li><span style=\"font-size: 13px\">东尼木木,男,20,初始战斗力1800</span></li>\r\n<li><span style=\"font-size: 13px\">波多多,女,19,初始战斗力2500</span></li>\r\n</ul>\r\n<p><span style=\"font-size: 13px\">2、游戏场景,分别:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\">草丛战斗,消耗200战斗力</span></li>\r\n<li><span style=\"font-size: 13px\">自我修炼,增长100战斗力</span></li>\r\n<li><span style=\"font-size: 13px\">多人游戏,消耗500战斗力</span></li>\r\n</ul>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_9e8ab2c7-ec42-424f-adae-fc4c756d2138\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_9e8ab2c7-ec42-424f-adae-fc4c756d2138\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_9e8ab2c7-ec42-424f-adae-fc4c756d2138\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> -*- coding:utf-8 -*-</span>\r\n\r\n<span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> ##################### 定义实现功能的类 #####################</span>\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Person:\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span><span style=\"color: rgba(0, 0, 0, 1)\">(self, na, gen, age, fig):\r\n self.name </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> na\r\n self.gender </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> gen\r\n self.age </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> age\r\n self.fight </span>=<span style=\"color: rgba(0, 0, 0, 1)\">fig\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> grassland(self):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">注释:草丛战斗,消耗200战斗力</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n\r\n self.fight </span>= self.fight - 200\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> practice(self):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">注释:自我修炼,增长100战斗力</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n \r\n self.fight </span>= self.fight + 200\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> incest(self):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">注释:多人游戏,消耗500战斗力</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n \r\n self.fight </span>= self.fight - 500\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> detail(self):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">注释:当前对象的详细情况</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n\r\n temp </span>= <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">姓名:%s ; 性别:%s ; 年龄:%s ; 战斗力:%s</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\"> (self.name, self.gender, self.age, self.fight)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span><span style=\"color: rgba(0, 0, 0, 1)\"> temp\r\n\r\n \r\n</span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> ##################### 开始游戏 #####################</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\">\r\ncang </span>= Person(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">苍井井</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">女</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 18, 1000) <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 创建苍井井角色</span>\r\ndong = Person(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">东尼木木</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 20, 1800) <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 创建东尼木木角色</span>\r\nbo = Person(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">波多多</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">女</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 19, 2500) <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 创建波多多角色</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\">\r\ncang.incest() </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">苍井空参加一次多人游戏</span>\r\ndong.practice()<span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">东尼木木自我修炼了一次</span>\r\nbo.grassland() <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">波多多参加一次草丛战斗</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">输出当前所有人的详细情况</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\">cang.detail()\r\ndong.detail()\r\nbo.detail()\r\n\r\n\r\ncang.incest() </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">苍井空又参加一次多人游戏</span>\r\ndong.incest() <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">东尼木木也参加了一个多人游戏</span>\r\nbo.practice() <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">波多多自我修炼了一次</span>\r\n\r\n<span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\">输出当前所有人的详细情况</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\">cang.detail()\r\ndong.detail()\r\nbo.detail()</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">游戏人生</span></div>\r\n</blockquote>\r\n<p><span style=\"font-size: 14pt\"><strong>二、继承</strong></span></p>\r\n<p>继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。</p>\r\n<p>例如:</p>\r\n<p> 猫可以:喵喵叫、吃、喝、拉、撒</p>\r\n<p> 狗可以:汪汪叫、吃、喝、拉、撒</p>\r\n<p>如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,如下所示:</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_1cf1e23a-d12e-48cc-9caa-775b2ba59a1f\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_1cf1e23a-d12e-48cc-9caa-775b2ba59a1f\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_1cf1e23a-d12e-48cc-9caa-775b2ba59a1f\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> 猫:\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 喵喵叫(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">喵喵叫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 吃(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 喝(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 拉(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 撒(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> 狗:\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 汪汪叫(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">喵喵叫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 吃(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 喝(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 拉(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 撒(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">伪代码</span></div>\r\n<p>上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:</p>\r\n<p> 动物:吃、喝、拉、撒</p>\r\n<p> 猫:喵喵叫(猫继承动物的功能)</p>\r\n<p> 狗:汪汪叫(狗继承动物的功能)</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_f9d8a2c1-97bd-4cc4-a575-a917782284f1\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_f9d8a2c1-97bd-4cc4-a575-a917782284f1\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_f9d8a2c1-97bd-4cc4-a575-a917782284f1\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> 动物:\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 吃(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 喝(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 拉(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 撒(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n\r\n<span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 在类后面括号中写入另外一个类名,表示当前类继承另外一个类</span>\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> 猫(动物):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 喵喵叫(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">喵喵叫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n \r\n<span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 在类后面括号中写入另外一个类名,表示当前类继承另外一个类</span>\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> 狗(动物):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 汪汪叫(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">喵喵叫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">伪代码</span> </div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_6f1b4379-dc9f-4c07-9184-281d98788ff2\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_6f1b4379-dc9f-4c07-9184-281d98788ff2\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_6f1b4379-dc9f-4c07-9184-281d98788ff2\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Animal:\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> eat(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s 吃 </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">self.name\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> drink(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s 喝 </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">self.name\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> shit(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s 拉 </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">self.name\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> pee(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s 撒 </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">self.name\r\n\r\n\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Cat(Animal):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span><span style=\"color: rgba(0, 0, 0, 1)\">(self, name):\r\n self.name </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> name\r\n self.breed = </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">猫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> cry(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">喵喵叫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Dog(Animal):\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span><span style=\"color: rgba(0, 0, 0, 1)\">(self, name):\r\n self.name </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> name\r\n self.breed = </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">狗</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n \r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> cry(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">汪汪叫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n \r\n\r\n<span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> ######### 执行 #########</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\">\r\nc1 </span>= Cat(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">小白家的小黑猫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nc1.eat()\r\n\r\nc2 </span>= Cat(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">小黑的小白猫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nc2.drink()\r\n\r\nd1 </span>= Dog(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">胖子家的小瘦狗</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nd1.eat()</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">代码实例</span></div>\r\n<p><span style=\"color: rgba(255, 0, 0, 1)\"><strong>所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。</strong></span></p>\r\n<p><span style=\"color: rgba(128, 128, 128, 1)\"><em>注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。</em></span></p>\r\n<p><img src=\"https://images0.cnblogs.com/blog2015/425762/201508/272229566093488.jpg\" alt=\"\" width=\"515\" height=\"260\" class=\"medium-zoom-image\"></p>\r\n<p>学习了继承的写法之后,我们用代码来是上述阿猫阿狗的功能:</p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_658fe675-072f-433f-badc-60e4452c8493\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_658fe675-072f-433f-badc-60e4452c8493\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_658fe675-072f-433f-badc-60e4452c8493\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Animal:\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> eat(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s 吃 </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">self.name\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> drink(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s 喝 </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">self.name\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> shit(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s 拉 </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">self.name\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> pee(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">%s 撒 </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\">self.name\r\n\r\n\r\n</span><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Cat(Animal):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span><span style=\"color: rgba(0, 0, 0, 1)\">(self, name):\r\n self.name </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> name\r\n self.breed = </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">猫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> cry(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">喵喵叫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Dog(Animal):\r\n \r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span><span style=\"color: rgba(0, 0, 0, 1)\">(self, name):\r\n self.name </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> name\r\n self.breed = </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">狗</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n \r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> cry(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">汪汪叫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n \r\n\r\n<span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> ######### 执行 #########</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\">\r\nc1 </span>= Cat(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">小白家的小黑猫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nc1.eat()\r\n\r\nc2 </span>= Cat(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">小黑的小白猫</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nc2.drink()\r\n\r\nd1 </span>= Dog(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">胖子家的小瘦狗</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nd1.eat()</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">代码实例</span></div>\r\n<p><strong><span style=\"font-size: 15px\">那么问题又来了,<span style=\"font-size: 14pt\">多继承</span>呢?</span></strong></p>\r\n<ul>\r\n<li>是否可以继承多个类</li>\r\n<li>如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?</li>\r\n</ul>\r\n<p>1、Python的类可以继承多个类,Java和C#中则只能继承一个类</p>\r\n<p>2、Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:<span style=\"color: rgba(255, 0, 0, 1)\"><strong>深度优先</strong></span>和<strong><span style=\"color: rgba(255, 0, 0, 1)\">广度优先</span></strong></p>\r\n<p><img src=\"https://images0.cnblogs.com/blog2015/425762/201508/272315068126604.jpg\" alt=\"\" width=\"519\" height=\"201\" class=\"medium-zoom-image\"></p>\r\n<ul>\r\n<li>当类是经典类时,多继承情况下,会按照深度优先方式查找</li>\r\n<li>当类是新式类时,多继承情况下,会按照广度优先方式查找</li>\r\n</ul>\r\n<p>经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 <strong><span style=\"color: rgba(255, 0, 0, 1)\">当前类</span>或者<span style=\"color: rgba(255, 0, 0, 1)\">父类</span>继承了<span style=\"color: rgba(255, 0, 0, 1)\">object类</span></strong>,那么该类便是新式类,否则便是经典类。</p>\r\n<p><img src=\"https://images0.cnblogs.com/blog2015/425762/201508/272341313127410.jpg\" alt=\"\" width=\"370\" height=\"117\" class=\"medium-zoom-image\"> <img src=\"https://images0.cnblogs.com/blog2015/425762/201508/272341553282314.jpg\" alt=\"\" width=\"402\" height=\"117\" class=\"medium-zoom-image\"></p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_0983fe55-3b09-4133-bdc3-8720d76ee43d\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_0983fe55-3b09-4133-bdc3-8720d76ee43d\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_0983fe55-3b09-4133-bdc3-8720d76ee43d\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> D:\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> bar(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">D.bar</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> C(D):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> bar(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">C.bar</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> B(D):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> bar(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">B.bar</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> A(B, C):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> bar(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">A.bar</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n\r\na </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> A()\r\n</span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 执行bar方法时</span><span style=\"color: rgba(0, 128, 0, 1)\">\r\n#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错</span><span style=\"color: rgba(0, 128, 0, 1)\">\r\n#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 所以,查找顺序:A --> B --> D --> C</span><span style=\"color: rgba(0, 128, 0, 1)\">\r\n#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了</span>\r\na.bar()</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">经典类多继承</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_df67a3e6-ec77-4741-b0c2-399e68633e67\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_df67a3e6-ec77-4741-b0c2-399e68633e67\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_df67a3e6-ec77-4741-b0c2-399e68633e67\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> D(object):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> bar(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">D.bar</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> C(D):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> bar(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">C.bar</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> B(D):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> bar(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">B.bar</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> A(B, C):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> bar(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">A.bar</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n\r\na </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> A()\r\n</span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 执行bar方法时</span><span style=\"color: rgba(0, 128, 0, 1)\">\r\n#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错</span><span style=\"color: rgba(0, 128, 0, 1)\">\r\n#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 所以,查找顺序:A --> B --> C --> D</span><span style=\"color: rgba(0, 128, 0, 1)\">\r\n#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了</span>\r\na.bar()</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">新式类多继承</span></div>\r\n<p><span style=\"font-size: 12px\">经典类:首先去<strong><span style=\"color: rgba(255, 0, 0, 1)\">A</span></strong>类中查找,如果A类中没有,则继续去<strong><span style=\"color: rgba(255, 0, 0, 1)\">B</span></strong>类中找,如果B类中么有,则继续去<strong><span style=\"color: rgba(255, 0, 0, 1)\">D</span></strong>类中找,如果D类中么有,则继续去<span style=\"color: rgba(255, 0, 0, 1)\"><strong>C</strong></span>类中找,如果还是未找到,则报错</span></p>\r\n<p><span style=\"font-size: 12px\">新式类:首先去<strong><span style=\"color: rgba(255, 0, 0, 1)\">A</span></strong>类中查找,如果A类中没有,则继续去<span style=\"color: rgba(255, 0, 0, 1)\"><strong>B</strong></span>类中找,如果B类中么有,则继续去<strong><span style=\"color: rgba(255, 0, 0, 1)\">C</span></strong>类中找,如果C类中么有,则继续去<strong><span style=\"color: rgba(255, 0, 0, 1)\">D</span></strong>类中找,如果还是未找到,则报错</span></p>\r\n<p><span style=\"font-size: 12px\">注意:在上述查找过程中,一旦找到,则寻找过程立即中断,便不会再继续找了</span></p>\r\n<p><strong><span style=\"line-height: 1.5; font-size: 14pt\">三、多态 </span></strong></p>\r\n<p><span style=\"font-size: 13px\"> Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。</span></p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_5b30daad-67e5-4bbc-9329-99688f8135bd\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_5b30daad-67e5-4bbc-9329-99688f8135bd\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_5b30daad-67e5-4bbc-9329-99688f8135bd\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> F1:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">pass</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> S1(F1):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> show(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">S1.show</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> S2(F1):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> show(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">S2.show</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 由于在Java或C#中定义函数参数时,必须指定参数的类型</span><span style=\"color: rgba(0, 128, 0, 1)\">\r\n#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类</span><span style=\"color: rgba(0, 128, 0, 1)\">\r\n#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 而实际传入的参数是:S1对象和S2对象</span>\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> Func(F1 obj):\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">Func函数需要接收一个F1类型或者F1子类的类型</span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span>\r\n \r\n <span style=\"color: rgba(0, 0, 255, 1)\">print</span><span style=\"color: rgba(0, 0, 0, 1)\"> obj.show()\r\n \r\ns1_obj </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> S1()\r\nFunc(s1_obj) </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\">\r\ns2_obj </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> S2()\r\nFunc(s2_obj) </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">Python伪代码实现Java或C#的多态</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_a00f2b23-479e-4c89-9aff-37725df86036\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_a00f2b23-479e-4c89-9aff-37725df86036\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_a00f2b23-479e-4c89-9aff-37725df86036\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> F1:\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">pass</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> S1(F1):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> show(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">S1.show</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> S2(F1):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> show(self):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span> <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">S2.show</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>\r\n\r\n<span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> Func(obj):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span><span style=\"color: rgba(0, 0, 0, 1)\"> obj.show()\r\n\r\ns1_obj </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> S1()\r\nFunc(s1_obj) \r\n\r\ns2_obj </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> S2()\r\nFunc(s2_obj) </span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">Python “鸭子类型”</span></div>\r\n<h3><span style=\"font-size: 14pt\"><strong>总结 </strong></span><button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>以上就是本节对于面向对象初级知识的介绍,总结如下:</p>\r\n<ul>\r\n<li>面向对象是一种编程方式,此编程方式的实现是基于对 <strong>类</strong> 和 <strong>对象</strong> 的使用</li>\r\n<li>类 是一个模板,模板中包装了多个“函数”供使用</li>\r\n<li>对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数</li>\r\n<li>面向对象三大特性:封装、继承和多态</li>\r\n</ul>\r\n<p><span style=\"font-size: 14pt\"><strong>问答专区</strong></span></p>\r\n<p><strong>问题一:什么样的代码才是面向对象?</strong></p>\r\n<p><span style=\"color: rgba(136, 136, 136, 1)\"><em>答:从简单来说,如果程序中的所有功能都是用 类 和 对象 来实现,那么就是面向对象编程了。</em></span></p>\r\n<p><strong>问题二:函数式编程 和 面向对象 如何选择?分别在什么情况下使用?</strong></p>\r\n<p><em><span style=\"color: rgba(136, 136, 136, 1)\">答:须知:对于 C# 和 Java 程序员来说不存在这个问题,因为该两门语言只支持面向对象编程(不支持函数式编程)。而对于 Python 和 PHP 等语言却同时支持两种编程方式,且函数式编程能完成的操作,面向对象都可以实现;而面向对象的能完成的操作,函数式编程不行(函数式编程无法实现面向对象的封装功能)。</span></em></p>\r\n<p><em><span style=\"color: rgba(136, 136, 136, 1)\">所以,一般在Python开发中,<strong><span style=\"color: rgba(51, 51, 51, 1)\">全部使用面向对象</span></strong> 或 <span style=\"color: rgba(51, 51, 51, 1)\"><strong>面向对象和函数式混合使用</strong></span></span></em></p>\r\n<p><em><span style=\"color: rgba(136, 136, 136, 1)\">面向对象的应用场景:</span></em></p>\r\n<ol>\r\n<li><em><span style=\"color: rgba(136, 136, 136, 1)\">多函数需使用共同的值,如:数据库的增、删、改、查操作都需要连接数据库字符串、主机名、用户名和密码</span></em><br>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_98fccd82-5587-4762-acfe-828174d1c579\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_98fccd82-5587-4762-acfe-828174d1c579\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_98fccd82-5587-4762-acfe-828174d1c579\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> SqlHelper:\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span><span style=\"color: rgba(0, 0, 0, 1)\">(self, host, user, pwd):\r\n\r\n self.host </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> host\r\n self.user </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> user\r\n self.pwd </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> pwd\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 增(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 关闭数据库连接</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 删(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 关闭数据库连接</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 改(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 关闭数据库连接</span>\r\n\r\n <span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> 查(self):\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 使用主机名、用户名、密码(self.host 、self.user 、self.pwd)打开数据库连接</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> do something</span>\r\n <span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 关闭数据库连接# do something</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">Demo</span></div>\r\n</li>\r\n<li><em><span style=\"color: rgba(136, 136, 136, 1)\">需要创建多个事物,每个事物属性个数相同,但是值的需求</span></em><br><em><span style=\"color: rgba(136, 136, 136, 1)\">如:张三、李四、杨五,他们都有姓名、年龄、血型,但其都是不相同。即:属性个数相同,但值不相同</span></em><br>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_063f3a88-706c-4e85-8698-07c33fa2efd2\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_063f3a88-706c-4e85-8698-07c33fa2efd2\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_063f3a88-706c-4e85-8698-07c33fa2efd2\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> Person:\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> <span style=\"color: rgba(128, 0, 128, 1)\">__init__</span><span style=\"color: rgba(0, 0, 0, 1)\">(self, name ,age ,blood_type):\r\n\r\n self.name </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> name\r\n self.age </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> age\r\n self.blood_type </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> blood_type\r\n\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span><span style=\"color: rgba(0, 0, 0, 1)\"> detail(self):\r\n temp </span>= <span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">i am %s, age %s , blood type %s </span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> %<span style=\"color: rgba(0, 0, 0, 1)\"> (self.name, self.age, self.blood_type)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span><span style=\"color: rgba(0, 0, 0, 1)\"> temp\r\n\r\nzhangsan </span>= Person(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">张三</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 18, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">A</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nlisi </span>= Person(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">李四</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 73, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">AB</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">)\r\nyangwu </span>= Person(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">杨五</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, 84, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">A</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">Demo</span></div>\r\n</li>\r\n</ol>\r\n<p><strong>问题三:类和对象在内存中是如何保存?</strong></p>\r\n<p>答:<em><span style=\"color: rgba(136, 136, 136, 1)\">类以及类中的方法在内存中只有一份,而根据类创建的每一个对象都在内存中需要存一份,大致如下图:</span></em></p>\r\n<p><img src=\"https://images2015.cnblogs.com/blog/425762/201508/425762-20150829133530437-321533636.jpg\" alt=\"\" width=\"672\" height=\"327\" class=\"medium-zoom-image\"></p>\r\n<p><span style=\"color: rgba(136, 136, 136, 1)\"><em>如上图所示,根据类创建对象时,对象中除了封装 name 和 age 的值之外,还会保存一个<strong>类对象指针</strong>,该值指向当前对象的类。</em></span></p>\r\n<p><span style=\"color: rgba(136, 136, 136, 1)\"><em>当通过 obj1 执行 【方法一】 时,过程如下:</em></span></p>\r\n<ol>\r\n<li><span style=\"color: rgba(136, 136, 136, 1)\"><em>根据当前对象中的 类对象指针 找到类中的方法</em></span></li>\r\n<li><span style=\"color: rgba(136, 136, 136, 1)\"><em>将对象 obj1 当作参数传给 方法的第一个参数 self </em></span></li>\r\n</ol>\r\n<p> </p>\r\n<p>以上是本篇文章的全部内容,如果觉得有点点意思,右边的<strong><span style=\"font-size: 14pt; color: rgba(255, 0, 0, 1)\">推荐</span></strong>再等你哟 ! 下一篇<a href=\"http://www.cnblogs.com/wupeiqi/p/4766801.html\" target=\"_blank\" rel=\"noopener\">《面向对象进阶篇》</a></p>\r\n<p> </p>\r\n</div>', '2022-06-01', 0, 0, 0, 1, 2);
INSERT INTO `app01_article` VALUES (4, '什么很多IT公司不喜欢进过培训机构的人呢?', '这几天在知乎看到一个问题“为什么很多IT公司不喜欢进过培训机构的人呢?” 身为老男孩的教学负责人,这样的问题必然会引起我的关注, 花时间看了各路人士的回答, 我了个去,尽是对培训机构排山倒海的谩骂声, 负面评价不胜枚举, 看完久久不能释怀,心里堵的慌, 又委屈又气愤又无奈, 委屈的是自己辛苦为之奋斗', '<div id=\"cnblogs_post_body\" class=\"blogpost-body blogpost-body-html\">\r\n<p><span style=\"font-size: 13px\">Tyrion是一个基于Python实现的支持多个WEB框架的</span><span style=\"color: rgba(255, 0, 0, 1)\"><strong>Form表单验证</strong></span><span style=\"font-size: 13px\">组件,其</span><span style=\"font-size: 13px\">完美的支持Tornado、Django、Flask、Bottle Web框架。</span><span style=\"font-size: 13px\">Tyrion主要有两大重要动能:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\">表单验证</span></li>\r\n<li><span style=\"font-size: 13px\">生成HTML标签</span></li>\r\n<li><span style=\"font-size: 13px\">保留上次提交内容</span></li>\r\n</ul>\r\n<p><span style=\"font-size: 13px\">对于表单验证,告别书写重复的正则表达式对用户提交的数据进行验证的工作,从此解放双手,跟着我左手右手一个慢动作...</span></p>\r\n<p><span style=\"font-size: 13px\">对于生成HTML标签,不在人工书写html标签,让Tyrion帮你自动创建...</span></p>\r\n<p><span style=\"font-size: 13px\">对于保留上次提交内容,由于默认表单提交后页面刷新,原来输入的内容会清空,Tyrion可以保留上次提交内容。</span></p>\r\n<p><span style=\"font-size: 13px\">github:<a href=\"https://github.com/WuPeiqi/Tyrion\" target=\"_blank\" rel=\"noopener\">https://github.com/WuPeiqi/Tyrion</a></span></p>\r\n<p> </p>\r\n<p><span style=\"font-size: 13px\"><img style=\"display: block; margin-left: auto; margin-right: auto\" src=\"https://images2015.cnblogs.com/blog/425762/201610/425762-20161009185237561-173732312.gif\" alt=\"\" class=\"medium-zoom-image\"></span></p>\r\n<h3>使用文档<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><strong><span style=\"font-size: 18px\">1、下载安装</span></strong></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_368198\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python plain\">pip install PyTyrion </code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><span style=\"font-size: 13px\">github: <a href=\"https://github.com/WuPeiqi/Tyrion\" target=\"_blank\" rel=\"noopener\">https://github.com/WuPeiqi/Tyrion</a></span></p>\r\n<p><strong><span style=\"font-size: 18px\">2、配置WEB框架种类</span></strong></p>\r\n<p><span style=\"font-size: 13px\">由于Tyrion同时支持Tornado、Django、Flask、Bottle多个WEB框架,所有在使用前需要进行指定。</span> </p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_977788\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">import</code> <code class=\"python plain\">Tyrion</code></div><div class=\"line number2 index1 alt1\"><code class=\"python plain\">Tyrion.setup(</code><code class=\"python string\">\'tornado\'</code><code class=\"python plain\">) </code></div><div class=\"line number3 index2 alt2\"><code class=\"python comments\"># setup的参数有:tornado(默认)、django、bottle、flask</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><strong><span style=\"font-size: 18px\">3、创建Form类</span></strong></p>\r\n<p><span style=\"font-size: 13px\">Form类用于提供验证规则、插件属性、错误信息等</span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_232972\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Forms </code><code class=\"python keyword\">import</code> <code class=\"python plain\">Form</code></div><div class=\"line number2 index1 alt1\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Fields </code><code class=\"python keyword\">import</code> <code class=\"python plain\">StringField</code></div><div class=\"line number3 index2 alt2\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Fields </code><code class=\"python keyword\">import</code> <code class=\"python plain\">EmailField</code></div><div class=\"line number4 index3 alt1\"> </div><div class=\"line number5 index4 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">LoginForm(Form):</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">username </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'用户名不能为空\'</code><code class=\"python plain\">})</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">password </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'密码不能为空\'</code><code class=\"python plain\">})</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">email </code><code class=\"python keyword\">=</code> <code class=\"python plain\">EmailField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'邮箱不能为空\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'邮箱格式错误\'</code><code class=\"python plain\">})</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><strong><span style=\"font-size: 18px\">4、验证用户请求</span></strong></p>\r\n<p><span style=\"font-size: 13px\">前端HTML代码:</span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_301263\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python plain\"><form method</code><code class=\"python keyword\">=</code><code class=\"python string\">\"POST\"</code> <code class=\"python plain\">action</code><code class=\"python keyword\">=</code><code class=\"python string\">\"/login.html\"</code><code class=\"python plain\">></code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\"><div></code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\"><</code><code class=\"python functions\">input</code> <code class=\"python functions\">type</code><code class=\"python keyword\">=</code><code class=\"python string\">\"text\"</code> <code class=\"python plain\">name</code><code class=\"python keyword\">=</code><code class=\"python string\">\"username\"</code><code class=\"python plain\">></code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\"><</code><code class=\"python keyword\">/</code><code class=\"python plain\">div></code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\"><div></code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\"><</code><code class=\"python functions\">input</code> <code class=\"python functions\">type</code><code class=\"python keyword\">=</code><code class=\"python string\">\"text\"</code> <code class=\"python plain\">name</code><code class=\"python keyword\">=</code><code class=\"python string\">\"password\"</code><code class=\"python plain\">></code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\"><</code><code class=\"python keyword\">/</code><code class=\"python plain\">div></code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\"><div></code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\"><</code><code class=\"python functions\">input</code> <code class=\"python functions\">type</code><code class=\"python keyword\">=</code><code class=\"python string\">\"text\"</code> <code class=\"python plain\">name</code><code class=\"python keyword\">=</code><code class=\"python string\">\"email\"</code><code class=\"python plain\">></code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\"><</code><code class=\"python keyword\">/</code><code class=\"python plain\">div></code></div><div class=\"line number11 index10 alt2\"> </div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\"><</code><code class=\"python functions\">input</code> <code class=\"python functions\">type</code><code class=\"python keyword\">=</code><code class=\"python string\">\"submit\"</code> <code class=\"python plain\">value</code><code class=\"python keyword\">=</code><code class=\"python string\">\"提交\"</code><code class=\"python plain\">></code></div><div class=\"line number13 index12 alt2\"><code class=\"python plain\"><</code><code class=\"python keyword\">/</code><code class=\"python plain\">form></code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><span style=\"font-size: 13px\">用户提交数据时,在后台书写如下代码即可实现用户请求数据验证(Tornado示例):</span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_618642\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">LoginHandler(tornado.web.RequestHandler):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">get(</code><code class=\"python color1\">self</code><code class=\"python plain\">, </code><code class=\"python keyword\">*</code><code class=\"python plain\">args, </code><code class=\"python keyword\">*</code><code class=\"python keyword\">*</code><code class=\"python plain\">kwargs):</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.render(</code><code class=\"python string\">\'login.html\'</code><code class=\"python plain\">)</code></div><div class=\"line number4 index3 alt1\"> </div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">post(</code><code class=\"python color1\">self</code><code class=\"python plain\">, </code><code class=\"python keyword\">*</code><code class=\"python plain\">args, </code><code class=\"python keyword\">*</code><code class=\"python keyword\">*</code><code class=\"python plain\">kwargs):</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">form </code><code class=\"python keyword\">=</code> <code class=\"python plain\">LoginForm(</code><code class=\"python color1\">self</code><code class=\"python plain\">)</code></div><div class=\"line number7 index6 alt2\"> </div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">###### 检查用户输入是否合法 ######</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">if</code> <code class=\"python plain\">form.is_valid():</code></div><div class=\"line number10 index9 alt1\"> </div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\">###### 如果不合法,则输出错误信息 ######</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python functions\">print</code><code class=\"python plain\">(form.error_dict)</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python keyword\">else</code><code class=\"python plain\">:</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python comments\">###### 如果合法,则输出用户输入的内容 ######</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python functions\">print</code><code class=\"python plain\">(form.value_dict)</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.render(</code><code class=\"python string\">\'login.html\'</code><code class=\"python plain\">)</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><span style=\"font-size: 13px\"><strong><span style=\"color: rgba(255, 0, 0, 1)\">示例01</span></strong>:<a href=\"https://files.cnblogs.com/files/wupeiqi/Demo01.zip\" target=\"_blank\" rel=\"noopener\">源码下载(含Tornado、Django、Flask、Bottle)</a></span></p>\r\n<p><strong><span style=\"font-size: 18px\">5、验证用户请求 && 生成HTML标签 && 保留上次输入内容 && 错误提示</span></strong></p>\r\n<p><span style=\"font-size: 13px\">Tyrion不仅可以验证用户请求,还可以生成自动创建HTML标签并且可以保留用户上次输入的内容。在HTML模板中调用Form类对象的字段即可,如(Tornado示例):</span></p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_cae82d37-a89d-43eb-9ff9-a5cff7cff736\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_cae82d37-a89d-43eb-9ff9-a5cff7cff736\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_cae82d37-a89d-43eb-9ff9-a5cff7cff736\" class=\"cnblogs_code_hide\">\r\n<pre> <span style=\"color: rgba(0, 0, 255, 1)\">from</span> Tyrion.Forms <span style=\"color: rgba(0, 0, 255, 1)\">import</span><span style=\"color: rgba(0, 0, 0, 1)\"> Form\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">from</span> Tyrion.Fields <span style=\"color: rgba(0, 0, 255, 1)\">import</span><span style=\"color: rgba(0, 0, 0, 1)\"> StringField\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">from</span> Tyrion.Fields <span style=\"color: rgba(0, 0, 255, 1)\">import</span><span style=\"color: rgba(0, 0, 0, 1)\"> EmailField\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> LoginForm(Form):\r\n username </span>= StringField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">用户名不能为空</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">})\r\n password </span>= StringField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">密码不能为空</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">})\r\n email </span>= EmailField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">邮箱不能为空</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">invalid</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">邮箱格式错误</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>})</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">Form类</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_cd3839d8-f9ba-4f87-87aa-992d3ca2ee74\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_cd3839d8-f9ba-4f87-87aa-992d3ca2ee74\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_cd3839d8-f9ba-4f87-87aa-992d3ca2ee74\" class=\"cnblogs_code_hide\">\r\n<pre> <span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> LoginHandler(tornado.web.RequestHandler):\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> get(self, *args, **<span style=\"color: rgba(0, 0, 0, 1)\">kwargs):\r\n form </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> LoginForm(self)\r\n self.render(</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">login.html</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, form=<span style=\"color: rgba(0, 0, 0, 1)\">form)\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> post(self, *args, **<span style=\"color: rgba(0, 0, 0, 1)\">kwargs):\r\n form </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> LoginForm(self)\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span><span style=\"color: rgba(0, 0, 0, 1)\">(form.is_valid())\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span><span style=\"color: rgba(0, 0, 0, 1)\">(form.error_dict)\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">print</span><span style=\"color: rgba(0, 0, 0, 1)\">(form.value_dict)\r\n\r\n self.render(</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">login.html</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, form=form)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">处理请求(Tornado)</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_e84b2cb3-4b1b-4f22-8da8-b8c51a18f18c\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_e84b2cb3-4b1b-4f22-8da8-b8c51a18f18c\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_e84b2cb3-4b1b-4f22-8da8-b8c51a18f18c\" class=\"cnblogs_code_hide\">\r\n<pre> <form method=<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">post</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> action=<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">/login.html</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>>\r\n <div>\r\n <!-- Form创建的标签 --><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {</span>% raw form.username %<span style=\"color: rgba(0, 0, 0, 1)\">}\r\n\r\n </span><!-- 错误信息 -->\r\n <span>{{form.error_dict.get(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">username</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>,<span style=\"color: rgba(128, 0, 0, 1)\">\"\"</span>)}}</span>\r\n </div>\r\n <div><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {</span>% raw form.password %<span style=\"color: rgba(0, 0, 0, 1)\">}\r\n </span><span>{{form.error_dict.get(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">password</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>,<span style=\"color: rgba(128, 0, 0, 1)\">\"\"</span>)}}</span>\r\n </div>\r\n <div><span style=\"color: rgba(0, 0, 0, 1)\">\r\n {</span>% raw form.email %<span style=\"color: rgba(0, 0, 0, 1)\">}\r\n </span><span>{{form.error_dict.get(<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">email</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>,<span style=\"color: rgba(128, 0, 0, 1)\">\"\"</span>)}}</span>\r\n </div>\r\n <input type=<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">submit</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span> value=<span style=\"color: rgba(128, 0, 0, 1)\">\"</span><span style=\"color: rgba(128, 0, 0, 1)\">提交</span><span style=\"color: rgba(128, 0, 0, 1)\">\"</span>/>\r\n </form></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">HTML模板login.html</span></div>\r\n<p><span style=\"font-size: 13px\"><em><span style=\"color: rgba(136, 136, 136, 1)\">注意: HTML模板中的转义</span></em></span></p>\r\n<p><strong><span style=\"color: rgba(255, 0, 0, 1)\">示例02</span></strong>:<a href=\"https://files.cnblogs.com/files/wupeiqi/Demo02.zip\" target=\"_blank\" rel=\"noopener\">源码下载(含有Tornado、Django、Flask、Bottle)</a></p>\r\n<p><strong><span style=\"font-size: 18px\">6、Form字段类型</span></strong></p>\r\n<p><span style=\"font-size: 13px\">Form的字段用于指定从请求中获取的数据类型以及格式,以此来验证用户输入的内容。</span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_943647\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Forms </code><code class=\"python keyword\">import</code> <code class=\"python plain\">Form</code></div><div class=\"line number2 index1 alt1\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Fields </code><code class=\"python keyword\">import</code> <code class=\"python plain\">StringField</code></div><div class=\"line number3 index2 alt2\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Fields </code><code class=\"python keyword\">import</code> <code class=\"python plain\">EmailField</code></div><div class=\"line number4 index3 alt1\"> </div><div class=\"line number5 index4 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">LoginForm(Form):</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">username </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'用户名不能为空\'</code><code class=\"python plain\">})</code></div><div class=\"line number7 index6 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">password </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'密码不能为空\'</code><code class=\"python plain\">})</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">email </code><code class=\"python keyword\">=</code> <code class=\"python plain\">EmailField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'邮箱不能为空\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'邮箱格式错误\'</code><code class=\"python plain\">})</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><span style=\"font-size: 13px\">以上代码表示此Form类可以用于验证用户输入的内容,并且 username和password必须不能为空,email必须不能为空并且必须是邮箱格式。</span></p>\r\n<p><span style=\"font-size: 13px\">目前支持所有字段:</span></p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_2b9ab8f9-44c3-4c79-a2e2-f48ba259d8f6\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_2b9ab8f9-44c3-4c79-a2e2-f48ba259d8f6\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_2b9ab8f9-44c3-4c79-a2e2-f48ba259d8f6\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 0, 1)\">StringField\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 要求必须是字符串,即:正则^.*$\r\n \r\n 参数:\r\n required 布尔值,是否允许为空\r\n max_length 整数,限制用户输入内容最大长度\r\n min_length 整数,限制用户输入内容最小长度\r\n error 字典,自定义错误提示,如:{\r\n \'required\': \'值为空时的错误提示\',\r\n \'invalid\': \'格式错误时的错误提示\',\r\n \'max_length\': \'最大长度为10\',\r\n \'min_length\': \'最小长度为1\',\r\n }\r\n widget 定制生成的HTML插件(默认InputText)\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n \r\nEmailField\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 要求必须是邮箱格式的字符串\r\n \r\n 参数:\r\n required 布尔值,是否允许为空\r\n max_length 整数,限制用户输入内容最大长度\r\n min_length 整数,限制用户输入内容最小长度\r\n error 字典,自定义错误提示,如:{\r\n \'required\': \'值为空时的错误提示\',\r\n \'invalid\': \'格式错误时的错误提示\',\r\n \'max_length\': \'最大长度为10\',\r\n \'min_length\': \'最小长度为1\',\r\n }\r\n widget 定制生成的HTML插件(默认InputText)\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n \r\nIPField\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 要求必须是IP格式\r\n \r\n 参数:\r\n required 布尔值,是否允许为空\r\n max_length 整数,限制用户输入内容最大长度\r\n min_length 整数,限制用户输入内容最小长度\r\n error 字典,自定义错误提示,如:{\r\n \'required\': \'值为空时的错误提示\',\r\n \'invalid\': \'格式错误时的错误提示\',\r\n \'max_length\': \'最大长度为10\',\r\n \'min_length\': \'最小长度为1\',\r\n }\r\n widget 定制生成的HTML插件(默认InputText)\r\n \r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n \r\nIntegerField\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 要求必须整数格式\r\n \r\n 参数:\r\n required 布尔值,是否允许为空\r\n max_value 整数,限制用户输入数字最大值\r\n min_value 整数,限制用户输入数字最小值\r\n error 字典,自定义错误提示,如:{\r\n \'required\': \'值为空时的错误提示\',\r\n \'invalid\': \'格式错误时的错误提示\',\r\n \'max_value\': \'最大值为10\',\r\n \'max_value\': \'最小值度为1\',\r\n }\r\n widget 定制生成的HTML插件(默认InputText)\r\n \r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n \r\nFloatField\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 要求必须小数格式\r\n \r\n 参数:\r\n required 布尔值,是否允许为空\r\n max_value 整数,限制用户输入数字最大值\r\n min_value 整数,限制用户输入数字最小值\r\n error 字典,自定义错误提示,如:{\r\n \'required\': \'值为空时的错误提示\',\r\n \'invalid\': \'格式错误时的错误提示\',\r\n \'max_value\': \'最大值为10\',\r\n \'max_value\': \'最小值度为1\',\r\n }\r\n widget 定制生成的HTML插件(默认InputText)\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n \r\nStringListField\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 用于获取请求中的多个值,且保证每一个元素是字符串,即:正则^.*$\r\n 如:checkbox或selct多选时,会提交多个值,用此字段可以将用户提交的值保存至列表\r\n \r\n 参数:\r\n required 布尔值,是否允许为空\r\n ele_max_length 整数,限制用户输入的每个元素内容最大长度\r\n ele_min_length 整数,限制用户输入的每个元素内容最小长度\r\n error 字典,自定义错误提示,如:{\r\n \'required\': \'值为空时的错误提示\',\r\n \'element\': \'列表中的元素必须是字符串\',\r\n \'ele_max_length\': \'最大长度为10\',\r\n \'ele_min_length\': \'最小长度为1\',\r\n }\r\n widget 定制生成的HTML插件(默认InputMultiCheckBox,即:checkbox)\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n \r\nIntegerListField\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 用于获取请求中的多个值,且保证每一个元素是整数\r\n 如:checkbox或selct多选时,会提交多个值,用此字段可以将用户提交的值保存至列表\r\n \r\n 参数:\r\n required 布尔值,是否允许为空\r\n ele_max_value 整数,限制用户输入的每个元素内容最大长度\r\n ele_min_value 整数,限制用户输入的每个元素内容最小长度\r\n error 字典,自定义错误提示,如:{\r\n \'required\': \'值为空时的错误提示\',\r\n \'element\': \'列表中的元素必须是数字\',\r\n \'ele_max_value\': \'最大值为x\',\r\n \'ele_min_value\': \'最小值为x\',\r\n }\r\n widget 定制生成的HTML插件(默认InputMultiCheckBox,即:checkbox)\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">View Code</span></div>\r\n<p><strong><span style=\"font-size: 18px\">7、Form字段widget参数:HTML插件</span></strong></p>\r\n<p><span style=\"font-size: 13px\">HTML插件用于指定当前字段在生成HTML时表现的种类和属性,通过指定此参数从而实现定制页面上生成的HTML标签</span></p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_184097\" class=\"syntaxhighlighter python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Forms </code><code class=\"python keyword\">import</code> <code class=\"python plain\">Form</code></div><div class=\"line number2 index1 alt1\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Fields </code><code class=\"python keyword\">import</code> <code class=\"python plain\">StringField</code></div><div class=\"line number3 index2 alt2\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Fields </code><code class=\"python keyword\">import</code> <code class=\"python plain\">EmailField</code></div><div class=\"line number4 index3 alt1\"> </div><div class=\"line number5 index4 alt2\"><code class=\"python keyword\">from</code> <code class=\"python plain\">Tyrion.Widget </code><code class=\"python keyword\">import</code> <code class=\"python plain\">InputPassword</code></div><div class=\"line number6 index5 alt1\"> </div><div class=\"line number7 index6 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">LoginForm(Form):</code></div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">password </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'密码不能为空\'</code><code class=\"python plain\">},widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">InputPassword())</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p><span style=\"font-size: 13px\">上述LoginForm的password字段要求用户输入必须是字符串类型,并且指定生成HTML标签时会创建为<input type=\'password\' > 标签</span></p>\r\n<p><span style=\"font-size: 13px\">目前支持所有插件:</span></p>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_3f6e6d72-5ffd-46d3-9f58-4b3ae2cfacf8\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_3f6e6d72-5ffd-46d3-9f58-4b3ae2cfacf8\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_3f6e6d72-5ffd-46d3-9f58-4b3ae2cfacf8\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 0, 1)\"> InputText\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 设置Form对应字段在HTML中生成input type=\'text\' 标签\r\n\r\n 参数:\r\n attr 字典,指定生成标签的属性,如: attr = {\'class\': \'c1\', \'placeholder\': \'username\'}\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n InputEmail\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 设置Form对应字段在HTML中生成input type=\'email\' 标签\r\n\r\n 参数:\r\n attr 字典,指定生成标签的属性,如: attr = {\'class\': \'c1\', \'placeholder\': \'username\'}\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n InputPassword\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 设置Form对应字段在HTML中生成input type=\'password\' 标签\r\n\r\n 参数:\r\n attr 字典,指定生成标签的属性,如: attr = {\'class\': \'c1\', \'placeholder\': \'username\'}\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n TextArea\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 设置Form对应字段在HTML中生成 textarea 标签\r\n\r\n 参数:\r\n attr 字典,指定生成标签的属性,如: attr = {\'class\': \'c1\'}\r\n value 字符串,用于设置textarea标签中默认显示的内容\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n\r\n InputRadio\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 设置Form对应字段在HTML中生成一系列 input type=\'radio\' 标签(选择时互斥)\r\n\r\n 参数:\r\n attr 字典,生成的HTML属性,如:{\'class\': \'c1\'}\r\n text_value_list 列表,生成的多个radio标签的内容和值,如:[\r\n {\'value\':1, \'text\': \'男\'},\r\n {\'value\':2, \'text\': \'女\'},\r\n ]\r\n checked_value 整数或字符串,默认被选中的标签的value的值\r\n\r\n 示例:\r\n from Tyrion.Forms import Form\r\n from Tyrion.Fields import IntegerField\r\n\r\n from Tyrion.Widget import InputRadio\r\n\r\n\r\n class LoginForm(Form):\r\n favor = IntegerField(error={\'required\': \'爱好不能为空\'},\r\n widget=InputRadio(attr={\'class\': \'c1\'},\r\n text_value_list=[\r\n {\'value\': 1, \'text\': \'男\'},\r\n {\'value\': 2, \'text\': \'女\'}, ],\r\n checked_value=2\r\n )\r\n )\r\n 上述favor字段生成的HTML标签为:\r\n <div>\r\n <span>\r\n <input class=\'c1\' type=\"radio\" name=\"gender\" value=\"1\">\r\n </span>\r\n <span>男</span>\r\n </div>\r\n <div>\r\n <span>\r\n <input class=\'c1\' type=\"radio\" name=\"gender\" value=\"2\" checked=\'checked\'>\r\n </span>\r\n <span>女</span>\r\n </div>\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n\r\n InputSingleCheckBox\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 设置Form对应字段在HTML中生成 input type=\'checkbox\' 标签\r\n 参数:\r\n attr 字典,指定生成标签的属性,如: attr = {\'class\': \'c1\'}\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n\r\n InputMultiCheckBox\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 设置Form对应字段在HTML中生成一系列 input type=\'checkbox\' 标签\r\n\r\n 参数:\r\n attr 字典,指定生成标签的属性,如: attr = {\'class\': \'c1\'}\r\n text_value_list 列表,生成的多个checkbox标签的内容和值,如:[\r\n {\'value\':1, \'text\': \'篮球\'},\r\n {\'value\':2, \'text\': \'足球\'},\r\n {\'value\':3, \'text\': \'乒乓球\'},\r\n {\'value\':4, \'text\': \'羽毛球\'},\r\n ]\r\n checked_value_list 列表,默认选中的标签对应的value, 如:[1,3]\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n SingleSelect\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 设置Form对应字段在HTML中生成 单选select 标签\r\n\r\n 参数:\r\n attr 字典,指定生成标签的属性,如: attr = {\'class\': \'c1\'}\r\n text_value_list 列表,用于指定select标签中的option,如:[\r\n {\'value\':1, \'text\': \'北京\'},\r\n {\'value\':2, \'text\': \'上海\'},\r\n {\'value\':3, \'text\': \'广州\'},\r\n {\'value\':4, \'text\': \'重庆\'},\r\n ]\r\n selected_value 数字或字符串,默认被选中选项对应的值,如: 3\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(0, 0, 0, 1)\">\r\n\r\n MultiSelect\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span><span style=\"color: rgba(128, 0, 0, 1)\">\r\n 设置Form对应字段在HTML中生成 多选select 标签\r\n\r\n 参数:\r\n attr 字典,指定生成标签的属性,如: attr = {\'class\': \'c1\'}\r\n text_value_list 列表,用于指定select标签中的option,如:[\r\n {\'value\':1, \'text\': \'篮球\'},\r\n {\'value\':2, \'text\': \'足球\'},\r\n {\'value\':3, \'text\': \'乒乓球\'},\r\n {\'value\':4, \'text\': \'羽毛球\'},\r\n ]\r\n selected_value_list 列表,默认被选中选项对应的值,如:[2,3,4]\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\"\"\"</span></pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">View Code</span></div>\r\n<p><strong><span style=\"font-size: 18px\">8、动态初始化默认值</span></strong></p>\r\n<p><span style=\"font-size: 13px\">由于Form可以用于生成HTML标签,如果想要在创建标签的同时再为其设置默认值有两种方式:</span></p>\r\n<ul>\r\n<li><span style=\"font-size: 13px\">静态,在插件参数中指定</span></li>\r\n<li><span style=\"font-size: 13px\">动态,调用Form对象的 init_field_value 方法来指定</span></li>\r\n</ul>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_52b9043d-4f8c-4926-93e7-d603f08ffc31\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_52b9043d-4f8c-4926-93e7-d603f08ffc31\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_52b9043d-4f8c-4926-93e7-d603f08ffc31\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> InitValueForm(Form):\r\n username </span>= StringField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">用户名不能为空</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">})\r\n age </span>= IntegerField(max_value=500<span style=\"color: rgba(0, 0, 0, 1)\">,\r\n min_value</span>=<span style=\"color: rgba(0, 0, 0, 1)\">0,\r\n error</span>={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">年龄不能为空</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">invalid</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">年龄必须为数字</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">min_value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">年龄不能小于0</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">max_value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">年龄不能大于500</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">})\r\n\r\n city </span>= IntegerField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">年龄不能为空</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">invalid</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">年龄必须为数字</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">},\r\n widget</span>=SingleSelect(text_value_list=[{<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 1, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">上海</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">},\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 2, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">北京</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">},\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 3, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">广州</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">}])\r\n )\r\n\r\n gender </span>= IntegerField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">请选择性别</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">invalid</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">性别必须为数字</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">},\r\n widget</span>=InputRadio(text_value_list=[{<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 1, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">男</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 2, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">女</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, }],\r\n checked_value</span>=2<span style=\"color: rgba(0, 0, 0, 1)\">))\r\n\r\n protocol </span>= IntegerField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">请选择协议</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">invalid</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">协议格式错误</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">},\r\n widget</span>=InputSingleCheckBox(attr={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 1<span style=\"color: rgba(0, 0, 0, 1)\">}))\r\n\r\n favor_int_val </span>= IntegerListField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">请选择爱好</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">invalid</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">选择爱好格式错误</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">},\r\n widget</span>=InputMultiCheckBox(text_value_list=[{<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 1, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">篮球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 2, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">足球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 3, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">乒乓球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 4, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">羽毛球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">}, ]))\r\n\r\n favor_str_val </span>= StringListField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">请选择爱好</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">invalid</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">选择爱好格式错误</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">},\r\n widget</span>=InputMultiCheckBox(text_value_list=[{<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">1</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">篮球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">2</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">足球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">3</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">乒乓球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">4</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">羽毛球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">}, ]))\r\n\r\n select_str_val </span>= StringListField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">请选择爱好</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">invalid</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">选择爱好格式错误</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">},\r\n widget</span>=MultiSelect(text_value_list=[{<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">1</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">篮球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">2</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">足球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">3</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">乒乓球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">4</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">羽毛球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">}, ]))\r\n\r\n select_int_val </span>= IntegerListField(error={<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">required</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">请选择爱好</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">invalid</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">选择爱好格式错误</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">},\r\n widget</span>=MultiSelect(text_value_list=[{<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 1, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">篮球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 2, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">足球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 3, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">乒乓球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">, },\r\n {</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">value</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 4, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">text</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">羽毛球</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>}, ]))</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">动态初始值 - Form类</span></div>\r\n<div class=\"cnblogs_code\"><img id=\"code_img_closed_1dd03bd5-67d5-4de8-872a-154452620c47\" class=\"code_img_closed\" src=\"https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif\" alt=\"\"><img id=\"code_img_opened_1dd03bd5-67d5-4de8-872a-154452620c47\" class=\"code_img_opened\" style=\"display: none\" src=\"https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif\" alt=\"\">\r\n<div id=\"cnblogs_code_open_1dd03bd5-67d5-4de8-872a-154452620c47\" class=\"cnblogs_code_hide\">\r\n<pre><span style=\"color: rgba(0, 0, 255, 1)\">class</span><span style=\"color: rgba(0, 0, 0, 1)\"> InitValueHandler(tornado.web.RequestHandler):\r\n\r\n </span><span style=\"color: rgba(0, 0, 255, 1)\">def</span> get(self, *args, **<span style=\"color: rgba(0, 0, 0, 1)\">kwargs):\r\n form </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> InitValueForm(self)\r\n\r\n init_dict </span>=<span style=\"color: rgba(0, 0, 0, 1)\"> {\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">username</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">seven</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">age</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 18<span style=\"color: rgba(0, 0, 0, 1)\">,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">city</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 2<span style=\"color: rgba(0, 0, 0, 1)\">,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">gender</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 2<span style=\"color: rgba(0, 0, 0, 1)\">,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">protocol</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: 1<span style=\"color: rgba(0, 0, 0, 1)\">,\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">favor_int_val</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: [1, 3<span style=\"color: rgba(0, 0, 0, 1)\">],\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">favor_str_val</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: [<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">1</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">3</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">],\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">select_int_val</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: [1, 3<span style=\"color: rgba(0, 0, 0, 1)\">],\r\n </span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">select_str_val</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>: [<span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">1</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, <span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">3</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(0, 0, 0, 1)\">]\r\n\r\n }\r\n\r\n </span><span style=\"color: rgba(0, 128, 0, 1)\">#</span><span style=\"color: rgba(0, 128, 0, 1)\"> 初始化操作,设置Form类中默认值以及默认选项</span>\r\n<span style=\"color: rgba(0, 0, 0, 1)\"> form.init_field_value(init_dict)\r\n\r\n self.render(</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span><span style=\"color: rgba(128, 0, 0, 1)\">init_value.html</span><span style=\"color: rgba(128, 0, 0, 1)\">\'</span>, form=form)</pre>\r\n</div>\r\n<span class=\"cnblogs_code_collapse\">动态初始值 - 处理请求的Handler(Tornado)</span></div>\r\n<p><strong><span style=\"font-size: 18px\">9、更多示例</span></strong></p>\r\n<p>示例源码下载:<a href=\"https://files.cnblogs.com/files/wupeiqi/Tyrion%E7%A4%BA%E4%BE%8B%E6%BA%90%E7%A0%81.zip\" target=\"_blank\" rel=\"noopener\">猛击这里</a></p>\r\n<p>a. 基本使用</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_302468\" class=\"syntaxhighlighter collapsed python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div><div class=\"line number27 index26 alt2\">27</div><div class=\"line number28 index27 alt1\">28</div><div class=\"line number29 index28 alt2\">29</div><div class=\"line number30 index29 alt1\">30</div><div class=\"line number31 index30 alt2\">31</div><div class=\"line number32 index31 alt1\">32</div><div class=\"line number33 index32 alt2\">33</div><div class=\"line number34 index33 alt1\">34</div><div class=\"line number35 index34 alt2\">35</div><div class=\"line number36 index35 alt1\">36</div><div class=\"line number37 index36 alt2\">37</div><div class=\"line number38 index37 alt1\">38</div><div class=\"line number39 index38 alt2\">39</div><div class=\"line number40 index39 alt1\">40</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">RegisterForm(Form):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">username </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringField(max_length</code><code class=\"python keyword\">=</code><code class=\"python value\">32</code><code class=\"python plain\">,</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">min_length</code><code class=\"python keyword\">=</code><code class=\"python value\">6</code><code class=\"python plain\">,</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'用户名不能为空\'</code><code class=\"python plain\">,</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python string\">\'min_length\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'用户名不能少于6位\'</code><code class=\"python plain\">,</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python string\">\'max_length\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'用户名不能超过32位\'</code><code class=\"python plain\">})</code></div><div class=\"line number7 index6 alt2\"> </div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">password </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringField(max_length</code><code class=\"python keyword\">=</code><code class=\"python value\">32</code><code class=\"python plain\">,</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">min_length</code><code class=\"python keyword\">=</code><code class=\"python value\">6</code><code class=\"python plain\">,</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'密码不能为空\'</code><code class=\"python plain\">},</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">InputPassword())</code></div><div class=\"line number12 index11 alt1\"> </div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">gender </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择性别\'</code><code class=\"python plain\">,</code></div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'性别必须为数字\'</code><code class=\"python plain\">},</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">InputRadio(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'男\'</code><code class=\"python plain\">, },</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'女\'</code><code class=\"python plain\">, }],</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">checked_value</code><code class=\"python keyword\">=</code><code class=\"python value\">2</code><code class=\"python plain\">))</code></div><div class=\"line number18 index17 alt1\"> </div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">age </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerField(max_value</code><code class=\"python keyword\">=</code><code class=\"python value\">500</code><code class=\"python plain\">,</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">min_value</code><code class=\"python keyword\">=</code><code class=\"python value\">0</code><code class=\"python plain\">,</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'年龄不能为空\'</code><code class=\"python plain\">,</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'年龄必须为数字\'</code><code class=\"python plain\">,</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python string\">\'min_value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'年龄不能小于0\'</code><code class=\"python plain\">,</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python string\">\'max_value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'年龄不能大于500\'</code><code class=\"python plain\">})</code></div><div class=\"line number25 index24 alt2\"> </div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">email </code><code class=\"python keyword\">=</code> <code class=\"python plain\">EmailField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'邮箱不能为空\'</code><code class=\"python plain\">,</code></div><div class=\"line number27 index26 alt2\"><code class=\"python spaces\"> </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'邮箱格式错误\'</code><code class=\"python plain\">})</code></div><div class=\"line number28 index27 alt1\"> </div><div class=\"line number29 index28 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">city </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'城市选项不能为空\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'城市选项必须为数字\'</code><code class=\"python plain\">},</code></div><div class=\"line number30 index29 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">SingleSelect(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'上海\'</code><code class=\"python plain\">},</code></div><div class=\"line number31 index30 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'北京\'</code><code class=\"python plain\">},</code></div><div class=\"line number32 index31 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">3</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'广州\'</code><code class=\"python plain\">}])</code></div><div class=\"line number33 index32 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">)</code></div><div class=\"line number34 index33 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">protocol </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择协议\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'协议格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number35 index34 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">InputSingleCheckBox(attr</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">}))</code></div><div class=\"line number36 index35 alt1\"> </div><div class=\"line number37 index36 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">memo </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringField(required</code><code class=\"python keyword\">=</code><code class=\"python color1\">False</code><code class=\"python plain\">,</code></div><div class=\"line number38 index37 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">max_length</code><code class=\"python keyword\">=</code><code class=\"python value\">150</code><code class=\"python plain\">,</code></div><div class=\"line number39 index38 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'备注格式错误\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'max_length\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'备注最大长度为150字\'</code><code class=\"python plain\">},</code></div><div class=\"line number40 index39 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">TextArea())</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>b. 多选checkbox</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_898300\" class=\"syntaxhighlighter collapsed python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">MultiCheckBoxForm(Form):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">favor_str_val </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringListField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择爱好\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'选择爱好格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">InputMultiCheckBox(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'1\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'2\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'3\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'4\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">}, ]))</code></div><div class=\"line number7 index6 alt2\"> </div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">favor_str_val_default </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringListField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择爱好\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'选择爱好格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">InputMultiCheckBox(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'1\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'2\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'3\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'4\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">}, ],</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">checked_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[</code><code class=\"python string\">\'1\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'4\'</code><code class=\"python plain\">]))</code></div><div class=\"line number14 index13 alt1\"> </div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">favor_int_val </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerListField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择爱好\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'选择爱好格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">InputMultiCheckBox(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">3</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">4</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">}, ]))</code></div><div class=\"line number20 index19 alt1\"> </div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">favor_int_val_default </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerListField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择爱好\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'选择爱好格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">InputMultiCheckBox(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">3</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number25 index24 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">4</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">}, ],</code></div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">checked_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[</code><code class=\"python value\">2</code><code class=\"python plain\">, ]))</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>c、多选select</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_204370\" class=\"syntaxhighlighter collapsed python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">MultiSelectForm(Form):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">select_str_val </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringListField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择爱好\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'选择爱好格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">MultiSelect(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'1\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'2\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'3\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'4\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">}, ]))</code></div><div class=\"line number7 index6 alt2\"> </div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">select_str_val_default </code><code class=\"python keyword\">=</code> <code class=\"python plain\">StringListField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择爱好\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'选择爱好格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">MultiSelect(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'1\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'2\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'3\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'4\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">}, ],</code></div><div class=\"line number13 index12 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">selected_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[</code><code class=\"python string\">\'1\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'3\'</code><code class=\"python plain\">]))</code></div><div class=\"line number14 index13 alt1\"> </div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">select_int_val </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerListField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择爱好\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'选择爱好格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number16 index15 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">MultiSelect(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">3</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">4</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">}, ]))</code></div><div class=\"line number20 index19 alt1\"> </div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">select_int_val_default </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerListField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择爱好\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'选择爱好格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number22 index21 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">MultiSelect(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">3</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number25 index24 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">4</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">}, ],</code></div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">selected_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[</code><code class=\"python value\">2</code><code class=\"python plain\">]))</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<p>d. 动态select选项</p>\r\n<div class=\"cnblogs_Highlighter sh-gutter\">\r\n<div><div id=\"highlighter_142739\" class=\"syntaxhighlighter collapsed python\"><div class=\"toolbar\"><span><a href=\"#\" class=\"toolbar_item command_expandSource expandSource\">+ View Code</a></span><span><a href=\"#\" class=\"toolbar_item command_help help\">?</a></span></div><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody><tr><td class=\"gutter\"><div class=\"line number1 index0 alt2\">1</div><div class=\"line number2 index1 alt1\">2</div><div class=\"line number3 index2 alt2\">3</div><div class=\"line number4 index3 alt1\">4</div><div class=\"line number5 index4 alt2\">5</div><div class=\"line number6 index5 alt1\">6</div><div class=\"line number7 index6 alt2\">7</div><div class=\"line number8 index7 alt1\">8</div><div class=\"line number9 index8 alt2\">9</div><div class=\"line number10 index9 alt1\">10</div><div class=\"line number11 index10 alt2\">11</div><div class=\"line number12 index11 alt1\">12</div><div class=\"line number13 index12 alt2\">13</div><div class=\"line number14 index13 alt1\">14</div><div class=\"line number15 index14 alt2\">15</div><div class=\"line number16 index15 alt1\">16</div><div class=\"line number17 index16 alt2\">17</div><div class=\"line number18 index17 alt1\">18</div><div class=\"line number19 index18 alt2\">19</div><div class=\"line number20 index19 alt1\">20</div><div class=\"line number21 index20 alt2\">21</div><div class=\"line number22 index21 alt1\">22</div><div class=\"line number23 index22 alt2\">23</div><div class=\"line number24 index23 alt1\">24</div><div class=\"line number25 index24 alt2\">25</div><div class=\"line number26 index25 alt1\">26</div><div class=\"line number27 index26 alt2\">27</div></td><td class=\"code\"><div class=\"container\"><div class=\"line number1 index0 alt2\"><code class=\"python keyword\">class</code> <code class=\"python plain\">DynamicSelectForm(Form):</code></div><div class=\"line number2 index1 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">city </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'年龄不能为空\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'年龄必须为数字\'</code><code class=\"python plain\">},</code></div><div class=\"line number3 index2 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">SingleSelect(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'上海\'</code><code class=\"python plain\">},</code></div><div class=\"line number4 index3 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'北京\'</code><code class=\"python plain\">},</code></div><div class=\"line number5 index4 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">3</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'广州\'</code><code class=\"python plain\">}])</code></div><div class=\"line number6 index5 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">)</code></div><div class=\"line number7 index6 alt2\"> </div><div class=\"line number8 index7 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">multi_favor </code><code class=\"python keyword\">=</code> <code class=\"python plain\">IntegerListField(error</code><code class=\"python keyword\">=</code><code class=\"python plain\">{</code><code class=\"python string\">\'required\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'请选择爱好\'</code><code class=\"python plain\">, </code><code class=\"python string\">\'invalid\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'选择爱好格式错误\'</code><code class=\"python plain\">},</code></div><div class=\"line number9 index8 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">widget</code><code class=\"python keyword\">=</code><code class=\"python plain\">MultiSelect(text_value_list</code><code class=\"python keyword\">=</code><code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number10 index9 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number11 index10 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">3</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">, },</code></div><div class=\"line number12 index11 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">4</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">}, ]))</code></div><div class=\"line number13 index12 alt2\"> </div><div class=\"line number14 index13 alt1\"><code class=\"python spaces\"> </code><code class=\"python keyword\">def</code> <code class=\"python plain\">__init__(</code><code class=\"python color1\">self</code><code class=\"python plain\">, </code><code class=\"python keyword\">*</code><code class=\"python plain\">args, </code><code class=\"python keyword\">*</code><code class=\"python keyword\">*</code><code class=\"python plain\">kwargs):</code></div><div class=\"line number15 index14 alt2\"><code class=\"python spaces\"> </code><code class=\"python functions\">super</code><code class=\"python plain\">(DynamicSelectForm, </code><code class=\"python color1\">self</code><code class=\"python plain\">).__init__(</code><code class=\"python keyword\">*</code><code class=\"python plain\">args, </code><code class=\"python keyword\">*</code><code class=\"python keyword\">*</code><code class=\"python plain\">kwargs)</code></div><div class=\"line number16 index15 alt1\"> </div><div class=\"line number17 index16 alt2\"><code class=\"python spaces\"> </code><code class=\"python comments\"># 获取数据库中的最新数据并显示在页面上(每次创建对象都执行一次数据库操作来获取最新数据)</code></div><div class=\"line number18 index17 alt1\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.city.widget.text_value_list </code><code class=\"python keyword\">=</code> <code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'上海\'</code><code class=\"python plain\">},</code></div><div class=\"line number19 index18 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'北京\'</code><code class=\"python plain\">},</code></div><div class=\"line number20 index19 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">3</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'南京\'</code><code class=\"python plain\">},</code></div><div class=\"line number21 index20 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">4</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'广州\'</code><code class=\"python plain\">}]</code></div><div class=\"line number22 index21 alt1\"> </div><div class=\"line number23 index22 alt2\"><code class=\"python spaces\"> </code><code class=\"python color1\">self</code><code class=\"python plain\">.multi_favor.widget.text_value_list </code><code class=\"python keyword\">=</code> <code class=\"python plain\">[{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">1</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'篮球\'</code><code class=\"python plain\">},</code></div><div class=\"line number24 index23 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">2</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'足球\'</code><code class=\"python plain\">},</code></div><div class=\"line number25 index24 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">3</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'乒乓球\'</code><code class=\"python plain\">},</code></div><div class=\"line number26 index25 alt1\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">4</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'羽毛球\'</code><code class=\"python plain\">},</code></div><div class=\"line number27 index26 alt2\"><code class=\"python spaces\"> </code><code class=\"python plain\">{</code><code class=\"python string\">\'value\'</code><code class=\"python plain\">: </code><code class=\"python value\">5</code><code class=\"python plain\">, </code><code class=\"python string\">\'text\'</code><code class=\"python plain\">: </code><code class=\"python string\">\'玻璃球\'</code><code class=\"python plain\">}]</code></div></div></td></tr></tbody></table></div></div>\r\n</div>\r\n<h3>写在最后<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><span style=\"font-size: 13px\">开源组件持续更新中,如您在使用过程中遇到任何问题,请留言,我将尽快回复!!!</span></p>\r\n<p>Tyrion技术交流QQ群:564068039</p>\r\n<p>Tyrion技术交流QQ群:564068039</p>\r\n<p>Tyrion技术交流QQ群:564068039</p>\r\n<p>重要的事情说三遍....</p>\r\n<p>...</p>\r\n<p>......</p>\r\n<p>.........</p>\r\n<p>............</p>\r\n<p>................. </p>\r\n<p> </p>\r\n</div>', '2022-05-06', 0, 0, 0, 1, 2);
INSERT INTO `app01_article` VALUES (5, 'Tyrion中文文档(含示例源码)', 'Tyrion是一个基于Python实现的支持多个WEB框架的Form表单验证组件,其完美的支持Tornado、Django、Flask、Bottle Web框架。Tyrion主要有两大重要动能: 表单验证 生成HTML标签 保留上次提交内容 对于表单验证,告别书写重复的正则表达式对用户提交的数据进行', '<div id=\"cnblogs_post_body\" class=\"blogpost-body blogpost-body-html\">\r\n<p dir=\"ltr\">这几天在知乎看到一个问题“为什么很多IT公司不喜欢进过培训机构的人呢?”</p>\r\n<p dir=\"ltr\">身为老男孩的教学负责人,这样的问题必然会引起我的关注,</p>\r\n<p dir=\"ltr\">花时间看了各路人士的回答,</p>\r\n<p dir=\"ltr\">我了个去,尽是对培训机构排山倒海的谩骂声,</p>\r\n<p dir=\"ltr\">负面评价不胜枚举,</p>\r\n<p dir=\"ltr\"><img src=\"https://yiqixie.com/d/loadimage?id=4251481897854758864\" alt=\"\" width=\"683px;\" height=\"387px;\"></p>\r\n<p> </p>\r\n<p dir=\"ltr\"><img src=\"https://yiqixie.com/d/loadimage?id=-2785345453865525180\" alt=\"\" width=\"663px;\" height=\"185px;\"></p>\r\n<p> </p>\r\n<p dir=\"ltr\"><img src=\"https://yiqixie.com/d/loadimage?id=-2694125429521035577\" alt=\"\" width=\"573px;\" height=\"173px;\"></p>\r\n<p> </p>\r\n<p dir=\"ltr\">看完久久不能释怀,心里堵的慌,</p>\r\n<p dir=\"ltr\">又委屈又气愤又无奈,</p>\r\n<p dir=\"ltr\">委屈的是自己辛苦为之奋斗的事业在别人眼里成了骗人的行当,</p>\r\n<p dir=\"ltr\">气愤的是太多无良同行们为了短期利益把行业做臭了,</p>\r\n<p dir=\"ltr\">无奈的是连少量的认真做事情的人也要跟着背负骂名。</p>\r\n<p dir=\"ltr\">冷静下来后,我想写一篇回答为培训机构正名,但想来想去,</p>\r\n<p dir=\"ltr\">觉得无论我如何辩解还是有人在认真做教育等blablabla类的言辞,</p>\r\n<p dir=\"ltr\">在那些被培训机构出来的学生通过包装假简历坑了的公司面前,</p>\r\n<p dir=\"ltr\">在那些被无良培训机构通过招转(招聘名义转招生)骗了的学生面前,</p>\r\n<p dir=\"ltr\">我的辩解显的毫无意义,</p>\r\n<p dir=\"ltr\">我为培训机构的正名正好把我自己变成了那些无良机构的同谋,</p>\r\n<p dir=\"ltr\">这个行业就是被糟蹋啦,都他妈2018年了,IT培训行业还到处存在着卑劣的坑蒙拐骗,</p>\r\n<p dir=\"ltr\">就应该被唾弃,操。</p>\r\n<p><br><br></p>\r\n<p dir=\"ltr\">讲真,我并不是通过这个问题才得知培训机构名声不好的,</p>\r\n<p dir=\"ltr\">毕竟干这行不是一天两天了,行业中的各种作案手段自是门儿清,</p>\r\n<p dir=\"ltr\">早就知道某行业老大一直大量通过招转招生,</p>\r\n<p dir=\"ltr\">早就知道某知名大机构的每个毕业生出来都包装成2年工作经验,</p>\r\n<p dir=\"ltr\">早就知道某人尽皆知的品牌现在已沦落到连小学没毕业的人都敢招,</p>\r\n<p dir=\"ltr\">只不过之前觉得坚持 做好自己就行了,别家机构这样做下去,口碑越来越差,肯定长久不了。</p>\r\n<p dir=\"ltr\">然而,好几年过去,那些机构依然屹立不倒,且业务有越做越好之势。</p>\r\n<p dir=\"ltr\">究其原因,还是广告打的响+销售人员忽悠能力强吧。</p>\r\n<p dir=\"ltr\">1年给百度1个亿(真的,请自行去看某上市培训机构的财报),就能忽悠到足够多的小白用户。</p>\r\n<p dir=\"ltr\">不管什么人,交钱就招,什么机构这么NB可以在四五个月把一个只有初中学历的人培养成一个合格的程序员呢?但不管,交钱就招,培训机构通过忽悠+过度承诺不设门槛疯狂招人,教学质量又控制不好,导致学生毕业后能力根本达不到企业要求,那怎么办,没关系,大不了毕业时包装简历嘛。</p>\r\n<p dir=\"ltr\">这样的故事上演的多了之后,就出现了连锁反应,</p>\r\n<p dir=\"ltr\">培训机构骗学生——》学生毕业后骗公司——》公司被骗的多了,开始直接过滤掉培训机构毕业的学员——》导致更多学员找不到工作,只能认倒霉,到网上去骂培训机构——》负面消息过多,导致机构招生成本上涨——》只能投更多广告招生,增加成本——》羊毛出在羊身上,导致学费上涨,且教研成本压缩——》导致招不到优秀老师——》导致教学质量下降——》导致毕业生质量更差——》更多的企业不想要培训机构出来的人——》死局。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">没错,这最后会变成一个死局,并且会形成劣币驱逐良币效果。</p>\r\n<p dir=\"ltr\">做为外行的你知道么?现在IT培训行业平均获客成本已经到了3000-6000了!!!</p>\r\n<p dir=\"ltr\">接近平均学费(15000-20000)的3分之一啦。注意这只是获客成本,还不包括招生人员的提成等。</p>\r\n<p dir=\"ltr\">销售费用这么高真的只是因为竞争激烈么?</p>\r\n<p dir=\"ltr\">扯蛋,明明就是因为整个行业都在被那些垃圾无良同行们承担着巨大的信任成本 。</p>\r\n<p dir=\"ltr\">继续这样下去,获客成本涨到1万块是迟早的事,相当于50%的费用全给了百度啊,呵呵。</p>\r\n<p dir=\"ltr\">试问,如果这样,即使想认真做教育的机构,哪还有更多的钱做教学研究?哪还有更多的钱招优秀讲师?</p>\r\n<p dir=\"ltr\">哪还有更多钱提高教学的硬软件环境?等着国家拨款么?呵呵,不可能的,这辈子都不可能的。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">想到这个灰暗的前景,让我感到深深的焦虑。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">其实还有一件事,更让我如鲠在喉,</p>\r\n<p dir=\"ltr\">前些天,因为公司要做新的宣传册,你懂的嘛,毕业生就是我们的产品,</p>\r\n<p dir=\"ltr\">希望找一些老学员给个照片,再写点感言,这样显的多真实+有吸引力。</p>\r\n<p dir=\"ltr\">很自然找到一些平时跟我联系比较多的老学员,结果呢,</p>\r\n<p dir=\"ltr\">有几个学生很为难,不愿意给,说怕泄漏隐私,我说,放心,不会写真名的,只写xx同学,还是不愿意,</p>\r\n<p dir=\"ltr\">最后才说出来,说怕让别人知道自己是培训出来的。</p>\r\n<p dir=\"ltr\"><img src=\"https://yiqixie.com/d/loadimage?id=8893880353408953389\" alt=\"\" width=\"207px;\" height=\"420px;\"><img src=\"https://yiqixie.com/d/loadimage?id=1796369585150491506\" alt=\"\" width=\"248px;\" height=\"415px;\"></p>\r\n<p dir=\"ltr\">上面2个同学,一个在小米,一个在汽车之家。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">我突然间好难过,真的。</p>\r\n<p dir=\"ltr\">难过的不是他们连这点小忙不帮,我难过的是,我们如此含辛茹苦培养出来的好学生,</p>\r\n<p dir=\"ltr\">出去后,竟然不敢跟别人承认自己是培训过的。</p>\r\n<p dir=\"ltr\">我难过的是,我们一起度过的那段艰苦、充实、激情的岁月竟只能埋在他们心里不能对别人讲。</p>\r\n<p dir=\"ltr\">我难过的是,那些努力学习、提升自已,只不过借助培训班让自己成长的更快些的初衷却造就了别人眼中的低人一等。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">这是个多么操蛋又不得不接受的现实呀!唉!</p>\r\n<p><br><br></p>\r\n<p dir=\"ltr\">这些事让我觉得瞬间失去了干这份职业的荣誉感,甚至开始质疑我当初从企业辞职出来做讲师是不是正确的选择?</p>\r\n<p dir=\"ltr\">本来是师者,所以传道受业解惑也,</p>\r\n<p dir=\"ltr\">本来是一直秉承“教育不是灌输,而是点燃火焰”,</p>\r\n<p dir=\"ltr\">本来是一直坚信“优秀的老师教授知识只是基本,还要对学生的人生观价值观产生积极正向的影响”</p>\r\n<p dir=\"ltr\">本来是一直跟带的新老师讲,“真正NB的老师,一定是活成了学生心中想活成的样子。”</p>\r\n<p> </p>\r\n<p dir=\"ltr\">我们的讲师天天如此拼命工作,到头来却发现,所从事的行当竟变成了过街老鼠,人人喊打。</p>\r\n<p dir=\"ltr\"> <img src=\"https://yiqixie.com/d/loadimage?id=4964367708517761191\" alt=\"\" width=\"266px;\" height=\"518px;\"><img src=\"https://yiqixie.com/d/loadimage?id=3871251115654613827\" alt=\"\" width=\"282px;\" height=\"509px;\"></p>\r\n<p dir=\"ltr\">我们的学员如此努力的学习,最后出去找工作竟然要靠隐瞒培训经历+包装简历方能得到面试机会。</p>\r\n<p><br><br><br></p>\r\n<p dir=\"ltr\">最后被逼的,我们也要教给学生如何包装简历,因为不这样,可能连面试机会都拿不到,或者只能接受5千的起薪,即使你的技术水平比那些科班毕业的学的还要好。不好意思,包装2年就可以十几K一个月,不包装就工资5千,只因你是培训出来的,你就处在鄙视链的底层。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">清晰记得上次在毕业班,教他们包装简历,边讲边觉得自己的形象在崩塌,你老男孩的价值观呢?不是说Do the right thing么?这是right thing么?为人师表却教别人如何耍诈,呵呵,真是可笑呀。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">我当然会自我安慰啦,比如对自己说,你可以坚持让学生不包装,你心中是正义了,但代价是学生需要接受比其它机构毕业生低一倍的工资,凭什么呢?凭什么你自己的正义坚持却让学员买单?所以,别自个在那端着了,至少少包装点吧,包装个半年,这样子也不太过分。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">呵呵,于是乎,我们也变成了同谋。</p>\r\n<p> </p>\r\n<p dir=\"ltr\"><strong>”当正义长久得不到伸张,当受害者得不到应有的同情,荒谬也就变成真理。“</strong></p>\r\n<p><br><br></p>\r\n<p dir=\"ltr\">直到去年5月,我去硅谷参加Google的IO大会,认识一个Uber的工程师,聊起我的职业,他说他老婆就是在美国一家培训机构培训了几个月,现在TripAdvisor(相当于国内的大众点评)做开发,并且他自己在Uber的小team里也有2个是培训出来的,发现技术能力还挺强的,我问,你知道他们是培训出来的?他说对呀,面试时直接说了,我问那你们不会区别对待么?他说不会呀,只要具备实际能力,为什么要在意人家是培训出来的呢,本职工作干到半路想转行做IT的人多了去了,这反而是勇敢尝试新事物的表现呀。</p>\r\n<p><br><br></p>\r\n<p dir=\"ltr\">这个事让我思考,明明是帮人改变、提升的好事,在国内怎么就变成这个样子了呢?</p>\r\n<p> </p>\r\n<p dir=\"ltr\">那这个游戏还玩着有什么劲呢?</p>\r\n<p> </p>\r\n<p dir=\"ltr\">难过、愤慨、无奈、想骂人。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">妈的,不能再这样下去了。</p>\r\n<p dir=\"ltr\">要么改变,要么滚蛋,</p>\r\n<p dir=\"ltr\">如果没人要出来做点什么,那我来做。</p>\r\n<p dir=\"ltr\">经过很多天的深思及和小伙伴们的讨论,我们决定在目前老男孩教育的基础上,推出一个新的品牌。</p>\r\n<p dir=\"ltr\">这个品牌要通过行动为培训行业正名,</p>\r\n<p dir=\"ltr\">证明给社会这个行业还是有希望,</p>\r\n<p dir=\"ltr\">证明给无良同行其实不用靠坑蒙拐骗也能招到学生,</p>\r\n<p dir=\"ltr\">证明给学员你们的努力不应该受人质疑,</p>\r\n<p dir=\"ltr\">证明给企业培训出来的学生是可以用的,</p>\r\n<p dir=\"ltr\">证明给自己,我们依然在做一件很崇高伟大的事情。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">这个新品牌,我们给他起了名字,叫“骑士计划”。</p>\r\n<p dir=\"ltr\">“骑士”——骑士(Knight、Cavalier) 是欧洲中世纪时受过正式的军事训练的骑兵,后来演变为一种荣誉称号用于表示一个社会阶层。</p>\r\n<p dir=\"ltr\">在骑士文学中,骑士往往是勇敢、忠诚的象征,</p>\r\n<p dir=\"ltr\">每一位骑士都以骑士精神作为守则,是英雄的化身。</p>\r\n<p><br><br></p>\r\n<p dir=\"ltr\">我们会对入学门槛进行严格的设置,</p>\r\n<p dir=\"ltr\">我们会派出老男孩最牛逼的讲师任教,</p>\r\n<p dir=\"ltr\">我们会对教学过程严格的把控,</p>\r\n<p dir=\"ltr\">总之,一切按我们现在能做到的最高标准来执行。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">我们希望,每个从“骑士计划”毕业的学员,都能在简历上豪不畏惧的写下“骑士计划”,</p>\r\n<p dir=\"ltr\">我们希望,每个从“骑士计划”毕业的学员,除了技术之外,都能收获面对未来生活的自信、坚毅和勇敢。</p>\r\n<p><br><br></p>\r\n<p dir=\"ltr\">当然这件事并不容易,这是一场革命,</p>\r\n<p dir=\"ltr\">一场通过自身进化而推动整体行业变革的革命。</p>\r\n<p dir=\"ltr\">一场把劣币驱逐出这个行业的革命,</p>\r\n<p> </p>\r\n<p dir=\"ltr\">毛主席说:</p>\r\n<p dir=\"ltr\">“革命不是请客吃饭,不是做文章,不是绘画绣花,不能那样雅致,</p>\r\n<p dir=\"ltr\">那样从容不迫,文质彬彬,那样温良恭俭让。</p>\r\n<p dir=\"ltr\">革命是暴动,是一个阶级推翻一个阶级的暴烈的行动。”</p>\r\n<p dir=\"ltr\">我意识到这将会是一场漫长的战役,</p>\r\n<p dir=\"ltr\">即使胜利了也许都不会有任何的勋章,</p>\r\n<p dir=\"ltr\">也不会有任何人为你骄傲。</p>\r\n<p dir=\"ltr\">所以我能做的就是坚持作战,</p>\r\n<p dir=\"ltr\">直到环顾四周,我不再是孤身一人时。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">再见面时,我愿我能以骑士之名,赋予你勇气。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">----------------------</p>\r\n<p dir=\"ltr\">噢 ,这个新品牌,将随老男孩深圳新校区8月首发,符合《骑士计划》标准的第1个课程《Python全栈开发+人工智能》将在8.1号深圳新校区开班,愿你能成为第一批骑士。</p>\r\n<p> </p>\r\n<p dir=\"ltr\">ps, 关于这计划的详情可以查看<a href=\"http://www.oldboyedu.com/Public/lnh/kec/shenzhen_knight/\" target=\"_blank\" rel=\"noopener\">骑士计划详情 </a></p>\r\n<p dir=\"ltr\"><img src=\"https://yiqixie.com/d/loadimage?id=-3714917673426706588\" alt=\"\" width=\"621\" height=\"292\"></p>\r\n<p> </p>\r\n<p> </p>\r\n<p></p>\r\n<p><audio controls=\"controls\" style=\"display: none\"></audio></p>\r\n</div>', '2022-05-06', 2, 0, 1, 2, 3);
INSERT INTO `app01_article` VALUES (6, 'python 面向对象(进阶篇)', '上一篇《Python 面向对象(初级篇)》文章介绍了面向对象基本知识:面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中)对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数面向对..', '<div id=\"cnblogs_post_body\" class=\"blogpost-body cnblogs-markdown\"><a rel=\"nofollow noopener\" name=\"_labelTop\"></a><div id=\"toc\"><a rel=\"nofollow noopener\" class=\"head\" href=\"#cb_post_title_url\">目录</a><ul style=\"margin-left:40px;margin-right:40px;margin-top:5px;\"><li style=\"margin-bottom:5px;\"><a rel=\"nofollow noopener\" href=\"#%E5%A6%82%E4%BD%95%E9%80%9A%E8%BF%87ip%E6%89%BE%E5%88%B0%E5%9C%B0%E5%9D%80\">如何通过 IP 找到地址?</a></li><li style=\"margin-bottom:5px;\"><a rel=\"nofollow noopener\" href=\"#ip%E5%9C%B0%E5%9D%80%E7%9A%84%E9%9A%90%E7%A7%81%E9%97%AE%E9%A2%98\">IP 地址的隐私问题</a></li><li style=\"margin-bottom:5px;\"><a rel=\"nofollow noopener\" href=\"#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\">参考资料</a></li></ul></div>\r\n<p><img src=\"https://shuyi-tech-blog.oss-cn-shenzhen.aliyuncs.com/halo_blog_system_file/16519110498873.jpg\" alt=\"\" loading=\"lazy\" class=\"medium-zoom-image\"></p>\r\n<p>为了进一步规范国内的网络舆论,国家规定了各互联网平台都需要显示 IP 归属地信息。微博、抖音、公众号等多个平台纷纷上线了 IP 归属地功能,这标志着国内言论的进一步规范化。但互联网平台商们是怎么通过 IP 定位到我们所属地区的?这背后的原理是什么?IP 归属地背后又有哪些实际的应用?今天我们就来聊聊 IP 归属地背后的技术原理。</p>\r\n<h2 id=\"如何通过-ip-找到地址\">如何通过 IP 找到地址?<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<p>在我们印象中,我们都知道可以通过 IP 地址找到某个人。但当我们细想一下,我们会发现其实 IP 地址与地理位置并不是直接相关的。那我们到底是如何通过 IP 地址找到地址的呢?答案是:通过自治系统(Autonomous System)。</p>\r\n<p>互联网是由不同网络组成的网络,自治系统是组成 Internet 的大型网络,连接到 Internet 的每台计算机或设备都连接到一个 AS。而每一个自治系统都会有一个编码,我们称之为 ASN。</p>\r\n<p><img src=\"https://shuyi-tech-blog.oss-cn-shenzhen.aliyuncs.com/halo_blog_system_file/16519112009977.jpg\" alt=\"\" loading=\"lazy\" class=\"medium-zoom-image\"></p>\r\n<p>可以认为 AS 类似于一个城镇的邮局。邮件从一个邮局到另一个邮局,直到到达正确的城镇为止,然后该城镇的邮局将在该城镇内传递邮件。每个 AS 都控制一组特定的 IP 地址,就像每个镇的邮局负责将邮件传递到该镇内的所有地址一样。通常,每个 AS 由单个大型组织(例如 Internet 服务提供商(ISP)、大型企业技术公司、大学或政府机构)运营。</p>\r\n<p>到这里,我们可以捋清楚这样一个逻辑关系:<code>IP地址 -> 地址块 -> 自治网络编码(ASN) -> 组织 -> 国家</code>。通过 IP 地址,我们就可以定位到一个大致的地理位置,例如:北京朝阳区、深圳南山区等。例如我现在的 IP 地址就归属于编码为 <code>AS4xxx</code> 这个自治网络,通过这个 ASN 可以知道位置在中国深圳,这个 ASN 编码所属的组织为 <code>中国电信</code>。</p>\r\n<p><img src=\"https://shuyi-tech-blog.oss-cn-shenzhen.aliyuncs.com/halo_blog_system_file/16519084933019.jpg\" alt=\"\" loading=\"lazy\" class=\"medium-zoom-image\"></p>\r\n<p>但是通过 ASN 也只能是找到县级或者区级的地理位置,再细的位置就找不到了。但怎么有些时候同学说:他被查水表了,直接定位到某个单元某一户呢?其实原理也很简单!上面我们说到可以根据 IP 地址定位到 ASN 所属组织,而 ASN 所属组织在进行 IP 地址分配的时候,都是会进行 IP 地址分配记录的。某个 IP 地址分配给了谁,都记录得一清二楚。因此警察叔叔想找你喝茶,那还不是一抓一个准。但要提示一下的是,并不是谁都有那个权限去运营商查询这些数据。所以那些说可以爬着网线找到你的人,基本上可以忽略,都是在吓唬你。只有警察叔叔立案,并且出示相关手续之后才可以进行数据查询。</p>\r\n<h2 id=\"ip-地址的隐私问题\">IP 地址的隐私问题<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<p>那是不是只有运营商才能查到某个人的住址信息呢?在大数据时代的今天,各种互联网应用搜集了大量的数据信息,它们其实也可以根据这些信息,推断出某个人的大致地址位置。例如百度地图会一直用 App SDK 以及网页的方式记录 IP 和地址位置的关联,并允许反向查询,也就是可以根据 IP 地址反向查询到某个位置,这个数据精度可能精确到几百米。</p>\r\n<p>其实不止国内的公司会这么做,其实国外的公司同样也会这么做,就比如 Google 也做了。只是国外对这方面控制得非常严格,因此它们会比较明确地披露所使用的用户隐私数据,并且还提供了对应功能可以让用户关闭。</p>\r\n<p><img src=\"https://shuyi-tech-blog.oss-cn-shenzhen.aliyuncs.com/halo_blog_system_file/16519100570578.jpg\" alt=\"\" loading=\"lazy\" class=\"medium-zoom-image\"></p>\r\n<p>有朋友说了,那我可以用 VPN 改变 IP,那是不是某些 App 就不知道我的精确位置了呀?其实并不是的,因为你的邻居可以出卖了你。某些 App 发现,邻居周围的 WIFI、蓝牙等和你的非常像。而且当某个 WiFi 信号消失时,邻居那边的也同步消失了。那么他们就可以猜测,你隐藏了自己的真实 IP,你的地理位置和邻居的非常近。这就是大数据时代背景下的应用。</p>\r\n<p>因此,当某些设备弹出提示「是否允许扫描本地设备」时,你就要谨慎选择了。如果不是内网 NAS 或者投屏类的,基本上没有必要允许这个操作,这个操作都是在盗取你的个人隐私信息。如果你允许了这个操作,那他就会开始扫描整个局域网的设备信息,然后记录下来。最终,其会将你的 IP 地址、手机 IMEI、WiFi 等信息汇总起来,从而做一些商业化的信息,例如 —— 你在电脑上搜了下房子这个关键词,等会你刷手机抖音就会给你推送房地产广告。</p>\r\n<p><img src=\"https://shuyi-tech-blog.oss-cn-shenzhen.aliyuncs.com/halo_blog_system_file/16519107277276.jpg\" alt=\"连接本地网络设备\" loading=\"lazy\"></p>\r\n<p>说白了,「查找并连接到本地网络上的设备」的使用为跨平台广告提供了方便,而从个人信息保护和隐私保护体验的角度来讲,这种对设备的监控、跟踪可能会给用户带来担忧。</p>\r\n<h2 id=\"参考资料\">参考资料<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<ul>\r\n<li><a href=\"https://www.cloudflare.com/zh-cn/learning/network-layer/what-is-an-autonomous-system/\" target=\"_blank\" rel=\"noopener\">什么是自治系统?| 什么是 ASN? | Cloudflare</a></li>\r\n<li><a href=\"https://www.zhihu.com/question/378858233/answer/1090480642\" target=\"_blank\" rel=\"noopener\">IP 地址能精确到什么地步,如何保护隐私? - Luv Letter的回答 - 知乎</a></li>\r\n<li><a href=\"https://www.zhihu.com/question/378858233/answer/1092144083\" target=\"_blank\" rel=\"noopener\">IP 地址能精确到什么地步,如何保护隐私? - Happy Ennding的回答 - 知乎</a></li>\r\n</ul>\r\n\r\n</div>', '2022-08-01', 2, 0, 3, 2, 3);
INSERT INTO `app01_article` VALUES (7, 'Python 面向对象(初级篇)', '51CTO同步发布地址:http://3060674.blog.51cto.com/3050674/1689163 概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 面向', '<div id=\"cnblogs_post_body\" class=\"blogpost-body cnblogs-markdown\">\r\n<h2 id=\"说一段废话\">说一段废话<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<p>压缩响应数据有什么作用呢?问的好:从用户体验和IT成本两方面回答这个问题:</p>\r\n<ul>\r\n<li>用户体验上</li>\r\n</ul>\r\n<p>网速一定的情况下,传输5MB数据比传输10MB数据的时间快了一半。所以传输数据越小用户加载页面就越快,当然相比较之下体验会更好。</p>\r\n<ul>\r\n<li>IT成本上</li>\r\n</ul>\r\n<p>对这个场景来说的成本主要是带宽成本, 数据不压缩那么传输这些数据相应的带宽肯定更大,对比之下压缩耗费的CPU资源在带宽费用上不值一提。</p>\r\n<p>所以你有什么理由不用压缩呢?</p>\r\n<h2 id=\"背景\">背景<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<p>当然Nginx也提供了gzip的压缩方式可以使用,但是在日常的工作中我发现或多或少在使用上有些问题,有点像:用了但又好像没用的感觉。 这篇就记录一下gzip的使用方式和易错点。</p>\r\n<h2 id=\"指令介绍\">指令介绍<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<h3 id=\"gzip\">gzip<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>gzip指令来自 ngx_http_gzip_module 模块,提供的核心能力就是压缩响应数据。</p>\r\n<p>该模块下提供的指令如下:</p>\r\n<pre highlighted=\"true\"><code class=\"hljs language-bash\">gzip on; <span class=\"hljs-comment\"># 开启gzip</span>\r\ngzip_comp_level 6; <span class=\"hljs-comment\"># 压缩等级:1-9 1:压缩最快/CPU消耗最少/压缩率最低 以次类推</span>\r\ngzip_min_length 1000; <span class=\"hljs-comment\"># 小于此大小的数据不压缩(单位字节/byte);数据来源\"Content-Length\"头</span>\r\ngzip_buffers 32 4k; <span class=\"hljs-comment\"># 压缩响应的缓冲区数量和大小(4K 内存页大小取决于平台)</span>\r\ngzip_proxied any; <span class=\"hljs-comment\"># 对代理的请求是否开启压缩</span>\r\ngzip_types text/plain application/xml application/javascript application/x-javascript text/css application/json; <span class=\"hljs-comment\"># 哪些类型的数据需要被压缩</span>\r\ngzip_disable <span class=\"hljs-string\">\"MSIE [1-5]\\.\"</span>; <span class=\"hljs-comment\"># User-Agent 被正则匹配到的不开启压缩</span>\r\ngzip_vary on; <span class=\"hljs-comment\"># 当gzip对请求生效时会被添加一个响应头 \"Vary: Accept-Encoding\"</span>\r\n</code></pre>\r\n<h4 id=\"tips\">tips:<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h4>\r\n<ol>\r\n<li>gzip 是动态压缩: 每个请求在被响应时都会在gzip逻辑内走一遍</li>\r\n<li>压缩等级不是越高越好: 压缩到一定程度后就会吃力不讨好, 从js的测试来看性价比最高的级别是 5或6</li>\r\n<li>buffer大小设置最好是和平台的内存页保持一致: getconf PAGE_SIZE</li>\r\n<li>gzip_types不要瞎写: 写压缩率大的(css/js/xml/json/ttf), image图片就不要写了,压缩空间太小,又耗CPU</li>\r\n</ol>\r\n<h2 id=\"gzip_static\">gzip_static<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<p>gzip_stati指令来自 ngx_http_gzip_static_module模块,提供的核心能力是静态/预压缩</p>\r\n<p>该模块提供的指令如下:</p>\r\n<pre highlighted=\"true\"><code class=\"hljs language-cmake\">gzip_static <span class=\"hljs-keyword\">on</span>|<span class=\"hljs-keyword\">off</span>|always; <span class=\"hljs-comment\"># always: 不管客户端是否支持压缩我他妈全部给你压缩之后给你</span>\r\n</code></pre>\r\n<h4 id=\"tips-1\">tips:<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h4>\r\n<ol>\r\n<li>可以复用gzip_module中以下的指令:\r\n<ol>\r\n<li>gzip_http_version, gzip_proxied, gzip_disable, gzip_vary</li>\r\n</ol>\r\n</li>\r\n<li>gzip_static是静态压缩:意思是你的服务端需要同时存在源文件和使用gzip压缩后的源文件,这时请求的时候会优先吧压缩文件返回,这样就不用再耗费CPU去动态压缩了。(视情况来用,我们没用)</li>\r\n<li>可以和gzip一同开启,没啥影响,它的优先级高于gzip</li>\r\n</ol>\r\n<h2 id=\"易错点提示\">易错点提示<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<p>在实际的生产环境中架构都比较负载,不像一个单纯的Nginx一样,我配置好了就万事大吉了。</p>\r\n<p>时常会遇到有些网站明明配置了gzip但是展示上看并没有生效,为什么?</p>\r\n<p>此时需要梳理这个请求流程,看看这个请求都经过了哪些地方,比如 你的请求通过三次代理(CDN-->Nginx-->Nginx)那么在其中一层没有配置或者配置错误那么整体的返回数据就是没有被压缩的, 这种情况出现还是比较多的。</p>\r\n\r\n</div>', '2022-05-06', 1, 0, 0, 2, 4);
INSERT INTO `app01_article` VALUES (8, '第五篇:白话tornado源码之褪去模板的外衣', '上一篇《白话tornado源码之请求来了》介绍了客户端请求在tornado框架中的生命周期,其本质就是利用epoll和socket来获取并处理请求。在上一篇的内容中,我们只是给客户端返回了简单的字符串,如:“Hello World”,而在实际开发中,需要使用html文件的内容作为模板,然后将被处理后', '<div id=\"topics\">\r\n <div class=\"post\">\r\n <h1 class=\"postTitle\">\r\n \r\n<a id=\"cb_post_title_url\" class=\"postTitle2 vertical-middle\" href=\"https://www.cnblogs.com/yunmeng-shi/p/16245827.html\">\r\n <span role=\"heading\" aria-level=\"2\">Wireshark抓包分析TCP“三次握手,四次挥手”</span>\r\n \r\n</a><button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button>\r\n\r\n </h1>\r\n <div class=\"clear\"></div>\r\n <div class=\"postBody\">\r\n <div id=\"cnblogs_post_body\" class=\"blogpost-body cnblogs-markdown\">\r\n<h1 id=\"1目的\">1.目的<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h1>\r\n<p>客户端与服务器之间建立TCP/IP连接,我们知道是通过<strong>三次握手,四次挥手</strong>实现的,但是很多地方对这个知识的描述仅限于理论层面,这次我们通过网络抓包的方式来看一下实际的TCP/IP传输过程。</p>\r\n<h1 id=\"2什么是抓包\">2.什么是抓包?<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h1>\r\n<p>网络传输信息是通过层层打包,最终到达客户端物理层,经过网线等设备传输到服务器端后,再进行层层拆包,最后获取信息。而<strong>抓包</strong>的“包”就是这个打包了信息的“包。抓包(packet capture)就是将网络传输发送与接收的数据包进行截获,来进行分析的过程。</p>\r\n<h1 id=\"3如何进行抓包\">3.如何进行抓包?<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h1>\r\n<p>我们可以利用现成的网络抓包软件Wireshark,进行抓包,从而分析TCP/IP传输过程。<br>\r\nWireshark软件下载:<a href=\"https://www.wireshark.org/#download\" target=\"_blank\" rel=\"noopener\">Wireshark软件官网下载</a>,一定要下载下图中的”Windows Installer(64-bit)<br>\r\n<img src=\"https://img2022.cnblogs.com/blog/1734017/202205/1734017-20220508152910087-1879190602.png\" alt=\"image\" loading=\"lazy\" class=\"medium-zoom-image\"></p>\r\n<h1 id=\"4抓包分析tcpip传输过程三次握手\">4.抓包分析TCP/IP传输过程(“三次握手”)<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h1>\r\n<h2 id=\"41第一步浏览器打开网页httpswwwhiteducn-其他的网页也没问题\">4.1第一步:浏览器打开网页https://www.hit.edu.cn/ (其他的网页也没问题)<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<p><img src=\"https://img2022.cnblogs.com/blog/1734017/202205/1734017-20220508160248273-525582716.png\" alt=\"image\" loading=\"lazy\" class=\"medium-zoom-image\"></p>\r\n<h2 id=\"42第二步打开命令行窗口输入ping-wwwtencentcom查看ip地址切记千万不要把httpshttp加进去\">4.2第二步:打开命令行窗口,输入:<code>ping www.tencent.com</code>,查看IP地址(切记:千万不要把https/http加进去)<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<p><img src=\"https://img2022.cnblogs.com/blog/1734017/202205/1734017-20220508160216069-698205633.png\" alt=\"image\" loading=\"lazy\" class=\"medium-zoom-image\"><br>\r\n这里我们得到的IP地址是<code>61.167.60.70</code></p>\r\n<h2 id=\"43第三步打开wireshark软件\">4.3第三步:打开Wireshark软件<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h2>\r\n<h3 id=\"431先双击wlan\">4.3.1先双击“WLAN”<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><img src=\"https://img2022.cnblogs.com/blog/1734017/202205/1734017-20220508154045077-248207805.png\" alt=\"image\" loading=\"lazy\" class=\"medium-zoom-image\"></p>\r\n<h3 id=\"432得到下图\">4.3.2得到下图<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><img src=\"https://img2022.cnblogs.com/blog/1734017/202205/1734017-20220508154212120-455756182.png\" alt=\"image\" loading=\"lazy\" class=\"medium-zoom-image\"></p>\r\n<h3 id=\"433在下图方框位置输入ipaddr611676070按下回车键稍等片刻\">4.3.3在下图方框位置输入:<code>ip.addr==61.167.60.70</code>,按下回车键,稍等片刻<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p>(如果没反应,重新在浏览器输入网址,并重新获取IP地址,也就是重复1,2步操作)<br>\r\n<img src=\"https://img2022.cnblogs.com/blog/1734017/202205/1734017-20220508154519974-46427313.png\" alt=\"image\" loading=\"lazy\" class=\"medium-zoom-image\"></p>\r\n<h3 id=\"434显示如下图所示\">4.3.4显示如下图所示<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h3>\r\n<p><img src=\"https://img2022.cnblogs.com/blog/1734017/202205/1734017-20220508160019223-620055633.png\" alt=\"image\" loading=\"lazy\" class=\"medium-zoom-image\"><br>\r\n<strong>注意!!</strong>:如果第一步访问的是一些比较大的网站,例如腾讯之类的,这步会出不来,因为这些大网站往往有多个主机,你用ping访问到的ip地址和浏览器访问到的ip地址会出现不一致的情况,导致这一步只有ping的包。也就是说建议大家不要选择大网站测试,可以像我这样,用自己学校网址或者一些小的网站测试。</p>\r\n<h1 id=\"5分析三次握手抓包结果\">5.分析“三次握手”抓包结果<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h1>\r\n<p>首先是抓包结果图(把上一步得到的结果划到最上面看)如下:<br>\r\n<img src=\"https://img2022.cnblogs.com/blog/1734017/202205/1734017-20220508161023812-2030578906.png\" alt=\"image\" loading=\"lazy\" class=\"medium-zoom-image\"><br>\r\n方框处也就是“三次握手的结果。</p>\r\n<ul>\r\n<li>第一次的标志是“[SYN]”,序列号seq为0, 代表客户端请求建立连接</li>\r\n<li>第二次的标志是“[SYN, ACK]”,序列号Seq为0,Ack值为客户端发送过来的Seq加1,也就是1,表示服务器可以正常接收客户端数据包。</li>\r\n<li>第三次的标志是“[ACK]”,客户端表示可以正常接收服务器数据包,这是为了保证可以全双工通讯,接下来就可以正常发送数据。</li>\r\n</ul>\r\n<h1 id=\"6四次挥手抓包及分析\">6.“四次挥手”抓包及分析<button class=\"cnblogs-toc-button\" title=\"显示目录导航\" aria-expanded=\"false\"></button></h1>\r\n<p>首先我们需要把浏览器的页面关闭,也就是断开TCP/IP连接,之后等待几分钟。会出现下面的画面,方框就是“挥手”过程。<br>\r\n<img src=\"https://img2022.cnblogs.com/blog/1734017/202205/1734017-20220508164807636-930790898.png\" alt=\"image\" loading=\"lazy\" class=\"medium-zoom-image\"><br>\r\n四次挥手标志分别为:</p>\r\n<ul>\r\n<li>\"[FIN, ACK]\"</li>\r\n<li>\"[ACK]\"</li>\r\n<li>\"[FIN, ACK]\"</li>\r\n<li>\"[ACK]\"</li>\r\n</ul>\r\n<p>这里,我们需要注意两点:<br>\r\n(1)客户端与服务器端传输时全双工的,因此断开请求既可以由客户端发起,也可以由服务器端发起。只要找准第一次出现\"[FIN, ACK]\"的位置,就是第一次挥手位置。<br>\r\n(2)为什么我们抓包抓到的不是“四次挥手”,而是“三次挥手”呢?<br>\r\n这里涉及到LInux的TCP时延机制,当被挥手端(这里是443端口)第一次收到挥手端(这里是12672端口)的“FIN”请求时,并不会立即发送ACK,而是会经过一段延迟时间后再发送,但是此时被挥手端也没有数据发送,就会向挥手端发送“FIN\"请求,这里就可能造成被挥手端发送的“FIN”与“ACK”一起被挥手端收到,导致出现“第二、三次挥手”合并为一次的现象,也就最终呈现出“三次挥手”的情况。</p>\r\n\r\n</div>\r\n<div id=\"MySignature\" role=\"contentinfo\">\r\n <div>作者:<a href=\"http://www.cnblogs.com/yunmeng-shi/\" target=\"_blank\">云梦士</a></div>\r\n<div>出处:<a href=\"http://www.cnblogs.com/yunmeng-shi/\" target=\"_blank\">http://www.cnblogs.com/yunmeng-shi/</a></div>\r\n<div>本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>\r\n</div>\r\n<div class=\"clear\"></div>\r\n<div id=\"blog_post_info_block\" role=\"contentinfo\"><div id=\"BlogPostCategory\">\r\n 分类: \r\n <a href=\"https://www.cnblogs.com/yunmeng-shi/category/2153985.html\" target=\"_blank\">linux开发</a></div>\r\n\r\n\r\n <div id=\"blog_post_info\">\r\n<div id=\"green_channel\">\r\n <a href=\"javascript:void(0);\" id=\"green_channel_digg\" onclick=\"DiggIt(16245827,cb_blogId,1);green_channel_success(this,\'谢谢推荐!\');\">好文要顶</a>\r\n <a id=\"green_channel_follow\" onclick=\"follow(\'b99cd685-b89a-4aa5-e427-08d7006bad27\');\" href=\"javascript:void(0);\">关注我</a>\r\n <a id=\"green_channel_favorite\" onclick=\"AddToWz(cb_entryId);return false;\" href=\"javascript:void(0);\">收藏该文</a>\r\n <a id=\"green_channel_weibo\" href=\"javascript:void(0);\" title=\"分享至新浪微博\" onclick=\"ShareToTsina()\"><img src=\"https://common.cnblogs.com/images/icon_weibo_24.png\" alt=\"\"></a>\r\n <a id=\"green_channel_wechat\" href=\"javascript:void(0);\" title=\"分享至微信\" onclick=\"shareOnWechat()\"><img src=\"https://common.cnblogs.com/images/wechat.png\" alt=\"\"></a>\r\n</div>\r\n<div id=\"author_profile\">\r\n <div id=\"author_profile_info\" class=\"author_profile_info\">\r\n <a href=\"https://home.cnblogs.com/u/yunmeng-shi/\" target=\"_blank\"><img src=\"https://pic.cnblogs.com/face/1734017/20210818220207.png\" class=\"author_avatar\" alt=\"\"></a>\r\n <div id=\"author_profile_detail\" class=\"author_profile_info\">\r\n <a href=\"https://home.cnblogs.com/u/yunmeng-shi/\">云梦士</a><br>\r\n <a href=\"https://home.cnblogs.com/u/yunmeng-shi/followees/\">关注 - 10</a><br>\r\n <a href=\"https://home.cnblogs.com/u/yunmeng-shi/followers/\">粉丝 - 1</a>\r\n </div>\r\n </div>\r\n <div class=\"clear\"></div>\r\n <div id=\"author_profile_honor\"></div>\r\n <div id=\"author_profile_follow\">\r\n <a href=\"javascript:void(0);\" onclick=\"follow(\'b99cd685-b89a-4aa5-e427-08d7006bad27\');return false;\">+加关注</a>\r\n </div>\r\n</div>\r\n<div id=\"div_digg\">\r\n <div class=\"diggit\" onclick=\"votePost(16245827,\'Digg\')\">\r\n <span class=\"diggnum\" id=\"digg_count\">0</span>\r\n </div>\r\n <div class=\"buryit\" onclick=\"votePost(16245827,\'Bury\')\">\r\n <span class=\"burynum\" id=\"bury_count\">0</span>\r\n </div>\r\n <div class=\"clear\"></div>\r\n <div class=\"diggword\" id=\"digg_tips\">\r\n </div>\r\n</div>\r\n\r\n<script type=\"text/javascript\">\r\n currentDiggType = 0;\r\n</script></div>\r\n <div class=\"clear\"></div>\r\n <div id=\"post_next_prev\">\r\n\r\n <a href=\"https://www.cnblogs.com/yunmeng-shi/p/16244241.html\" class=\"p_n_p_prefix\">« </a> 上一篇: <a href=\"https://www.cnblogs.com/yunmeng-shi/p/16244241.html\" data-featured-image=\"\" title=\"发布于 2022-05-07 21:43\">GDB调试小白教程</a>\r\n\r\n</div>\r\n</div>\r\n </div>\r\n <div class=\"postDesc\">posted @ \r\n<span id=\"post-date\">2022-05-08 17:03</span> \r\n<a href=\"https://www.cnblogs.com/yunmeng-shi/\">云梦士</a> \r\n阅读(<span id=\"post_view_count\">42</span>) \r\n评论(<span id=\"post_comment_count\">0</span>) \r\n<a href=\"https://i.cnblogs.com/EditPosts.aspx?postid=16245827\" rel=\"nofollow\">编辑</a> \r\n<a href=\"javascript:void(0)\" onclick=\"AddToWz(16245827);return false;\">收藏</a> \r\n<a href=\"javascript:void(0)\" onclick=\"reportManager.report({ currentUserId: \'\', targetType: \'blogPost\', targetId: \'16245827\', targetLink: \'https://www.cnblogs.com/yunmeng-shi/p/16245827.html\', title: \'Wireshark抓包分析TCP“三次握手,四次挥手”\' })\">举报</a></div>\r\n </div>\r\n \r\n </div>', '2022-05-06', 1, 0, 0, 2, 4);
INSERT INTO `app01_article` VALUES (13, '关联管理器', '<strong><article data-content=\"[{"type":"block","id":"3060-1621846615933","name":"paragraph&quo', '<strong><article data-content=\"[{"type":"block","id":"3060-1621846615933","name":"paragraph","data":{},"nodes":[{"type":"text","id":"p5PQ-1621846617594","leaves":[{"text":"关联管理器(RelatedManager)","marks":[{"type":"fontSize","value":30},{"type":"bold"}]}]}],"state":{}},{"type":"block","id":"eaYF-1650785505310","name":"heading","data":{"level":"h1"},"nodes":[{"type":"text","id":"FYp1-1650785505309","leaves":[{"text":"1、class RelatedManager","marks":[{"type":"bold"},{"type":"fontSize","value":26}]}]}]},{"type":"block","id":"aMkK-1650785505312","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"B2qQ-1650785505311","leaves":[{"text":"\\"关联管理器\\"是在一对多或者多对多的关联上下文中使用的管理器。它存在于下面两种情况:","marks":[]}]}],"state":{}},{"type":"block","id":"c7Cq-1650785505314","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"007X-1650785505313","leaves":[{"text":"ForeignKey关系的“另一边”。像这样:","marks":[]}]}],"state":{}},{"type":"block","id":"QOxL-1650785570724","name":"code","data":{"wrap":false,"language":"","theme":"default"},"nodes":[{"type":"block","id":"Hq01-1650785570718","name":"code-line","data":{},"nodes":[{"type":"text","id":"sMpe-1650785505331","leaves":[{"text":"from django.db import models","marks":[]}]}]},{"type":"block","id":"CpnZ-1650785570719","name":"code-line","data":{},"nodes":[{"type":"text","id":"B9ma-1650785505333","leaves":[{"text":"class Reporter(models.Model):","marks":[]}]}]},{"type":"block","id":"sTOB-1650785570720","name":"code-line","data":{},"nodes":[{"type":"text","id":"Mn6D-1650785505335","leaves":[{"text":"# ...","marks":[]}]}]},{"type":"block","id":"6cJa-1650785570721","name":"code-line","data":{},"nodes":[{"type":"text","id":"Nd41-1650785505337","leaves":[{"text":"pass","marks":[]}]}]},{"type":"block","id":"tJ9E-1650785570722","name":"code-line","data":{},"nodes":[{"type":"text","id":"eVwq-1650785505339","leaves":[{"text":"class Article(models.Model):","marks":[]}]}]},{"type":"block","id":"dZd8-1650785570723","name":"code-line","data":{},"nodes":[{"type":"text","id":"ipAh-1650785505341","leaves":[{"text":"reporter = models.ForeignKey(Reporter)","marks":[]}]}]}],"state":{}},{"type":"block","id":"ieQ3-1650785505345","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"v8qp-1650785505344","leaves":[{"text":"在上面的例子中,管理器reporter.article_set拥有下面的方法。","marks":[]}]}],"state":{}},{"type":"block","id":"QtHD-1650785505347","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"HX0K-1650785505346","leaves":[{"text":"ManyToManyField关系的两边:","marks":[]}]}],"state":{}},{"type":"block","id":"skyr-1650785766844","name":"code","data":{"wrap":false,"language":"","theme":"default"},"nodes":[{"type":"block","id":"q84W-1650785766838","name":"code-line","data":{},"nodes":[{"type":"text","id":"ZTBX-1650785505360","leaves":[{"text":"class Topping(models.Model):","marks":[]}]}]},{"type":"block","id":"ic0j-1650785766839","name":"code-line","data":{},"nodes":[{"type":"text","id":"ppso-1650785505362","leaves":[{"text":"# ...","marks":[]}]}]},{"type":"block","id":"kuBs-1650785766840","name":"code-line","data":{},"nodes":[{"type":"text","id":"DUXW-1650785505364","leaves":[{"text":"pass","marks":[]}]}]},{"type":"block","id":"258y-1650785766841","name":"code-line","data":{},"nodes":[{"type":"text","id":"K0Vb-1650785505366","leaves":[{"text":"class Pizza(models.Model):","marks":[]}]}]},{"type":"block","id":"0BO0-1650785766842","name":"code-line","data":{},"nodes":[{"type":"text","id":"7QQF-1650785505368","leaves":[{"text":"toppings = models.ManyToManyField(Topping)","marks":[]}]}]}],"state":{}},{"type":"block","id":"WjGz-1650785505371","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"s9eM-1650785505370","leaves":[{"text":"这个例子中,topping.pizza_set 和pizza.toppings都拥有下面的方法。","marks":[]}]}],"state":{}},{"type":"block","id":"nEA2-1650785505373","name":"list-item","data":{"listId":"Ie0U-1650785867216","listType":"unordered","listLevel":1},"nodes":[{"type":"text","id":"Y3Fb-1650785505372","leaves":[{"text":"add(obj1[, obj2, ...])","marks":[]}]}],"state":{"index":1}},{"type":"block","id":"HTKa-1650785832070","name":"code","data":{"wrap":false,"language":"","theme":"default"},"nodes":[{"type":"block","id":"qBr9-1650785832060","name":"code-line","data":{},"nodes":[{"type":"text","id":"zCnK-1650785505376","leaves":[{"text":"把指定的模型对象添加到关联对象集中。","marks":[]}]}]},{"type":"block","id":"R2xh-1650785832061","name":"code-line","data":{},"nodes":[{"type":"text","id":"bG8B-1650785505378","leaves":[{"text":"例如:","marks":[]}]}]},{"type":"block","id":"awTY-1650785832062","name":"code-line","data":{},"nodes":[{"type":"text","id":"ZkQ7-1650785505380","leaves":[{"text":"b = Blog.objects.get(id=1)\\ne = Entry.objects.get(id=234)\\nb.entry_set.add(e) # Associates Entry e with Blog b.\\n在上面的例子中,对于ForeignKey关系,e.save()由关联管理器调用,执行更新操作。然而,在多对多关系中使用add()并不会调用任何 save()方法,而是由QuerySet.bulk_create()创建关系。\\n","marks":[]}]}]},{"type":"block","id":"Eul5-1650785849690","name":"code-line","data":{},"nodes":[{"type":"text","id":"Q5kj-1650785849689","leaves":[{"text":"延伸:","marks":[]}]}]},{"type":"block","id":"nvw2-1650785832064","name":"code-line","data":{},"nodes":[{"type":"text","id":"EHut-1650785505385","leaves":[{"text":"1 *[]的使用","marks":[]}]}]},{"type":"block","id":"Y18k-1650785832066","name":"code-line","data":{},"nodes":[{"type":"text","id":"b6n4-1650785505387","leaves":[{"text":"\\n","marks":[]},{"text":"book_obj = Book.objects.get(id=1)\\nauthor_list = Author.objects.filter(id__gt=2)\\nbook_obj.authors.add(*author_list)","marks":[{"type":"color","value":"#403ED6"},{"type":"bold"}]}]}]},{"type":"block","id":"mO1f-1650785835858","name":"code-line","data":{},"nodes":[{"type":"text","id":"7W47-1650785835856","leaves":[{"text":" \\n","marks":[]}]}]},{"type":"block","id":"mqZb-1650785832067","name":"code-line","data":{},"nodes":[{"type":"text","id":"JF3u-1650785505390","leaves":[{"text":"2 直接绑定主键","marks":[]}]}]},{"type":"block","id":"k6BW-1650785832068","name":"code-line","data":{},"nodes":[{"type":"text","id":"XvDW-1650785505392","leaves":[{"text":"book_obj.authors.add(*[1,3]) # 将id=1和id=3的作者对象添加到这本书的作者集合中","marks":[]}]}]},{"type":"block","id":"fFse-1650785832069","name":"code-line","data":{},"nodes":[{"type":"text","id":"Jmi4-1650785505394","leaves":[{"text":"# 应用: 添加或者编辑时,提交作者信息时可以用到.","marks":[]}]}]}],"state":{}},{"type":"block","id":"YVdQ-1650785505399","name":"list-item","data":{"listId":"xGNb-1650785875607","listType":"unordered","listLevel":1},"nodes":[{"type":"text","id":"uMyr-1650785505398","leaves":[{"text":"create(**kwargs)","marks":[]}]}],"state":{"index":1}},{"type":"block","id":"mvlN-1650785915653","name":"code","data":{"wrap":false,"language":"","theme":"default"},"nodes":[{"type":"block","id":"Qjc1-1650785915647","name":"code-line","data":{},"nodes":[{"type":"text","id":"WqXs-1650785505402","leaves":[{"text":"创建一个新的对象,保存对象,并将它添加到关联对象集之中。返回新创建的对象:\\n\\n","marks":[]},{"text":"b = Blog.objects.get(id=1)\\ne = b.entry_set.create(\\n... headline=\" hello\',\\n...=\"\" body_text=\"Hi\" ,\\n...=\"\" pub_date=\"datetime.date(2005,\" 1,=\"\" 1)\\n...=\"\" )\",\"marks\":[{\"type\":\"bold\"},{\"type\":\"color\",\"value\":\"#403ed6\"}]},{\"text\":\"\\n\",\"marks\":[{\"type\":\"bold\"}]},{\"text\":\"\\n\\n\",\"marks\":[]}]}]},{\"type\":\"block\",\"id\":\"m8o5-1650785915649\",\"name\":\"code-line\",\"data\":{},\"nodes\":[{\"type\":\"text\",\"id\":\"fujy-1650785505407\",\"leaves\":[{\"text\":\"no=\"\" need=\"\" to=\"\" call=\"\" e.save()=\"\" at=\"\" this=\"\" point=\"\" --=\"\" it\'s=\"\" already=\"\" been=\"\" saved.\",\"marks\":[]}]}]},{\"type\":\"block\",\"id\":\"bqi6-1650785915650\",\"name\":\"code-line\",\"data\":{},\"nodes\":[{\"type\":\"text\",\"id\":\"rayi-1650785505409\",\"leaves\":[{\"text\":\"这完全等价于(不过更加简洁于):\",\"marks\":[]}]}]},{\"type\":\"block\",\"id\":\"gnml-1650785915652\",\"name\":\"code-line\",\"data\":{},\"nodes\":[{\"type\":\"text\",\"id\":\"ovm8-1650785505412\",\"leaves\":[{\"text\":\"\\n\",\"marks\":[]},{\"text\":\"b=\"Blog.objects.get(id=1)\\ne\" ==\"\" entry(\\n...=\"\" blog=\"b,\\n...\" headline=\"Hello\" )\\ne.save(force_insert=\"True)\\n要注意我们并不需要指定模型中用于定义关系的关键词参数。在上面的例子中,我们并没有传入blog参数给create()。Django会明白新的\" entry对象blog=\"\" 应该添加到b中。\\n复制代码\",\"marks\":[{\"type\":\"color\",\"value\":\"#403ed6\"},{\"type\":\"bold\"}]}]}]}],\"state\":{}},{\"type\":\"block\",\"id\":\"ew89-1650785915654\",\"name\":\"list-item\",\"data\":{\"listid\":\"fyyx-1650785953081\",\"listtype\":\"unordered\",\"listlevel\":1},\"nodes\":[{\"type\":\"text\",\"id\":\"mgji-1650785915655\",\"leaves\":[{\"text\":\"remove(obj1[,=\"\" obj2,=\"\" ...])\",\"marks\":[]}]}],\"state\":{\"index\":1}},{\"type\":\"block\",\"id\":\"pebz-1650785981522\",\"name\":\"code\",\"data\":{\"wrap\":false,\"language\":\"\",\"theme\":\"default\"},\"nodes\":[{\"type\":\"block\",\"id\":\"coo3-1650785981519\",\"name\":\"code-line\",\"data\":{},\"nodes\":[{\"type\":\"text\",\"id\":\"igwn-1650785958472\",\"leaves\":[{\"text\":\"从关联对象集中移除执行的模型对象:\",\"marks\":[]}]}]},{\"type\":\"block\",\"id\":\"8t10-1650785981521\",\"name\":\"code-line\",\"data\":{},\"nodes\":[{\"type\":\"text\",\"id\":\"h5mm-1650785505417\",\"leaves\":[{\"text\":\"\\n\\n\\n\",\"marks\":[]},{\"text\":\"b=\"Blog.objects.get(id=1)\\ne\" entry.objects.get(id=\"234)\\nb.entry_set.remove(e)\" #=\"\" disassociates=\"\" entry=\"\" e=\"\" from=\"\" b.\\n对于foreignkey对象,这个方法仅在null=\"True时存在。\\n","marks":[{"type":"bold"},{"type":"color","value":"#403ED6"}]},{"text":"\\n\\n\\n","marks":[]}]}]}],"state":{}},{"type":"block","id":"zPFd-1650785505421","name":"list-item","data":{"listId":"tCqK-1650785994995","listType":"unordered","listLevel":1},"nodes":[{"type":"text","id":"6fsy-1650785505420","leaves":[{"text":"clear()","marks":[]}]}],"state":{"index":1}},{"type":"block","id":"3LSE-1650786013450","name":"code","data":{"wrap":false,"language":"","theme":"default"},"nodes":[{"type":"block","id":"rCwD-1650786013447","name":"code-line","data":{},"nodes":[{"type":"text","id":"3fak-1650785505422","leaves":[{"text":"从关联对象集中移除一切对象。\\n","marks":[]},{"text":"b\" blog.objects.get(id=\"1)\\nb.entry_set.clear()\\n注意这样不会删除对象\" ——=\"\" 只会删除他们之间的关联\",\"marks\":[{\"type\":\"bold\"},{\"type\":\"color\",\"value\":\"#403ed6\"}]},{\"text\":\"。\\n\",\"marks\":[]}]}]},{\"type\":\"block\",\"id\":\"lmeg-1650786013449\",\"name\":\"code-line\",\"data\":{},\"nodes\":[{\"type\":\"text\",\"id\":\"en9s-1650785505427\",\"leaves\":[{\"text\":\"就像=\"\" remove()=\"\" 方法一样,clear()只能在=\"\" null=\"True的ForeignKey上被调用。","marks":[]}]}]}],"state":{}},{"type":"block","id":"KK7P-1650785505432","name":"list-item","data":{"listId":"q8gt-1650786023990","listType":"unordered","listLevel":1},"nodes":[{"type":"text","id":"pUXj-1650785505431","leaves":[{"text":"set()方法","marks":[]}]}],"state":{"index":1}},{"type":"block","id":"aOf6-1650785505434","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"zcj6-1650785505433","leaves":[{"text":"先清空,在设置,编辑书籍时即可用到","marks":[]}]}],"state":{}},{"type":"block","id":"FSah-1650786034757","name":"image","data":{"version":1,"url":"//note.youdao.com/yws/res/7/WEBRESOURCE346bedad31159dfce2dc1d57c871f6c7","width":784,"height":292},"nodes":[],"state":{}},{"type":"block","id":"FN8V-1650785505436","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"QFD8-1650785505435","leaves":[{"text":"注意","marks":[{"type":"bold"},{"type":"color","value":"#FF0001"}]}]}],"state":{}},{"type":"block","id":"9iuM-1650785505438","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"Hj3X-1650785505437","leaves":[{"text":"对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。","marks":[]}]}],"state":{}},{"type":"block","id":"bMqL-1650785505440","name":"paragraph","data":{"version":1},"nodes":[{"type":"text","id":"eMiw-1650785505439","leaves":[{"text":"直接赋值:","marks":[{"type":"bold"},{"type":"color","value":"#FF0001"}]}]}],"state":{}},{"type":"block","id":"vTUt-1650786064516","name":"code","data":{"wrap":false,"language":"","theme":"default"},"nodes":[{"type":"block","id":"0n0b-1650786064514","name":"code-line","data":{},"nodes":[{"type":"text","id":"5Lg3-1650785505441","leaves":[{"text":"通过赋值一个新的可迭代的对象,关联对象集可以被整体替换掉。\\n\\n","marks":[]},{"text":"new_list\" [obj1,=\"\" obj3]\\ne.related_set=\"new_list\\n如果外键关系满足null=True,关联管理器会在添加new_list中的内容之前,首先调用clear()方法来解除关联集中一切已存在对象的关联。否则,\" new_list中的对象会在已存在的关联的基础上被添加。\\n\",\"marks\":[{\"type\":\"color\",\"value\":\"#403ed6\"},{\"type\":\"bold\"}]}]}]},{\"type\":\"block\",\"id\":\"pw9a-1650786074494\",\"name\":\"code-line\",\"data\":{},\"nodes\":[{\"type\":\"text\",\"id\":\"xvni-1650786074493\",\"leaves\":[{\"text\":\"\\n\",\"marks\":[]}]}]}],\"state\":{}},{\"type\":\"block\",\"id\":\"mgbh-1650785505451\",\"name\":\"paragraph\",\"data\":{\"version\":1},\"nodes\":[{\"type\":\"text\",\"id\":\"6jd7-1650785505450\",\"leaves\":[{\"text\":\"\",\"marks\":[]}]}],\"state\":{}}]\'=\"\">\r\n<div style=\"font-size:14px;\">\r\n <span style=\"font-size:30px;font-weight:bold;\">关联管理器(RelatedManager)</span>\r\n</div>\r\n<div id=\"WqL6-1652368072038\" style=\"font-size:14px;\">\r\n <span style=\"font-weight:bold;font-size:26px;\">1、class RelatedManager</span>\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n \"关联管理器\"是在一对多或者多对多的关联上下文中使用的管理器。它存在于下面两种情况:\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n ForeignKey关系的“另一边”。像这样:\r\n</div>\r\n<div>\r\n from django.db import models\r\nclass Reporter(models.Model):\r\n# ...\r\npass\r\nclass Article(models.Model):\r\nreporter = models.ForeignKey(Reporter)\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n 在上面的例子中,管理器reporter.article_set拥有下面的方法。\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n ManyToManyField关系的两边:\r\n</div>\r\n<div>\r\n class Topping(models.Model):\r\n# ...\r\npass\r\nclass Pizza(models.Model):\r\ntoppings = models.ManyToManyField(Topping)\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n 这个例子中,topping.pizza_set 和pizza.toppings都拥有下面的方法。\r\n</div>\r\n<div>\r\n <ul>\r\n <li style=\"font-size:14px;text-align:left;font-family:"\">\r\n add(obj1[, obj2, ...])\r\n </li>\r\n </ul>\r\n</div>\r\n<div>\r\n 把指定的模型对象添加到关联对象集中。\r\n例如:\r\nb = Blog.objects.get(id=1)\r\ne = Entry.objects.get(id=234)\r\nb.entry_set.add(e) # Associates Entry e with Blog b.\r\n在上面的例子中,对于ForeignKey关系,e.save()由关联管理器调用,执行更新操作。然而,在多对多关系中使用add()并不会调用任何 save()方法,而是由QuerySet.bulk_create()创建关系。\r\n延伸:\r\n1 *[]的使用\r\nbook_obj = Book.objects.get(id=1)\r\nauthor_list = Author.objects.filter(id__gt=2)\r\nbook_obj.authors.add(*author_list)\r\n2 直接绑定主键\r\nbook_obj.authors.add(*[1,3]) # 将id=1和id=3的作者对象添加到这本书的作者集合中\r\n# 应用: 添加或者编辑时,提交作者信息时可以用到.\r\n</div>\r\n<div>\r\n <ul>\r\n <li style=\"font-size:14px;text-align:left;font-family:"\">\r\n create(**kwargs)\r\n </li>\r\n </ul>\r\n</div>\r\n<div>\r\n 创建一个新的对象,保存对象,并将它添加到关联对象集之中。返回新创建的对象:\r\nb = Blog.objects.get(id=1)\r\ne = b.entry_set.create(\r\n... headline=\'Hello\',\r\n... body_text=\'Hi\',\r\n... pub_date=datetime.date(2005, 1, 1)\r\n... )\r\nNo need to call e.save() at this point -- it\'s already been saved.\r\n这完全等价于(不过更加简洁于):\r\nb = Blog.objects.get(id=1)\r\ne = Entry(\r\n... blog=b,\r\n... headline=\'Hello\',\r\n... body_text=\'Hi\',\r\n... pub_date=datetime.date(2005, 1, 1)\r\n... )\r\ne.save(force_insert=True)\r\n要注意我们并不需要指定模型中用于定义关系的关键词参数。在上面的例子中,我们并没有传入blog参数给create()。Django会明白新的 Entry对象blog 应该添加到b中。\r\n复制代码\r\n</div>\r\n<div>\r\n <ul>\r\n <li style=\"font-size:14px;text-align:left;font-family:"\">\r\n remove(obj1[, obj2, ...])\r\n </li>\r\n </ul>\r\n</div>\r\n<div>\r\n 从关联对象集中移除执行的模型对象:\r\nb = Blog.objects.get(id=1)\r\ne = Entry.objects.get(id=234)\r\nb.entry_set.remove(e) # Disassociates Entry e from Blog b.\r\n对于ForeignKey对象,这个方法仅在null=True时存在。\r\n</div>\r\n<div>\r\n <ul>\r\n <li style=\"font-size:14px;text-align:left;font-family:"\">\r\n clear()\r\n </li>\r\n </ul>\r\n</div>\r\n<div>\r\n 从关联对象集中移除一切对象。\r\nb = Blog.objects.get(id=1)\r\nb.entry_set.clear()\r\n注意这样不会删除对象 —— 只会删除他们之间的关联。\r\n就像 remove() 方法一样,clear()只能在 null=True的ForeignKey上被调用。\r\n</div>\r\n<div>\r\n <ul>\r\n <li style=\"font-size:14px;text-align:left;font-family:"\">\r\n set()方法\r\n </li>\r\n </ul>\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n 先清空,在设置,编辑书籍时即可用到\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n <img alt=\"0\" src=\"//note.youdao.com/yws/res/7/WEBRESOURCE346bedad31159dfce2dc1d57c871f6c7\" style=\"width:784px;height:292px;\" /> \r\n</div>\r\n<div style=\"font-size:14px;\">\r\n <span style=\"font-weight:bold;color:#FF0001;\">注意</span>\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n 对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n <span style=\"font-weight:bold;color:#FF0001;\">直接赋值:</span>\r\n</div>\r\n<div>\r\n 通过赋值一个新的可迭代的对象,关联对象集可以被整体替换掉。\r\nnew_list = [obj1, obj2, obj3]\r\ne.related_set = new_list\r\n如果外键关系满足null=True,关联管理器会在添加new_list中的内容之前,首先调用clear()方法来解除关联集中一切已存在对象的关联。否则, new_list中的对象会在已存在的关联的基础上被添加。\r\n</div>\r\n<div style=\"font-size:14px;\">\r\n</div>\r\n</strong>', '2022-05-12', 0, 0, 0, 1, 1);
INSERT INTO `app01_article` VALUES (14, '内容概要', '<strong>\r\n<h1 id=\"内容概要\" style=\"font-size:2.25em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n 内容概要\r\n</h1>\r\n<ul style=\"', '<strong>\r\n<h1 id=\"内容概要\" style=\"font-size:2.25em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n 内容概要\r\n</h1>\r\n<ul style=\"color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "font-size:14px;\">\r\n <li>\r\n 登陆功能\r\n </li>\r\n <li>\r\n bbs首页搭建\r\n <ul>\r\n <li>\r\n 导航条用户功能\r\n </li>\r\n </ul>\r\n </li>\r\n <li>\r\n admin后台管理\r\n </li>\r\n <li>\r\n 首页文章展示\r\n </li>\r\n <li>\r\n 用户头像展示(media配置)\r\n </li>\r\n <li>\r\n 图片防盗链\r\n </li>\r\n</ul>\r\n<h3 id=\"首页搭建\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E9%A6%96%E9%A1%B5%E6%90%AD%E5%BB%BA\"></a>首页搭建\r\n</h3>\r\n<pre><span class=\"hljs-comment\" style=\"color:#6A737D;\"># 1.<span class=\"zh-hans\" style=\"font-family:"\">动态展示用户名称</span></span> {% <span class=\"hljs-keyword\" style=\"color:#D73A49;\">if</span> request.user.is_authenticated %}\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>>{{ request.user.username }}</a></li>\r\n <li <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown\"</span>>\r\n <a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span> <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown-toggle\"</span> data-toggle=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown\"</span> role=<span class=\"hljs-string\" style=\"color:#032F62;\">\"button\"</span> aria-haspopup=<span class=\"hljs-string\" style=\"color:#032F62;\">\"true\"</span> aria-expanded=<span class=\"hljs-string\" style=\"color:#032F62;\">\"false\"</span>><span class=\"zh-hans\" style=\"font-family:"\">更多操作</span> <span <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"caret\"</span>></span></a>\r\n <ul <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown-menu\"</span>>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">修改密码</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">修改头像</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">后台管理</span></a></li>\r\n <li role=<span class=\"hljs-string\" style=\"color:#032F62;\">\"separator\"</span> <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"divider\"</span>></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">退出登陆</span></a></li>\r\n </ul>\r\n </li>\r\n {% <span class=\"hljs-keyword\" style=\"color:#D73A49;\">else</span> %}\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"{% url \'reg\' %}\"</span>><span class=\"zh-hans\" style=\"font-family:"\">注册</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"{% url \'login\' %}\"</span>><span class=\"zh-hans\" style=\"font-family:"\">登陆</span></a></li>\r\n {% endif %}\r\n <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">更多操作</span></span> </pre>\r\n<h3 id=\"admin后台管理\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#admin%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86\"></a>admin后台管理\r\n</h3>\r\n<pre><span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\"\r\ndjango<span class=\"zh-hans\" style=\"font-family:"\">给你提供了一个可视化的界面用来让你方便的对你的模型表</span> <span class=\"zh-hans\" style=\"font-family:"\">进行数据的增删改查操作</span> <span class=\"zh-hans\" style=\"font-family:"\">如果你先想要使用</span>amdin<span class=\"zh-hans\" style=\"font-family:"\">后台管理操作模型表</span> <span class=\"zh-hans\" style=\"font-family:"\">你需要先注册你的模型表告诉</span>admin<span class=\"zh-hans\" style=\"font-family:"\">你需要操作哪些表</span> <span class=\"zh-hans\" style=\"font-family:"\">去你的应用下的</span>admin.py<span class=\"zh-hans\" style=\"font-family:"\">中注册你的模型表</span> from django.contrib import admin\r\n from app01 import models\r\n # Register your models here.\r\n\r\n admin.site.register(models.UserInfo)\r\n admin.site.register(models.Blog)\r\n admin.site.register(models.Category)\r\n admin.site.register(models.Tag)\r\n admin.site.register(models.Article)\r\n admin.site.register(models.Article2Tag)\r\n admin.site.register(models.UpAndDown)\r\n admin.site.register(models.Comment)\r\n\"\"\"</span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># admin<span class=\"zh-hans\" style=\"font-family:"\">会给每一个注册了的模型表自动生成增删改查四条</span>url</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/ <span class=\"zh-hans\" style=\"font-family:"\">查</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/add/ <span class=\"zh-hans\" style=\"font-family:"\">增</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/change/ <span class=\"zh-hans\" style=\"font-family:"\">改</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/delete/ <span class=\"zh-hans\" style=\"font-family:"\">删</span> \r\n \r\nhttp://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/ <span class=\"zh-hans\" style=\"font-family:"\">查</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/add/ <span class=\"zh-hans\" style=\"font-family:"\">增</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/change/ <span class=\"zh-hans\" style=\"font-family:"\">改</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/delete/ <span class=\"zh-hans\" style=\"font-family:"\">删</span> <span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\" <span class=\"zh-hans\" style=\"font-family:"\">关键点就在于</span>urls.py<span class=\"zh-hans\" style=\"font-family:"\">中的第一条自带的</span>url <span class=\"zh-hans\" style=\"font-family:"\">前期我们需要自己手动苦逼的录入数据,自己克服一下</span> \"\"\"</span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 1.<span class=\"zh-hans\" style=\"font-family:"\">数据绑定尤其需要注意的是用户和个人站点不要忘记绑定了</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 2.<span class=\"zh-hans\" style=\"font-family:"\">标签</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 3.<span class=\"zh-hans\" style=\"font-family:"\">标签和文章</span></span> <span class=\"zh-hans\" style=\"font-family:"\">千万不要把别人的文章绑定标签</span> </pre>\r\n<h3 id=\"用户头像展示\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E7%94%A8%E6%88%B7%E5%A4%B4%E5%83%8F%E5%B1%95%E7%A4%BA\"></a>用户头像展示\r\n</h3>\r\n<pre><span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\"\r\n1 <span class=\"zh-hans\" style=\"font-family:"\">网址所使用的静态文件默认放在</span>static<span class=\"zh-hans\" style=\"font-family:"\">文件夹下</span> 2 <span class=\"zh-hans\" style=\"font-family:"\">用户上传的静态文件也应该单独放在某个文件夹下</span> media<span class=\"zh-hans\" style=\"font-family:"\">配置</span> <span class=\"zh-hans\" style=\"font-family:"\">该配置可以让用户上传的所有文件都固定存放在某一个指定的文件夹下</span> # <span class=\"zh-hans\" style=\"font-family:"\">配置用户上传的文件存储位置</span> MEDIA_ROOT = os.path.join(BASE_DIR,\'media\') # <span class=\"zh-hans\" style=\"font-family:"\">文件名</span> <span class=\"zh-hans\" style=\"font-family:"\">随你</span> <span class=\"zh-hans\" style=\"font-family:"\">自己</span> <span class=\"zh-hans\" style=\"font-family:"\">会自动创建多级目录</span> <span class=\"zh-hans\" style=\"font-family:"\">如何开设后端指定文件夹资源</span> <span class=\"zh-hans\" style=\"font-family:"\">首先你需要自己去</span>urls.py<span class=\"zh-hans\" style=\"font-family:"\">书写固定的代码</span> from django.views.static import serve\r\n from BBS14 import settings\r\n \r\n # <span class=\"zh-hans\" style=\"font-family:"\">暴露后端指定文件夹资源</span> url(r\'^media/(?P<path>.*)\',serve,{\'document_root\':settings.MEDIA_ROOT})\r\n \r\n\"\"\"</span> </pre>\r\n<h3 id=\"图片防盗链\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E5%9B%BE%E7%89%87%E9%98%B2%E7%9B%97%E9%93%BE\"></a>图片防盗链\r\n</h3>\r\n<pre><span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">如何避免别的网站直接通过本网站的</span>url<span class=\"zh-hans\" style=\"font-family:"\">访问本网站资源</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">简单的防盗</span></span> <span class=\"zh-hans\" style=\"font-family:"\">我可以做到请求来的时候先看看当前请求是从哪个网站过来的</span> <span class=\"zh-hans\" style=\"font-family:"\">如果是本网站那么正常访问</span> <span class=\"zh-hans\" style=\"font-family:"\">如果是其他网站直接拒绝</span> <span class=\"zh-hans\" style=\"font-family:"\">请求头里面有一个专门记录请求来自于哪个网址的参数</span> Referer: http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/xxx/ <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">如何避免</span></span> <span class=\"hljs-number\" style=\"color:#005CC5;\">1.</span><span class=\"zh-hans\" style=\"font-family:"\">要么修改请求头</span>referer\r\n <span class=\"hljs-number\" style=\"color:#005CC5;\">2.</span><span class=\"zh-hans\" style=\"font-family:"\">直接写爬虫把对方网址的所有资源直接下载到我们自己的服务器上</span></pre>\r\n</strong>', '2022-05-12', 0, 0, 0, 1, 2);
INSERT INTO `app01_article` VALUES (15, '内容概要2', '<strong>\r\n<h1 id=\"内容概要\" style=\"font-size:2.25em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <h1 id=\"内容概要\" style=\"fon', '<strong>\r\n<h1 id=\"内容概要\" style=\"font-size:2.25em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <h1 id=\"内容概要\" style=\"font-size:2.25em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n 内容概要\r\n </h1>\r\n <ul style=\"color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "font-size:14px;\">\r\n <li>\r\n 登陆功能\r\n </li>\r\n <li>\r\n bbs首页搭建\r\n <ul>\r\n <li>\r\n 导航条用户功能\r\n </li>\r\n </ul>\r\n </li>\r\n <li>\r\n admin后台管理\r\n </li>\r\n <li>\r\n 首页文章展示\r\n </li>\r\n <li>\r\n 用户头像展示(media配置)\r\n </li>\r\n <li>\r\n 图片防盗链\r\n </li>\r\n </ul>\r\n <h3 id=\"首页搭建\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E9%A6%96%E9%A1%B5%E6%90%AD%E5%BB%BA\"></a>首页搭建\r\n </h3>\r\n<pre><span class=\"hljs-comment\" style=\"color:#6A737D;\"># 1.<span class=\"zh-hans\" style=\"font-family:"\">动态展示用户名称</span></span> {% <span class=\"hljs-keyword\" style=\"color:#D73A49;\">if</span> request.user.is_authenticated %}\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>>{{ request.user.username }}</a></li>\r\n <li <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown\"</span>>\r\n <a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span> <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown-toggle\"</span> data-toggle=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown\"</span> role=<span class=\"hljs-string\" style=\"color:#032F62;\">\"button\"</span> aria-haspopup=<span class=\"hljs-string\" style=\"color:#032F62;\">\"true\"</span> aria-expanded=<span class=\"hljs-string\" style=\"color:#032F62;\">\"false\"</span>><span class=\"zh-hans\" style=\"font-family:"\">更多操作</span> <span <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"caret\"</span>></span></a>\r\n <ul <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown-menu\"</span>>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">修改密码</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">修改头像</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">后台管理</span></a></li>\r\n <li role=<span class=\"hljs-string\" style=\"color:#032F62;\">\"separator\"</span> <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"divider\"</span>></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">退出登陆</span></a></li>\r\n </ul>\r\n </li>\r\n {% <span class=\"hljs-keyword\" style=\"color:#D73A49;\">else</span> %}\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"{% url \'reg\' %}\"</span>><span class=\"zh-hans\" style=\"font-family:"\">注册</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"{% url \'login\' %}\"</span>><span class=\"zh-hans\" style=\"font-family:"\">登陆</span></a></li>\r\n {% endif %}\r\n <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">更多操作</span></span> </pre>\r\n <h3 id=\"admin后台管理\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#admin%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86\"></a>admin后台管理\r\n </h3>\r\n<pre><span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\"\r\ndjango<span class=\"zh-hans\" style=\"font-family:"\">给你提供了一个可视化的界面用来让你方便的对你的模型表</span> <span class=\"zh-hans\" style=\"font-family:"\">进行数据的增删改查操作</span> <span class=\"zh-hans\" style=\"font-family:"\">如果你先想要使用</span>amdin<span class=\"zh-hans\" style=\"font-family:"\">后台管理操作模型表</span> <span class=\"zh-hans\" style=\"font-family:"\">你需要先注册你的模型表告诉</span>admin<span class=\"zh-hans\" style=\"font-family:"\">你需要操作哪些表</span> <span class=\"zh-hans\" style=\"font-family:"\">去你的应用下的</span>admin.py<span class=\"zh-hans\" style=\"font-family:"\">中注册你的模型表</span> from django.contrib import admin\r\n from app01 import models\r\n # Register your models here.\r\n\r\n admin.site.register(models.UserInfo)\r\n admin.site.register(models.Blog)\r\n admin.site.register(models.Category)\r\n admin.site.register(models.Tag)\r\n admin.site.register(models.Article)\r\n admin.site.register(models.Article2Tag)\r\n admin.site.register(models.UpAndDown)\r\n admin.site.register(models.Comment)\r\n\"\"\"</span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># admin<span class=\"zh-hans\" style=\"font-family:"\">会给每一个注册了的模型表自动生成增删改查四条</span>url</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/ <span class=\"zh-hans\" style=\"font-family:"\">查</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/add/ <span class=\"zh-hans\" style=\"font-family:"\">增</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/change/ <span class=\"zh-hans\" style=\"font-family:"\">改</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/delete/ <span class=\"zh-hans\" style=\"font-family:"\">删</span> \r\n \r\nhttp://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/ <span class=\"zh-hans\" style=\"font-family:"\">查</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/add/ <span class=\"zh-hans\" style=\"font-family:"\">增</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/change/ <span class=\"zh-hans\" style=\"font-family:"\">改</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/delete/ <span class=\"zh-hans\" style=\"font-family:"\">删</span> <span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\" <span class=\"zh-hans\" style=\"font-family:"\">关键点就在于</span>urls.py<span class=\"zh-hans\" style=\"font-family:"\">中的第一条自带的</span>url <span class=\"zh-hans\" style=\"font-family:"\">前期我们需要自己手动苦逼的录入数据,自己克服一下</span> \"\"\"</span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 1.<span class=\"zh-hans\" style=\"font-family:"\">数据绑定尤其需要注意的是用户和个人站点不要忘记绑定了</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 2.<span class=\"zh-hans\" style=\"font-family:"\">标签</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 3.<span class=\"zh-hans\" style=\"font-family:"\">标签和文章</span></span> <span class=\"zh-hans\" style=\"font-family:"\">千万不要把别人的文章绑定标签</span> </pre>\r\n <h3 id=\"用户头像展示\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E7%94%A8%E6%88%B7%E5%A4%B4%E5%83%8F%E5%B1%95%E7%A4%BA\"></a>用户头像展示\r\n </h3>\r\n<pre><span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\"\r\n1 <span class=\"zh-hans\" style=\"font-family:"\">网址所使用的静态文件默认放在</span>static<span class=\"zh-hans\" style=\"font-family:"\">文件夹下</span> 2 <span class=\"zh-hans\" style=\"font-family:"\">用户上传的静态文件也应该单独放在某个文件夹下</span> media<span class=\"zh-hans\" style=\"font-family:"\">配置</span> <span class=\"zh-hans\" style=\"font-family:"\">该配置可以让用户上传的所有文件都固定存放在某一个指定的文件夹下</span> # <span class=\"zh-hans\" style=\"font-family:"\">配置用户上传的文件存储位置</span> MEDIA_ROOT = os.path.join(BASE_DIR,\'media\') # <span class=\"zh-hans\" style=\"font-family:"\">文件名</span> <span class=\"zh-hans\" style=\"font-family:"\">随你</span> <span class=\"zh-hans\" style=\"font-family:"\">自己</span> <span class=\"zh-hans\" style=\"font-family:"\">会自动创建多级目录</span> <span class=\"zh-hans\" style=\"font-family:"\">如何开设后端指定文件夹资源</span> <span class=\"zh-hans\" style=\"font-family:"\">首先你需要自己去</span>urls.py<span class=\"zh-hans\" style=\"font-family:"\">书写固定的代码</span> from django.views.static import serve\r\n from BBS14 import settings\r\n \r\n # <span class=\"zh-hans\" style=\"font-family:"\">暴露后端指定文件夹资源</span> url(r\'^media/(?P<path>.*)\',serve,{\'document_root\':settings.MEDIA_ROOT})\r\n \r\n\"\"\"</span> </pre>\r\n <h3 id=\"图片防盗链\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E5%9B%BE%E7%89%87%E9%98%B2%E7%9B%97%E9%93%BE\"></a>图片防盗链\r\n </h3>\r\n<pre><span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">如何避免别的网站直接通过本网站的</span>url<span class=\"zh-hans\" style=\"font-family:"\">访问本网站资源</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">简单的防盗</span></span> <span class=\"zh-hans\" style=\"font-family:"\">我可以做到请求来的时候先看看当前请求是从哪个网站过来的</span> <span class=\"zh-hans\" style=\"font-family:"\">如果是本网站那么正常访问</span> <span class=\"zh-hans\" style=\"font-family:"\">如果是其他网站直接拒绝</span> <span class=\"zh-hans\" style=\"font-family:"\">请求头里面有一个专门记录请求来自于哪个网址的参数</span> Referer: http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/xxx/ <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">如何避免</span></span> <span class=\"hljs-number\" style=\"color:#005CC5;\">1.</span><span class=\"zh-hans\" style=\"font-family:"\">要么修改请求头</span>referer\r\n <span class=\"hljs-number\" style=\"color:#005CC5;\">2.</span><span class=\"zh-hans\" style=\"font-family:"\">直接写爬虫把对方网址的所有资源直接下载到我们自己的服务器上</span></pre>\r\n<br />\r\n</h1>\r\n</strong>', '2022-05-12', 0, 0, 0, 1, 1);
INSERT INTO `app01_article` VALUES (16, '内容概要3', '<strong>\r\n<h1 id=\"内容概要\" style=\"font-size:2.25em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n 内容概要\r\n</h1>\r\n<ul style=\"', '<strong>\r\n<h1 id=\"内容概要\" style=\"font-size:2.25em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n 内容概要\r\n</h1>\r\n<ul style=\"color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "font-size:14px;\">\r\n <li>\r\n 登陆功能\r\n </li>\r\n <li>\r\n bbs首页搭建\r\n <ul>\r\n <li>\r\n 导航条用户功能\r\n </li>\r\n </ul>\r\n </li>\r\n <li>\r\n admin后台管理\r\n </li>\r\n <li>\r\n 首页文章展示\r\n </li>\r\n <li>\r\n 用户头像展示(media配置)\r\n </li>\r\n <li>\r\n 图片防盗链\r\n </li>\r\n</ul>\r\n<h3 id=\"首页搭建\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E9%A6%96%E9%A1%B5%E6%90%AD%E5%BB%BA\"></a>首页搭建\r\n</h3>\r\n<pre><span class=\"hljs-comment\" style=\"color:#6A737D;\"># 1.<span class=\"zh-hans\" style=\"font-family:"\">动态展示用户名称</span></span> {% <span class=\"hljs-keyword\" style=\"color:#D73A49;\">if</span> request.user.is_authenticated %}\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>>{{ request.user.username }}</a></li>\r\n <li <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown\"</span>>\r\n <a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span> <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown-toggle\"</span> data-toggle=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown\"</span> role=<span class=\"hljs-string\" style=\"color:#032F62;\">\"button\"</span> aria-haspopup=<span class=\"hljs-string\" style=\"color:#032F62;\">\"true\"</span> aria-expanded=<span class=\"hljs-string\" style=\"color:#032F62;\">\"false\"</span>><span class=\"zh-hans\" style=\"font-family:"\">更多操作</span> <span <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"caret\"</span>></span></a>\r\n <ul <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown-menu\"</span>>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">修改密码</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">修改头像</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">后台管理</span></a></li>\r\n <li role=<span class=\"hljs-string\" style=\"color:#032F62;\">\"separator\"</span> <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"divider\"</span>></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">退出登陆</span></a></li>\r\n </ul>\r\n </li>\r\n {% <span class=\"hljs-keyword\" style=\"color:#D73A49;\">else</span> %}\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"{% url \'reg\' %}\"</span>><span class=\"zh-hans\" style=\"font-family:"\">注册</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"{% url \'login\' %}\"</span>><span class=\"zh-hans\" style=\"font-family:"\">登陆</span></a></li>\r\n {% endif %}\r\n <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">更多操作</span></span> </pre>\r\n<h3 id=\"admin后台管理\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#admin%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86\"></a>admin后台管理\r\n</h3>\r\n<pre><span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\"\r\ndjango<span class=\"zh-hans\" style=\"font-family:"\">给你提供了一个可视化的界面用来让你方便的对你的模型表</span> <span class=\"zh-hans\" style=\"font-family:"\">进行数据的增删改查操作</span> <span class=\"zh-hans\" style=\"font-family:"\">如果你先想要使用</span>amdin<span class=\"zh-hans\" style=\"font-family:"\">后台管理操作模型表</span> <span class=\"zh-hans\" style=\"font-family:"\">你需要先注册你的模型表告诉</span>admin<span class=\"zh-hans\" style=\"font-family:"\">你需要操作哪些表</span> <span class=\"zh-hans\" style=\"font-family:"\">去你的应用下的</span>admin.py<span class=\"zh-hans\" style=\"font-family:"\">中注册你的模型表</span> from django.contrib import admin\r\n from app01 import models\r\n # Register your models here.\r\n\r\n admin.site.register(models.UserInfo)\r\n admin.site.register(models.Blog)\r\n admin.site.register(models.Category)\r\n admin.site.register(models.Tag)\r\n admin.site.register(models.Article)\r\n admin.site.register(models.Article2Tag)\r\n admin.site.register(models.UpAndDown)\r\n admin.site.register(models.Comment)\r\n\"\"\"</span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># admin<span class=\"zh-hans\" style=\"font-family:"\">会给每一个注册了的模型表自动生成增删改查四条</span>url</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/ <span class=\"zh-hans\" style=\"font-family:"\">查</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/add/ <span class=\"zh-hans\" style=\"font-family:"\">增</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/change/ <span class=\"zh-hans\" style=\"font-family:"\">改</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/delete/ <span class=\"zh-hans\" style=\"font-family:"\">删</span> \r\n \r\nhttp://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/ <span class=\"zh-hans\" style=\"font-family:"\">查</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/add/ <span class=\"zh-hans\" style=\"font-family:"\">增</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/change/ <span class=\"zh-hans\" style=\"font-family:"\">改</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/delete/ <span class=\"zh-hans\" style=\"font-family:"\">删</span> <span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\" <span class=\"zh-hans\" style=\"font-family:"\">关键点就在于</span>urls.py<span class=\"zh-hans\" style=\"font-family:"\">中的第一条自带的</span>url <span class=\"zh-hans\" style=\"font-family:"\">前期我们需要自己手动苦逼的录入数据,自己克服一下</span> \"\"\"</span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 1.<span class=\"zh-hans\" style=\"font-family:"\">数据绑定尤其需要注意的是用户和个人站点不要忘记绑定了</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 2.<span class=\"zh-hans\" style=\"font-family:"\">标签</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 3.<span class=\"zh-hans\" style=\"font-family:"\">标签和文章</span></span> <span class=\"zh-hans\" style=\"font-family:"\">千万不要把别人的文章绑定标签</span> </pre>\r\n<h3 id=\"用户头像展示\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E7%94%A8%E6%88%B7%E5%A4%B4%E5%83%8F%E5%B1%95%E7%A4%BA\"></a>用户头像展示\r\n</h3>\r\n<pre><span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\"\r\n1 <span class=\"zh-hans\" style=\"font-family:"\">网址所使用的静态文件默认放在</span>static<span class=\"zh-hans\" style=\"font-family:"\">文件夹下</span> 2 <span class=\"zh-hans\" style=\"font-family:"\">用户上传的静态文件也应该单独放在某个文件夹下</span> media<span class=\"zh-hans\" style=\"font-family:"\">配置</span> <span class=\"zh-hans\" style=\"font-family:"\">该配置可以让用户上传的所有文件都固定存放在某一个指定的文件夹下</span> # <span class=\"zh-hans\" style=\"font-family:"\">配置用户上传的文件存储位置</span> MEDIA_ROOT = os.path.join(BASE_DIR,\'media\') # <span class=\"zh-hans\" style=\"font-family:"\">文件名</span> <span class=\"zh-hans\" style=\"font-family:"\">随你</span> <span class=\"zh-hans\" style=\"font-family:"\">自己</span> <span class=\"zh-hans\" style=\"font-family:"\">会自动创建多级目录</span> <span class=\"zh-hans\" style=\"font-family:"\">如何开设后端指定文件夹资源</span> <span class=\"zh-hans\" style=\"font-family:"\">首先你需要自己去</span>urls.py<span class=\"zh-hans\" style=\"font-family:"\">书写固定的代码</span> from django.views.static import serve\r\n from BBS14 import settings\r\n \r\n # <span class=\"zh-hans\" style=\"font-family:"\">暴露后端指定文件夹资源</span> url(r\'^media/(?P<path>.*)\',serve,{\'document_root\':settings.MEDIA_ROOT})\r\n \r\n\"\"\"</span> </pre>\r\n<h3 id=\"图片防盗链\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E5%9B%BE%E7%89%87%E9%98%B2%E7%9B%97%E9%93%BE\"></a>图片防盗链\r\n</h3>\r\n<pre><span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">如何避免别的网站直接通过本网站的</span>url<span class=\"zh-hans\" style=\"font-family:"\">访问本网站资源</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">简单的防盗</span></span> <span class=\"zh-hans\" style=\"font-family:"\">我可以做到请求来的时候先看看当前请求是从哪个网站过来的</span> <span class=\"zh-hans\" style=\"font-family:"\">如果是本网站那么正常访问</span> <span class=\"zh-hans\" style=\"font-family:"\">如果是其他网站直接拒绝</span> <span class=\"zh-hans\" style=\"font-family:"\">请求头里面有一个专门记录请求来自于哪个网址的参数</span> Referer: http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/xxx/ <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">如何避免</span></span> <span class=\"hljs-number\" style=\"color:#005CC5;\">1.</span><span class=\"zh-hans\" style=\"font-family:"\">要么修改请求头</span>referer\r\n <span class=\"hljs-number\" style=\"color:#005CC5;\">2.</span><span class=\"zh-hans\" style=\"font-family:"\">直接写爬虫把对方网址的所有资源直接下载到我们自己的服务器上</span></pre>\r\n</strong>', '2022-05-12', 0, 0, 0, 1, 1);
INSERT INTO `app01_article` VALUES (17, '内容概要4', '<strong>\r\n<h1 id=\"内容概要\" style=\"font-size:2.25em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n 内容概要\r\n</h1>\r\n<ul style=\"', '<strong>\r\n<h1 id=\"内容概要\" style=\"font-size:2.25em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n 内容概要\r\n</h1>\r\n<ul style=\"color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "font-size:14px;\">\r\n <li>\r\n 登陆功能\r\n </li>\r\n <li>\r\n bbs首页搭建\r\n <ul>\r\n <li>\r\n 导航条用户功能\r\n </li>\r\n </ul>\r\n </li>\r\n <li>\r\n admin后台管理\r\n </li>\r\n <li>\r\n 首页文章展示\r\n </li>\r\n <li>\r\n 用户头像展示(media配置)\r\n </li>\r\n <li>\r\n 图片防盗链\r\n </li>\r\n</ul>\r\n<h3 id=\"首页搭建\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E9%A6%96%E9%A1%B5%E6%90%AD%E5%BB%BA\"></a>首页搭建\r\n</h3>\r\n<pre><span class=\"hljs-comment\" style=\"color:#6A737D;\"># 1.<span class=\"zh-hans\" style=\"font-family:"\">动态展示用户名称</span></span> {% <span class=\"hljs-keyword\" style=\"color:#D73A49;\">if</span> request.user.is_authenticated %}\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>>{{ request.user.username }}</a></li>\r\n <li <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown\"</span>>\r\n <a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span> <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown-toggle\"</span> data-toggle=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown\"</span> role=<span class=\"hljs-string\" style=\"color:#032F62;\">\"button\"</span> aria-haspopup=<span class=\"hljs-string\" style=\"color:#032F62;\">\"true\"</span> aria-expanded=<span class=\"hljs-string\" style=\"color:#032F62;\">\"false\"</span>><span class=\"zh-hans\" style=\"font-family:"\">更多操作</span> <span <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"caret\"</span>></span></a>\r\n <ul <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"dropdown-menu\"</span>>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">修改密码</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">修改头像</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">后台管理</span></a></li>\r\n <li role=<span class=\"hljs-string\" style=\"color:#032F62;\">\"separator\"</span> <span class=\"hljs-keyword\" style=\"color:#D73A49;\">class</span>=<span class=\"hljs-string\" style=\"color:#032F62;\">\"divider\"</span>></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"#\"</span>><span class=\"zh-hans\" style=\"font-family:"\">退出登陆</span></a></li>\r\n </ul>\r\n </li>\r\n {% <span class=\"hljs-keyword\" style=\"color:#D73A49;\">else</span> %}\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"{% url \'reg\' %}\"</span>><span class=\"zh-hans\" style=\"font-family:"\">注册</span></a></li>\r\n <li><a href=<span class=\"hljs-string\" style=\"color:#032F62;\">\"{% url \'login\' %}\"</span>><span class=\"zh-hans\" style=\"font-family:"\">登陆</span></a></li>\r\n {% endif %}\r\n <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">更多操作</span></span> </pre>\r\n<h3 id=\"admin后台管理\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#admin%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86\"></a>admin后台管理\r\n</h3>\r\n<pre><span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\"\r\ndjango<span class=\"zh-hans\" style=\"font-family:"\">给你提供了一个可视化的界面用来让你方便的对你的模型表</span> <span class=\"zh-hans\" style=\"font-family:"\">进行数据的增删改查操作</span> <span class=\"zh-hans\" style=\"font-family:"\">如果你先想要使用</span>amdin<span class=\"zh-hans\" style=\"font-family:"\">后台管理操作模型表</span> <span class=\"zh-hans\" style=\"font-family:"\">你需要先注册你的模型表告诉</span>admin<span class=\"zh-hans\" style=\"font-family:"\">你需要操作哪些表</span> <span class=\"zh-hans\" style=\"font-family:"\">去你的应用下的</span>admin.py<span class=\"zh-hans\" style=\"font-family:"\">中注册你的模型表</span> from django.contrib import admin\r\n from app01 import models\r\n # Register your models here.\r\n\r\n admin.site.register(models.UserInfo)\r\n admin.site.register(models.Blog)\r\n admin.site.register(models.Category)\r\n admin.site.register(models.Tag)\r\n admin.site.register(models.Article)\r\n admin.site.register(models.Article2Tag)\r\n admin.site.register(models.UpAndDown)\r\n admin.site.register(models.Comment)\r\n\"\"\"</span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># admin<span class=\"zh-hans\" style=\"font-family:"\">会给每一个注册了的模型表自动生成增删改查四条</span>url</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/ <span class=\"zh-hans\" style=\"font-family:"\">查</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/add/ <span class=\"zh-hans\" style=\"font-family:"\">增</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/change/ <span class=\"zh-hans\" style=\"font-family:"\">改</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/userinfo/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/delete/ <span class=\"zh-hans\" style=\"font-family:"\">删</span> \r\n \r\nhttp://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/ <span class=\"zh-hans\" style=\"font-family:"\">查</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/add/ <span class=\"zh-hans\" style=\"font-family:"\">增</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/change/ <span class=\"zh-hans\" style=\"font-family:"\">改</span> http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/admin/app01/blog/<span class=\"hljs-number\" style=\"color:#005CC5;\">1</span>/delete/ <span class=\"zh-hans\" style=\"font-family:"\">删</span> <span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\" <span class=\"zh-hans\" style=\"font-family:"\">关键点就在于</span>urls.py<span class=\"zh-hans\" style=\"font-family:"\">中的第一条自带的</span>url <span class=\"zh-hans\" style=\"font-family:"\">前期我们需要自己手动苦逼的录入数据,自己克服一下</span> \"\"\"</span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 1.<span class=\"zh-hans\" style=\"font-family:"\">数据绑定尤其需要注意的是用户和个人站点不要忘记绑定了</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 2.<span class=\"zh-hans\" style=\"font-family:"\">标签</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># 3.<span class=\"zh-hans\" style=\"font-family:"\">标签和文章</span></span> <span class=\"zh-hans\" style=\"font-family:"\">千万不要把别人的文章绑定标签</span> </pre>\r\n<h3 id=\"用户头像展示\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E7%94%A8%E6%88%B7%E5%A4%B4%E5%83%8F%E5%B1%95%E7%A4%BA\"></a>用户头像展示\r\n</h3>\r\n<pre><span class=\"hljs-string\" style=\"color:#032F62;\">\"\"\"\r\n1 <span class=\"zh-hans\" style=\"font-family:"\">网址所使用的静态文件默认放在</span>static<span class=\"zh-hans\" style=\"font-family:"\">文件夹下</span> 2 <span class=\"zh-hans\" style=\"font-family:"\">用户上传的静态文件也应该单独放在某个文件夹下</span> media<span class=\"zh-hans\" style=\"font-family:"\">配置</span> <span class=\"zh-hans\" style=\"font-family:"\">该配置可以让用户上传的所有文件都固定存放在某一个指定的文件夹下</span> # <span class=\"zh-hans\" style=\"font-family:"\">配置用户上传的文件存储位置</span> MEDIA_ROOT = os.path.join(BASE_DIR,\'media\') # <span class=\"zh-hans\" style=\"font-family:"\">文件名</span> <span class=\"zh-hans\" style=\"font-family:"\">随你</span> <span class=\"zh-hans\" style=\"font-family:"\">自己</span> <span class=\"zh-hans\" style=\"font-family:"\">会自动创建多级目录</span> <span class=\"zh-hans\" style=\"font-family:"\">如何开设后端指定文件夹资源</span> <span class=\"zh-hans\" style=\"font-family:"\">首先你需要自己去</span>urls.py<span class=\"zh-hans\" style=\"font-family:"\">书写固定的代码</span> from django.views.static import serve\r\n from BBS14 import settings\r\n \r\n # <span class=\"zh-hans\" style=\"font-family:"\">暴露后端指定文件夹资源</span> url(r\'^media/(?P<path>.*)\',serve,{\'document_root\':settings.MEDIA_ROOT})\r\n \r\n\"\"\"</span> </pre>\r\n<h3 id=\"图片防盗链\" style=\"font-size:1.5em;color:#333333;font-family:-apple-system, BlinkMacSystemFont, 微软雅黑, "\">\r\n <a class=\"markdownIt-Anchor\" href=\"http://127.0.0.1:3334/mdEditor/#%E5%9B%BE%E7%89%87%E9%98%B2%E7%9B%97%E9%93%BE\"></a>图片防盗链\r\n</h3>\r\n<pre><span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">如何避免别的网站直接通过本网站的</span>url<span class=\"zh-hans\" style=\"font-family:"\">访问本网站资源</span></span> <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">简单的防盗</span></span> <span class=\"zh-hans\" style=\"font-family:"\">我可以做到请求来的时候先看看当前请求是从哪个网站过来的</span> <span class=\"zh-hans\" style=\"font-family:"\">如果是本网站那么正常访问</span> <span class=\"zh-hans\" style=\"font-family:"\">如果是其他网站直接拒绝</span> <span class=\"zh-hans\" style=\"font-family:"\">请求头里面有一个专门记录请求来自于哪个网址的参数</span> Referer: http://<span class=\"hljs-number\" style=\"color:#005CC5;\">127.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.0</span><span class=\"hljs-number\" style=\"color:#005CC5;\">.1</span>:<span class=\"hljs-number\" style=\"color:#005CC5;\">8000</span>/xxx/ <span class=\"hljs-comment\" style=\"color:#6A737D;\"># <span class=\"zh-hans\" style=\"font-family:"\">如何避免</span></span> <span class=\"hljs-number\" style=\"color:#005CC5;\">1.</span><span class=\"zh-hans\" style=\"font-family:"\">要么修改请求头</span>referer\r\n <span class=\"hljs-number\" style=\"color:#005CC5;\">2.</span><span class=\"zh-hans\" style=\"font-family:"\">直接写爬虫把对方网址的所有资源直接下载到我们自己的服务器上</span></pre>\r\n</strong>', '2022-05-12', 0, 0, 0, 1, 2);
INSERT INTO `app01_article` VALUES (18, 'xss攻击效果', '<pre><span style=\"color:#e8bf6a;\"><script> </span><span style=\"color:#ffc66d;\">alert</span>(<span style=\"color:#6a8759;\">\"你完了\"</span>)<span styl', '<pre><span style=\"color:#e8bf6a;\"><script> </span><span style=\"color:#ffc66d;\">alert</span>(<span style=\"color:#6a8759;\">\"你完了\"</span>)<span style=\"color:#cc7832;\">; </span><span style=\"color:#e8bf6a;\"></script></span></pre>\r\n<br />', '2022-05-12', 0, 0, 0, 1, NULL);
INSERT INTO `app01_article` VALUES (19, 'XSS攻击', '<script> alert(\"你完了\"); </script>', '<script> alert(\"你完了\"); </script>', '2022-05-12', 0, 0, 0, 1, 1);
INSERT INTO `app01_article` VALUES (20, 'XXS再次攻击', '<script>alert(\"hahah\")</script>', '', '2022-05-13', 0, 0, 0, 1, 1);
INSERT INTO `app01_article` VALUES (21, 'XSS攻击再次测试', '<script>alert(\"hahah\")</script>', '', '2022-05-13', 0, 0, 0, 1, 1);
INSERT INTO `app01_article` VALUES (22, '', '永威 你好棒', '<b>永威 你好棒</b>', '2022-06-13', 0, 0, 0, NULL, NULL);
-- ----------------------------
-- Table structure for app01_article2tag
-- ----------------------------
DROP TABLE IF EXISTS `app01_article2tag`;
CREATE TABLE `app01_article2tag` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`article_id` bigint(20) NOT NULL,
`tag_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `app01_article2tag_article_id_35c1561c_fk_app01_article_id`(`article_id`) USING BTREE,
INDEX `app01_article2tag_tag_id_d24dfcf8_fk_app01_tag_id`(`tag_id`) USING BTREE,
CONSTRAINT `app01_article2tag_article_id_35c1561c_fk_app01_article_id` FOREIGN KEY (`article_id`) REFERENCES `app01_article` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `app01_article2tag_tag_id_d24dfcf8_fk_app01_tag_id` FOREIGN KEY (`tag_id`) REFERENCES `app01_tag` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_article2tag
-- ----------------------------
INSERT INTO `app01_article2tag` VALUES (1, 1, 1);
INSERT INTO `app01_article2tag` VALUES (2, 2, 1);
INSERT INTO `app01_article2tag` VALUES (3, 3, 2);
INSERT INTO `app01_article2tag` VALUES (4, 4, 2);
INSERT INTO `app01_article2tag` VALUES (5, 5, 3);
INSERT INTO `app01_article2tag` VALUES (6, 6, 3);
INSERT INTO `app01_article2tag` VALUES (7, 7, 4);
INSERT INTO `app01_article2tag` VALUES (8, 8, 4);
INSERT INTO `app01_article2tag` VALUES (9, 13, 1);
INSERT INTO `app01_article2tag` VALUES (10, 13, 2);
INSERT INTO `app01_article2tag` VALUES (11, 14, 2);
INSERT INTO `app01_article2tag` VALUES (12, 14, 6);
INSERT INTO `app01_article2tag` VALUES (13, 15, 1);
INSERT INTO `app01_article2tag` VALUES (14, 16, 1);
INSERT INTO `app01_article2tag` VALUES (15, 17, 1);
INSERT INTO `app01_article2tag` VALUES (16, 17, 2);
INSERT INTO `app01_article2tag` VALUES (17, 19, 1);
INSERT INTO `app01_article2tag` VALUES (18, 20, 1);
INSERT INTO `app01_article2tag` VALUES (19, 21, 1);
-- ----------------------------
-- Table structure for app01_blog
-- ----------------------------
DROP TABLE IF EXISTS `app01_blog`;
CREATE TABLE `app01_blog` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`stie_name` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
`site_title` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
`site_theme` varchar(64) CHARACTER SET utf8mb4 NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_blog
-- ----------------------------
INSERT INTO `app01_blog` VALUES (1, 'jason', '技多不压身', 'jason.css');
INSERT INTO `app01_blog` VALUES (2, 'tank', '喝茶', 'tank.csa');
-- ----------------------------
-- Table structure for app01_category
-- ----------------------------
DROP TABLE IF EXISTS `app01_category`;
CREATE TABLE `app01_category` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
`blog_id` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `app01_category_blog_id_5f26cf92_fk_app01_blog_id`(`blog_id`) USING BTREE,
CONSTRAINT `app01_category_blog_id_5f26cf92_fk_app01_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `app01_blog` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_category
-- ----------------------------
INSERT INTO `app01_category` VALUES (1, 'jason的分类1', 1);
INSERT INTO `app01_category` VALUES (2, 'Jason的分类3', 1);
INSERT INTO `app01_category` VALUES (3, 'tank的分类1', 2);
INSERT INTO `app01_category` VALUES (4, 'tank的分类2', 2);
INSERT INTO `app01_category` VALUES (5, 'tank的分类3', 2);
-- ----------------------------
-- Table structure for app01_comment
-- ----------------------------
DROP TABLE IF EXISTS `app01_comment`;
CREATE TABLE `app01_comment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`content` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
`comment_time` datetime(6) NOT NULL,
`article_id` bigint(20) NOT NULL,
`parent_id` bigint(20) NULL DEFAULT NULL,
`user_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `app01_comment_article_id_2bf4f73b_fk_app01_article_id`(`article_id`) USING BTREE,
INDEX `app01_comment_parent_id_a8e69cb8_fk_app01_comment_id`(`parent_id`) USING BTREE,
INDEX `app01_comment_user_id_7f913f03_fk_app01_userinfo_id`(`user_id`) USING BTREE,
CONSTRAINT `app01_comment_article_id_2bf4f73b_fk_app01_article_id` FOREIGN KEY (`article_id`) REFERENCES `app01_article` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `app01_comment_parent_id_a8e69cb8_fk_app01_comment_id` FOREIGN KEY (`parent_id`) REFERENCES `app01_comment` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `app01_comment_user_id_7f913f03_fk_app01_userinfo_id` FOREIGN KEY (`user_id`) REFERENCES `app01_userinfo` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 37 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_comment
-- ----------------------------
INSERT INTO `app01_comment` VALUES (1, '太酷了!!!', '2022-05-08 14:00:08.209278', 1, NULL, 17);
INSERT INTO `app01_comment` VALUES (2, '太酷了!!!', '2022-05-08 14:00:27.296062', 1, NULL, 17);
INSERT INTO `app01_comment` VALUES (3, '6666太会写了', '2022-05-08 14:33:10.255030', 1, NULL, 17);
INSERT INTO `app01_comment` VALUES (4, '今天天气不错!!!', '2022-05-08 14:53:32.188081', 1, NULL, 17);
INSERT INTO `app01_comment` VALUES (5, '高兴点', '2022-05-08 14:54:44.729733', 1, NULL, 16);
INSERT INTO `app01_comment` VALUES (7, '@admin\n确实不错!!', '2022-05-08 14:58:42.670612', 1, 4, 16);
INSERT INTO `app01_comment` VALUES (9, '牛逼\n', '2022-05-08 15:07:40.719106', 1, 2, 16);
INSERT INTO `app01_comment` VALUES (10, '我是更评论给', '2022-05-08 15:08:32.472024', 1, NULL, 16);
INSERT INTO `app01_comment` VALUES (11, '我也是根评论', '2022-05-08 15:09:01.682437', 1, NULL, 16);
INSERT INTO `app01_comment` VALUES (14, '太牛了', '2022-05-08 15:15:18.065519', 1, 2, 16);
INSERT INTO `app01_comment` VALUES (35, '6666', '2022-05-10 10:07:00.680221', 2, NULL, 16);
INSERT INTO `app01_comment` VALUES (36, '222', '2022-05-10 10:07:10.128029', 2, NULL, 16);
INSERT INTO `app01_comment` VALUES (37, '555', '2022-05-10 10:07:15.049660', 2, 35, 16);
-- ----------------------------
-- Table structure for app01_tag
-- ----------------------------
DROP TABLE IF EXISTS `app01_tag`;
CREATE TABLE `app01_tag` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
`blog_id` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `app01_tag_blog_id_ce05dc18_fk_app01_blog_id`(`blog_id`) USING BTREE,
CONSTRAINT `app01_tag_blog_id_ce05dc18_fk_app01_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `app01_blog` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_tag
-- ----------------------------
INSERT INTO `app01_tag` VALUES (1, 'jason的标签1', 1);
INSERT INTO `app01_tag` VALUES (2, 'jason的标签2', 1);
INSERT INTO `app01_tag` VALUES (3, 'tank的标签1', 2);
INSERT INTO `app01_tag` VALUES (4, 'tank的标签2', 2);
INSERT INTO `app01_tag` VALUES (5, 'tank的标签3', 2);
INSERT INTO `app01_tag` VALUES (6, 'jason的标签3', 1);
-- ----------------------------
-- Table structure for app01_upanddown
-- ----------------------------
DROP TABLE IF EXISTS `app01_upanddown`;
CREATE TABLE `app01_upanddown` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`is_up` tinyint(1) NOT NULL,
`article_id` bigint(20) NOT NULL,
`user_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `app01_upanddown_article_id_5a7b1add_fk_app01_article_id`(`article_id`) USING BTREE,
INDEX `app01_upanddown_user_id_cdb8debc_fk_app01_userinfo_id`(`user_id`) USING BTREE,
CONSTRAINT `app01_upanddown_article_id_5a7b1add_fk_app01_article_id` FOREIGN KEY (`article_id`) REFERENCES `app01_article` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `app01_upanddown_user_id_cdb8debc_fk_app01_userinfo_id` FOREIGN KEY (`user_id`) REFERENCES `app01_userinfo` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_upanddown
-- ----------------------------
INSERT INTO `app01_upanddown` VALUES (1, 1, 1, 16);
INSERT INTO `app01_upanddown` VALUES (2, 1, 5, 17);
INSERT INTO `app01_upanddown` VALUES (3, 1, 7, 17);
INSERT INTO `app01_upanddown` VALUES (4, 1, 6, 17);
INSERT INTO `app01_upanddown` VALUES (5, 1, 8, 17);
INSERT INTO `app01_upanddown` VALUES (6, 1, 6, 16);
INSERT INTO `app01_upanddown` VALUES (7, 1, 5, 21);
INSERT INTO `app01_upanddown` VALUES (8, 1, 1, 20);
-- ----------------------------
-- Table structure for app01_userinfo
-- ----------------------------
DROP TABLE IF EXISTS `app01_userinfo`;
CREATE TABLE `app01_userinfo` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`password` varchar(128) CHARACTER SET utf8mb4 NOT NULL,
`last_login` datetime(6) NULL DEFAULT NULL,
`is_superuser` tinyint(1) NOT NULL,
`username` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
`first_name` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
`last_name` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
`email` varchar(254) CHARACTER SET utf8mb4 NOT NULL,
`is_staff` tinyint(1) NOT NULL,
`is_active` tinyint(1) NOT NULL,
`date_joined` datetime(6) NOT NULL,
`phone` bigint(20) NULL DEFAULT NULL,
`avatar` varchar(100) CHARACTER SET utf8mb4 NOT NULL,
`create_time` date NOT NULL,
`blog_id` bigint(20) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `username`(`username`) USING BTREE,
UNIQUE INDEX `blog_id`(`blog_id`) USING BTREE,
CONSTRAINT `app01_userinfo_blog_id_12858ea2_fk_app01_blog_id` FOREIGN KEY (`blog_id`) REFERENCES `app01_blog` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 23 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_userinfo
-- ----------------------------
INSERT INTO `app01_userinfo` VALUES (16, 'pbkdf2_sha256$320000$CZOv2wzTk34wqWwpnuRqSg$8Wbnx6kgxjuTIXKiV7Tl0YEc2OJABUGavIeWWEkV9g8=', '2022-05-10 08:56:05.108465', 1, 'admin', '', '', '', 1, 1, '2022-05-06 03:12:43.479623', NULL, 'avatar/default.png', '2022-05-06', NULL);
INSERT INTO `app01_userinfo` VALUES (17, 'pbkdf2_sha256$320000$9zZbJaFtPlUdrEAVhfUwlo$TAIFCOXd40pV6x3+3UourHIiGvb5PNNqFnhpHP2crKs=', '2022-06-13 06:21:06.346569', 0, 'jason', '', '', '123@qq.com', 0, 1, '2022-05-06 05:32:18.000000', NULL, 'avatar/222_fhtgC3O.jpg', '2022-05-06', 1);
INSERT INTO `app01_userinfo` VALUES (18, 'pbkdf2_sha256$320000$CvKM8ksPSaNnXIun19gzCm$1qxUfqnMEP+d0QrQCMu81kMdFLOeeW37wtRniLp/ZHs=', NULL, 0, 'tank', '', '', '123@qq.com', 0, 1, '2022-05-06 05:32:31.000000', NULL, 'avatar/111_1F45S3j.jpg', '2022-05-06', 2);
INSERT INTO `app01_userinfo` VALUES (19, 'pbkdf2_sha256$320000$aqpuDdNlcOUllxBoTCvSeg$OOvFNkahKFkEX5mqCowRy+gGNEFKn8MbXycbpvh9RCU=', NULL, 0, 'xccc', '', '', '123@qq.com', 0, 1, '2022-05-06 06:19:26.882793', NULL, 'avatar/111.jpg', '2022-05-06', NULL);
INSERT INTO `app01_userinfo` VALUES (20, 'pbkdf2_sha256$320000$tKqnEmKPCEmFVh9ytwc6wW$VuhUfnNMHekE5TkvIZzrycdG1nO+4KhfjC+aG1lOWBw=', '2022-06-13 06:19:47.033871', 0, 'hack', '', '', '123@qq.com', 0, 1, '2022-05-07 08:36:29.629182', NULL, 'avatar/wyp__mEzPGe2.jpg', '2022-05-07', NULL);
INSERT INTO `app01_userinfo` VALUES (21, 'pbkdf2_sha256$320000$ov396LU9hxCpI1VRxr7VRC$q/aYI2Bbhk8mjpXH8FLaEm15OYAtDrDoijJZjZppThI=', '2022-05-09 12:38:51.987329', 0, 'www', '', '', '123@qq.com', 0, 1, '2022-05-09 12:38:25.305028', NULL, 'avatar/222_JzZ5soA.jpg', '2022-05-09', NULL);
INSERT INTO `app01_userinfo` VALUES (22, 'pbkdf2_sha256$320000$gsqg7G634MrBRurhqzLNo0$Nh/t+ni3lM2msQbqfTuv3hZ7e5WSzhVV7OVLlU7Swzo=', '2022-06-13 07:29:45.616978', 0, 'qwe', '', '', '123@qq.com', 0, 1, '2022-06-13 07:27:30.429578', NULL, 'avatar/222_eNfSlnY.jpg', '2022-06-13', NULL);
INSERT INTO `app01_userinfo` VALUES (23, 'pbkdf2_sha256$320000$mmkwvnjS3dyNulQhNbWtsM$JL4/rEmxBWjTUj+ZPqcSL6GdLGlu+zv+1hsCWf34OFw=', '2022-06-13 07:56:07.912365', 0, 'yw123', '', '', '123@qq.com', 0, 1, '2022-06-13 07:55:50.075004', NULL, 'avatar/111_9NgKd5s.jpg', '2022-06-13', NULL);
-- ----------------------------
-- Table structure for app01_userinfo_groups
-- ----------------------------
DROP TABLE IF EXISTS `app01_userinfo_groups`;
CREATE TABLE `app01_userinfo_groups` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`userinfo_id` bigint(20) NOT NULL,
`group_id` int(11) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `app01_userinfo_groups_userinfo_id_group_id_48ba2aa6_uniq`(`userinfo_id`, `group_id`) USING BTREE,
INDEX `app01_userinfo_groups_group_id_30b9b2c4_fk_auth_group_id`(`group_id`) USING BTREE,
CONSTRAINT `app01_userinfo_groups_group_id_30b9b2c4_fk_auth_group_id` FOREIGN KEY (`group_id`) REFERENCES `auth_group` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `app01_userinfo_groups_userinfo_id_04be482a_fk_app01_userinfo_id` FOREIGN KEY (`userinfo_id`) REFERENCES `app01_userinfo` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_userinfo_groups
-- ----------------------------
-- ----------------------------
-- Table structure for app01_userinfo_user_permissions
-- ----------------------------
DROP TABLE IF EXISTS `app01_userinfo_user_permissions`;
CREATE TABLE `app01_userinfo_user_permissions` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`userinfo_id` bigint(20) NOT NULL,
`permission_id` int(11) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `app01_userinfo_user_perm_userinfo_id_permission_i_8bd06903_uniq`(`userinfo_id`, `permission_id`) USING BTREE,
INDEX `app01_userinfo_user__permission_id_826033c9_fk_auth_perm`(`permission_id`) USING BTREE,
CONSTRAINT `app01_userinfo_user__permission_id_826033c9_fk_auth_perm` FOREIGN KEY (`permission_id`) REFERENCES `auth_permission` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `app01_userinfo_user__userinfo_id_3a67a872_fk_app01_use` FOREIGN KEY (`userinfo_id`) REFERENCES `app01_userinfo` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of app01_userinfo_user_permissions
-- ----------------------------
-- ----------------------------
-- Table structure for auth_group
-- ----------------------------
DROP TABLE IF EXISTS `auth_group`;
CREATE TABLE `auth_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `name`(`name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of auth_group
-- ----------------------------
-- ----------------------------
-- Table structure for auth_group_permissions
-- ----------------------------
DROP TABLE IF EXISTS `auth_group_permissions`;
CREATE TABLE `auth_group_permissions` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`group_id` int(11) NOT NULL,
`permission_id` int(11) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `auth_group_permissions_group_id_permission_id_0cd325b0_uniq`(`group_id`, `permission_id`) USING BTREE,
INDEX `auth_group_permissio_permission_id_84c5c92e_fk_auth_perm`(`permission_id`) USING BTREE,
CONSTRAINT `auth_group_permissio_permission_id_84c5c92e_fk_auth_perm` FOREIGN KEY (`permission_id`) REFERENCES `auth_permission` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `auth_group_permissions_group_id_b120cbf9_fk_auth_group_id` FOREIGN KEY (`group_id`) REFERENCES `auth_group` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of auth_group_permissions
-- ----------------------------
-- ----------------------------
-- Table structure for auth_permission
-- ----------------------------
DROP TABLE IF EXISTS `auth_permission`;
CREATE TABLE `auth_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
`content_type_id` int(11) NOT NULL,
`codename` varchar(100) CHARACTER SET utf8mb4 NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `auth_permission_content_type_id_codename_01ab375a_uniq`(`content_type_id`, `codename`) USING BTREE,
CONSTRAINT `auth_permission_content_type_id_2f476e4b_fk_django_co` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 52 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of auth_permission
-- ----------------------------
INSERT INTO `auth_permission` VALUES (1, 'Can add log entry', 1, 'add_logentry');
INSERT INTO `auth_permission` VALUES (2, 'Can change log entry', 1, 'change_logentry');
INSERT INTO `auth_permission` VALUES (3, 'Can delete log entry', 1, 'delete_logentry');
INSERT INTO `auth_permission` VALUES (4, 'Can view log entry', 1, 'view_logentry');
INSERT INTO `auth_permission` VALUES (5, 'Can add permission', 2, 'add_permission');
INSERT INTO `auth_permission` VALUES (6, 'Can change permission', 2, 'change_permission');
INSERT INTO `auth_permission` VALUES (7, 'Can delete permission', 2, 'delete_permission');
INSERT INTO `auth_permission` VALUES (8, 'Can view permission', 2, 'view_permission');
INSERT INTO `auth_permission` VALUES (9, 'Can add group', 3, 'add_group');
INSERT INTO `auth_permission` VALUES (10, 'Can change group', 3, 'change_group');
INSERT INTO `auth_permission` VALUES (11, 'Can delete group', 3, 'delete_group');
INSERT INTO `auth_permission` VALUES (12, 'Can view group', 3, 'view_group');
INSERT INTO `auth_permission` VALUES (13, 'Can add content type', 4, 'add_contenttype');
INSERT INTO `auth_permission` VALUES (14, 'Can change content type', 4, 'change_contenttype');
INSERT INTO `auth_permission` VALUES (15, 'Can delete content type', 4, 'delete_contenttype');
INSERT INTO `auth_permission` VALUES (16, 'Can view content type', 4, 'view_contenttype');
INSERT INTO `auth_permission` VALUES (17, 'Can add session', 5, 'add_session');
INSERT INTO `auth_permission` VALUES (18, 'Can change session', 5, 'change_session');
INSERT INTO `auth_permission` VALUES (19, 'Can delete session', 5, 'delete_session');
INSERT INTO `auth_permission` VALUES (20, 'Can view session', 5, 'view_session');
INSERT INTO `auth_permission` VALUES (21, 'Can add user', 6, 'add_userinfo');
INSERT INTO `auth_permission` VALUES (22, 'Can change user', 6, 'change_userinfo');
INSERT INTO `auth_permission` VALUES (23, 'Can delete user', 6, 'delete_userinfo');
INSERT INTO `auth_permission` VALUES (24, 'Can view user', 6, 'view_userinfo');
INSERT INTO `auth_permission` VALUES (25, 'Can add article', 7, 'add_article');
INSERT INTO `auth_permission` VALUES (26, 'Can change article', 7, 'change_article');
INSERT INTO `auth_permission` VALUES (27, 'Can delete article', 7, 'delete_article');
INSERT INTO `auth_permission` VALUES (28, 'Can view article', 7, 'view_article');
INSERT INTO `auth_permission` VALUES (29, 'Can add blog', 8, 'add_blog');
INSERT INTO `auth_permission` VALUES (30, 'Can change blog', 8, 'change_blog');
INSERT INTO `auth_permission` VALUES (31, 'Can delete blog', 8, 'delete_blog');
INSERT INTO `auth_permission` VALUES (32, 'Can view blog', 8, 'view_blog');
INSERT INTO `auth_permission` VALUES (33, 'Can add up and down', 9, 'add_upanddown');
INSERT INTO `auth_permission` VALUES (34, 'Can change up and down', 9, 'change_upanddown');
INSERT INTO `auth_permission` VALUES (35, 'Can delete up and down', 9, 'delete_upanddown');
INSERT INTO `auth_permission` VALUES (36, 'Can view up and down', 9, 'view_upanddown');
INSERT INTO `auth_permission` VALUES (37, 'Can add tag', 10, 'add_tag');
INSERT INTO `auth_permission` VALUES (38, 'Can change tag', 10, 'change_tag');
INSERT INTO `auth_permission` VALUES (39, 'Can delete tag', 10, 'delete_tag');
INSERT INTO `auth_permission` VALUES (40, 'Can view tag', 10, 'view_tag');
INSERT INTO `auth_permission` VALUES (41, 'Can add comment', 11, 'add_comment');
INSERT INTO `auth_permission` VALUES (42, 'Can change comment', 11, 'change_comment');
INSERT INTO `auth_permission` VALUES (43, 'Can delete comment', 11, 'delete_comment');
INSERT INTO `auth_permission` VALUES (44, 'Can view comment', 11, 'view_comment');
INSERT INTO `auth_permission` VALUES (45, 'Can add category', 12, 'add_category');
INSERT INTO `auth_permission` VALUES (46, 'Can change category', 12, 'change_category');
INSERT INTO `auth_permission` VALUES (47, 'Can delete category', 12, 'delete_category');
INSERT INTO `auth_permission` VALUES (48, 'Can view category', 12, 'view_category');
INSERT INTO `auth_permission` VALUES (49, 'Can add article2 tag', 13, 'add_article2tag');
INSERT INTO `auth_permission` VALUES (50, 'Can change article2 tag', 13, 'change_article2tag');
INSERT INTO `auth_permission` VALUES (51, 'Can delete article2 tag', 13, 'delete_article2tag');
INSERT INTO `auth_permission` VALUES (52, 'Can view article2 tag', 13, 'view_article2tag');
-- ----------------------------
-- Table structure for django_admin_log
-- ----------------------------
DROP TABLE IF EXISTS `django_admin_log`;
CREATE TABLE `django_admin_log` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`action_time` datetime(6) NOT NULL,
`object_id` longtext CHARACTER SET utf8mb4 NULL,
`object_repr` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
`action_flag` smallint(5) UNSIGNED NOT NULL,
`change_message` longtext CHARACTER SET utf8mb4 NOT NULL,
`content_type_id` int(11) NULL DEFAULT NULL,
`user_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `django_admin_log_content_type_id_c4bce8eb_fk_django_co`(`content_type_id`) USING BTREE,
INDEX `django_admin_log_user_id_c564eba6_fk_app01_userinfo_id`(`user_id`) USING BTREE,
CONSTRAINT `django_admin_log_content_type_id_c4bce8eb_fk_django_co` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `django_admin_log_user_id_c564eba6_fk_app01_userinfo_id` FOREIGN KEY (`user_id`) REFERENCES `app01_userinfo` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB AUTO_INCREMENT = 39 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of django_admin_log
-- ----------------------------
INSERT INTO `django_admin_log` VALUES (1, '2022-05-06 04:17:37.745040', '1', 'Blog object (1)', 1, '[{\"added\": {}}]', 8, 16);
INSERT INTO `django_admin_log` VALUES (2, '2022-05-06 04:21:20.850805', '2', 'tank', 1, '[{\"added\": {}}]', 8, 16);
INSERT INTO `django_admin_log` VALUES (3, '2022-05-06 04:22:01.053091', '1', 'jason的分类一', 1, '[{\"added\": {}}]', 12, 16);
INSERT INTO `django_admin_log` VALUES (4, '2022-05-06 04:22:21.544286', '2', 'Jason的分类3', 1, '[{\"added\": {}}]', 12, 16);
INSERT INTO `django_admin_log` VALUES (5, '2022-05-06 04:22:35.277002', '3', 'tank的分类1', 1, '[{\"added\": {}}]', 12, 16);
INSERT INTO `django_admin_log` VALUES (6, '2022-05-06 04:22:47.318328', '4', 'tank的分类2', 1, '[{\"added\": {}}]', 12, 16);
INSERT INTO `django_admin_log` VALUES (7, '2022-05-06 04:22:58.587585', '5', 'tank的分类3', 1, '[{\"added\": {}}]', 12, 16);
INSERT INTO `django_admin_log` VALUES (8, '2022-05-06 05:22:03.171646', '1', 'Python企业面试题(系列目录)', 1, '[{\"added\": {}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (9, '2022-05-06 05:22:59.026542', '2', '路过面了个试就拿到2个offer。是运气吗?', 1, '[{\"added\": {}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (10, '2022-05-06 05:24:00.693893', '3', '人生没有白走的路,每一步都算数', 1, '[{\"added\": {}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (11, '2022-05-06 05:24:45.418068', '4', '什么很多IT公司不喜欢进过培训机构的人呢?', 1, '[{\"added\": {}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (12, '2022-05-06 05:26:21.223324', '5', 'Tyrion中文文档(含示例源码)', 1, '[{\"added\": {}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (13, '2022-05-06 05:26:45.667473', '6', 'python 面向对象(进阶篇)', 1, '[{\"added\": {}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (14, '2022-05-06 05:27:13.943979', '7', 'Python 面向对象(初级篇)', 1, '[{\"added\": {}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (15, '2022-05-06 05:27:36.358550', '8', '第五篇:白话tornado源码之褪去模板的外衣', 1, '[{\"added\": {}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (16, '2022-05-06 05:32:57.090225', '17', 'jason', 2, '[{\"changed\": {\"fields\": [\"Blog\"]}}]', 6, 16);
INSERT INTO `django_admin_log` VALUES (17, '2022-05-06 05:33:17.572936', '18', 'tank', 2, '[{\"changed\": {\"fields\": [\"Blog\"]}}]', 6, 16);
INSERT INTO `django_admin_log` VALUES (18, '2022-05-06 05:34:34.085268', '1', 'jason的分类一', 1, '[{\"added\": {}}]', 10, 16);
INSERT INTO `django_admin_log` VALUES (19, '2022-05-06 05:34:42.144549', '2', 'jason的分类2', 1, '[{\"added\": {}}]', 10, 16);
INSERT INTO `django_admin_log` VALUES (20, '2022-05-06 05:34:52.872559', '3', 'tank的分类1', 1, '[{\"added\": {}}]', 10, 16);
INSERT INTO `django_admin_log` VALUES (21, '2022-05-06 05:34:59.765419', '4', 'tank的分类2', 1, '[{\"added\": {}}]', 10, 16);
INSERT INTO `django_admin_log` VALUES (22, '2022-05-06 05:35:06.747176', '5', 'tank的分类3', 1, '[{\"added\": {}}]', 10, 16);
INSERT INTO `django_admin_log` VALUES (23, '2022-05-06 05:35:28.053854', '6', 'jason的分类3', 1, '[{\"added\": {}}]', 10, 16);
INSERT INTO `django_admin_log` VALUES (24, '2022-05-06 05:35:59.159974', '1', 'Article2Tag object (1)', 1, '[{\"added\": {}}]', 13, 16);
INSERT INTO `django_admin_log` VALUES (25, '2022-05-06 05:36:06.845720', '2', 'Article2Tag object (2)', 1, '[{\"added\": {}}]', 13, 16);
INSERT INTO `django_admin_log` VALUES (26, '2022-05-06 05:36:15.127104', '3', 'Article2Tag object (3)', 1, '[{\"added\": {}}]', 13, 16);
INSERT INTO `django_admin_log` VALUES (27, '2022-05-06 05:36:24.459686', '4', 'Article2Tag object (4)', 1, '[{\"added\": {}}]', 13, 16);
INSERT INTO `django_admin_log` VALUES (28, '2022-05-06 05:36:30.917103', '5', 'Article2Tag object (5)', 1, '[{\"added\": {}}]', 13, 16);
INSERT INTO `django_admin_log` VALUES (29, '2022-05-06 05:36:37.160730', '6', 'Article2Tag object (6)', 1, '[{\"added\": {}}]', 13, 16);
INSERT INTO `django_admin_log` VALUES (30, '2022-05-06 05:36:44.165179', '7', 'Article2Tag object (7)', 1, '[{\"added\": {}}]', 13, 16);
INSERT INTO `django_admin_log` VALUES (31, '2022-05-06 05:36:48.800777', '8', 'Article2Tag object (8)', 1, '[{\"added\": {}}]', 13, 16);
INSERT INTO `django_admin_log` VALUES (32, '2022-05-08 11:17:10.433619', '8', '第五篇:白话tornado源码之褪去模板的外衣', 2, '[{\"changed\": {\"fields\": [\"\\u6587\\u7ae0\\u5185\\u5bb9\"]}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (33, '2022-05-08 11:18:32.466323', '7', 'Python 面向对象(初级篇)', 2, '[{\"changed\": {\"fields\": [\"\\u6587\\u7ae0\\u5185\\u5bb9\"]}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (34, '2022-05-08 11:19:25.331625', '6', 'python 面向对象(进阶篇)', 2, '[{\"changed\": {\"fields\": [\"\\u6587\\u7ae0\\u5185\\u5bb9\"]}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (35, '2022-05-08 11:20:03.966130', '5', 'Tyrion中文文档(含示例源码)', 2, '[{\"changed\": {\"fields\": [\"\\u6587\\u7ae0\\u5185\\u5bb9\"]}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (36, '2022-05-08 11:20:38.920291', '4', '什么很多IT公司不喜欢进过培训机构的人呢?', 2, '[{\"changed\": {\"fields\": [\"\\u6587\\u7ae0\\u5185\\u5bb9\"]}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (37, '2022-05-08 11:21:04.780791', '3', '人生没有白走的路,每一步都算数', 2, '[{\"changed\": {\"fields\": [\"\\u6587\\u7ae0\\u5185\\u5bb9\"]}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (38, '2022-05-08 11:21:30.571950', '2', '路过面了个试就拿到2个offer。是运气吗?', 2, '[{\"changed\": {\"fields\": [\"\\u6587\\u7ae0\\u5185\\u5bb9\"]}}]', 7, 16);
INSERT INTO `django_admin_log` VALUES (39, '2022-05-08 11:22:03.768373', '1', 'Python企业面试题(系列目录)', 2, '[{\"changed\": {\"fields\": [\"\\u6587\\u7ae0\\u5185\\u5bb9\"]}}]', 7, 16);
-- ----------------------------
-- Table structure for django_content_type
-- ----------------------------
DROP TABLE IF EXISTS `django_content_type`;
CREATE TABLE `django_content_type` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_label` varchar(100) CHARACTER SET utf8mb4 NOT NULL,
`model` varchar(100) CHARACTER SET utf8mb4 NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `django_content_type_app_label_model_76bd3d3b_uniq`(`app_label`, `model`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of django_content_type
-- ----------------------------
INSERT INTO `django_content_type` VALUES (1, 'admin', 'logentry');
INSERT INTO `django_content_type` VALUES (7, 'app01', 'article');
INSERT INTO `django_content_type` VALUES (13, 'app01', 'article2tag');
INSERT INTO `django_content_type` VALUES (8, 'app01', 'blog');
INSERT INTO `django_content_type` VALUES (12, 'app01', 'category');
INSERT INTO `django_content_type` VALUES (11, 'app01', 'comment');
INSERT INTO `django_content_type` VALUES (10, 'app01', 'tag');
INSERT INTO `django_content_type` VALUES (9, 'app01', 'upanddown');
INSERT INTO `django_content_type` VALUES (6, 'app01', 'userinfo');
INSERT INTO `django_content_type` VALUES (3, 'auth', 'group');
INSERT INTO `django_content_type` VALUES (2, 'auth', 'permission');
INSERT INTO `django_content_type` VALUES (4, 'contenttypes', 'contenttype');
INSERT INTO `django_content_type` VALUES (5, 'sessions', 'session');
-- ----------------------------
-- Table structure for django_migrations
-- ----------------------------
DROP TABLE IF EXISTS `django_migrations`;
CREATE TABLE `django_migrations` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`app` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
`name` varchar(255) CHARACTER SET utf8mb4 NOT NULL,
`applied` datetime(6) NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of django_migrations
-- ----------------------------
INSERT INTO `django_migrations` VALUES (1, 'contenttypes', '0001_initial', '2022-05-03 16:22:39.464683');
INSERT INTO `django_migrations` VALUES (2, 'contenttypes', '0002_remove_content_type_name', '2022-05-03 16:22:39.746284');
INSERT INTO `django_migrations` VALUES (3, 'auth', '0001_initial', '2022-05-03 16:22:40.634875');
INSERT INTO `django_migrations` VALUES (4, 'auth', '0002_alter_permission_name_max_length', '2022-05-03 16:22:40.808783');
INSERT INTO `django_migrations` VALUES (5, 'auth', '0003_alter_user_email_max_length', '2022-05-03 16:22:40.828197');
INSERT INTO `django_migrations` VALUES (6, 'auth', '0004_alter_user_username_opts', '2022-05-03 16:22:40.840784');
INSERT INTO `django_migrations` VALUES (7, 'auth', '0005_alter_user_last_login_null', '2022-05-03 16:22:40.874296');
INSERT INTO `django_migrations` VALUES (8, 'auth', '0006_require_contenttypes_0002', '2022-05-03 16:22:40.894356');
INSERT INTO `django_migrations` VALUES (9, 'auth', '0007_alter_validators_add_error_messages', '2022-05-03 16:22:40.906944');
INSERT INTO `django_migrations` VALUES (10, 'auth', '0008_alter_user_username_max_length', '2022-05-03 16:22:40.916916');
INSERT INTO `django_migrations` VALUES (11, 'auth', '0009_alter_user_last_name_max_length', '2022-05-03 16:22:40.929710');
INSERT INTO `django_migrations` VALUES (12, 'auth', '0010_alter_group_name_max_length', '2022-05-03 16:22:41.023989');
INSERT INTO `django_migrations` VALUES (13, 'auth', '0011_update_proxy_permissions', '2022-05-03 16:22:41.038867');
INSERT INTO `django_migrations` VALUES (14, 'auth', '0012_alter_user_first_name_max_length', '2022-05-03 16:22:41.051246');
INSERT INTO `django_migrations` VALUES (15, 'app01', '0001_initial', '2022-05-03 16:22:45.906315');
INSERT INTO `django_migrations` VALUES (16, 'admin', '0001_initial', '2022-05-03 16:22:46.374005');
INSERT INTO `django_migrations` VALUES (17, 'admin', '0002_logentry_remove_auto_add', '2022-05-03 16:22:46.393110');
INSERT INTO `django_migrations` VALUES (18, 'admin', '0003_logentry_add_action_flag_choices', '2022-05-03 16:22:46.406574');
INSERT INTO `django_migrations` VALUES (19, 'sessions', '0001_initial', '2022-05-03 16:22:46.621555');
-- ----------------------------
-- Table structure for django_session
-- ----------------------------
DROP TABLE IF EXISTS `django_session`;
CREATE TABLE `django_session` (
`session_key` varchar(40) CHARACTER SET utf8mb4 NOT NULL,
`session_data` longtext CHARACTER SET utf8mb4 NOT NULL,
`expire_date` datetime(6) NOT NULL,
PRIMARY KEY (`session_key`) USING BTREE,
INDEX `django_session_expire_date_a5c62663`(`expire_date`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of django_session
-- ----------------------------
INSERT INTO `django_session` VALUES ('48esxsatvgzloe2dvnadykntr78dt4tc', '.eJxVjL0OwiAURt-F2RAp7aU4uji5ujbce0FqDST9GYzx3YWkS8fvfCfnKyizFxcRH9PnJk5icNsah23x8zBy4QqOEB1NPtWHXy49s6Sc1nlEWRW5v4u8l-r7uruHQHRLrF3tW0ehw67pFRulqeeyfGNQc-dbGwwAETZna0CzsYUGtBgAoFUOxe8PPL486w:1nnigo:B0qRjHaQV1rd0031f7A4tySD2D03CA1p67TzRwv6dZ0', '2022-05-22 15:19:18.488351');
INSERT INTO `django_session` VALUES ('7k2h4tzg7hwpqllocz9e1qezqeeu1f0g', '.eJxVjL0OwiAURt-F2RDAy5-jSUcXX6DhwsVWTUlK62J8d2nSpes55_u-LJZE7MLuH4UdO7E-rMvQr5XmfkyNS3uEGOKLps2kZ5gehccyLfOIfEv4biu_tdf3dW8PB0OoQ1sjpLNBtFEqsOC8IJl9yGS1EU5D1EkkrxwI7zyhQe8gRK3IOKt0lsB-f-6eO5I:1nmsF0:93qBiOPn4O6nONxafNYtBeGCj6KBiVO_je1yv8HFc_I', '2022-05-20 07:19:06.804650');
INSERT INTO `django_session` VALUES ('b3ayl7uno7p07qqe1kswy2s1lg71m4co', '.eJxdjDsOwjAQBe_iGlm2s_5R0nMGy-vdkABKpDgpEOLuxFIaaGfmvbcoM7E4C_3qRi9OIuVtHdJWeUkjNf4HMZcHT83QPU-3WZZ5WpcRZUvkYau87q_Py9H-HAy5DvsagTqH6Is24CFExbqPuWdvnQoWiiVF0QRQMURGhzFALtawC97YXoP4fAHVtDtu:1np8k6:TzEHwkChq0n409e2QOXKowchpASlXA3RDyhkpFuvU2o', '2022-05-26 13:20:34.730523');
INSERT INTO `django_session` VALUES ('nar9kg8i2206jwz87d6v9dsy6h2bsxsi', 'eyJjb2RlIjoicFc2Q1AifQ:1o3FrF:ZLaPKdCpdPksM0vVDNXWYVs24LuQPUGVCWrW0bgzS5M', '2022-07-04 11:46:17.838986');
INSERT INTO `django_session` VALUES ('xagifr1oajn2rb64idvg40apmltk692v', 'eyJjb2RlIjoiNUVKZk4ifQ:1no1F0:0O1QzaaYHHKGbdof_oQWtO-5B7wwIVUn2uRBanFOH9c', '2022-05-23 11:07:50.101489');
INSERT INTO `django_session` VALUES ('xj2aj9zp7agca9owibt7ewemmblz75hg', '.eJxVjMsOwiAQRf-FtSGAw8ul-34DYWCQqoGktCvjv2uTLnR7zzn3xULc1hq2QUuYM7swadnpd8SYHtR2ku-x3TpPva3LjHxX-EEHn3qm5_Vw_w5qHPVbI-SzQbRJKrDgvCBZfCxktRFOQ9JZZK8cCO88oUHvICatyDirdJHA3h_73Ddo:1noRvz:1EZwLadlyOe_cwATyN6IlljVfC1v8X5RjBZxoV1VaQg', '2022-05-24 15:37:59.064609');
SET FOREIGN_KEY_CHECKS = 1;