[
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django "
                    }
                ],
                "level": 1
            },
            "bbox": [
                149,
                112,
                294,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "本身基于 MVC 模型（架构），即 Model（模型） "
                    },
                    {
                        "type": "equation_inline",
                        "content": "^ +"
                    },
                    {
                        "type": "text",
                        "content": "View（视图） "
                    },
                    {
                        "type": "equation_inline",
                        "content": "^ +"
                    },
                    {
                        "type": "text",
                        "content": "Controller（控制器）设计模式，MVC 模式使后续对程序的修改和扩展简化，并且使程序某一部分的重复利用成为可能。但在 Django 中更常被称为 MTV（Model-Template-View）。"
                    }
                ]
            },
            "bbox": [
                144,
                161,
                848,
                212
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "模型（Model）：负责应用程序的数据和业务逻辑。通过将数据和逻辑从用户界面分离出来，使得模型可以独立于用户界面进行测试和修改。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "视图（View）：负责显示用户界面，但通常没有直接访问应用程序的数据。这使得可以更容易地更改应用程序的外观而不影响数据处理。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "控制器（Controller）：处理用户输入、更新模型和调整视图。通过将用户输入和应用程序逻辑分离，可以更容易地更改用户界面的交互方式而不影响数据和业务逻辑。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                159,
                217,
                845,
                347
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 提供了全栈开发所需的工具，包括数据库ORM、模板引擎、路由系统、用户认证等，大幅减少重复代码。"
                    }
                ]
            },
            "bbox": [
                144,
                366,
                815,
                379
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 的哲学:"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                397,
                245,
                410
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "DRY（Don't Repeat Yourself）: 避免重复代码，提倡复用（如模板继承、模型继承）。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "约定优于配置: 默认提供合理配置（如自动生成Admin 界面），减少决策成本。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "快速开发：Django 提供了大量内置功能，如认证、管理后台、表单处理等，让开发者专注于业务逻辑，而非底层实现。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "自动化管理后台：只需简单的模型定义，即可生成强大的后台管理界面，支持增删改查。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "ORM 数据库映射：Django 内置 ORM (Object-Relational Mapping)，可以让开发者使用 Python 类与数据库交互，无需编写 SQL。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "强大的 URL 路由：使用正则表达式灵活定义 URL，轻松实现页面路由。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "模板引擎：内置强大的模板系统，支持逻辑判断、循环处理，方便渲染 HTML 页面。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "国际化支持：Django 支持多语言国际化，非常适合全球化应用。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "高安全性：内置多种安全保护措施，如防止 SQL 注入、XSS 攻击、CSRF 攻击等。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " 丰富的社区与扩展：大量开源的第三方库，如 Django REST framework、Django CMS 等，快速扩展功能。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                428,
                850,
                757
            ]
        },
        {
            "type": "image",
            "content": {
                "image_source": {
                    "path": "images/f4487cc28d0ed6be5aa3b6d12a641d265ce457c6192d9a6a0c73c17c74dfe081.jpg"
                },
                "image_caption": [],
                "image_footnote": []
            },
            "bbox": [
                149,
                771,
                426,
                883
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "内置功能"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                130,
                273,
                154
            ]
        },
        {
            "type": "table",
            "content": {
                "image_source": {
                    "path": "images/5d60b0537c37007c990ae2b61e846c3457cfbc1fa80f09239c115f6a3a8da393.jpg"
                },
                "table_caption": [],
                "table_footnote": [],
                "html": "<table><tr><td>功能</td><td>说明</td></tr><tr><td>Admin后台</td><td>自动生成管理界面，无需手动编写CRUD逻辑。</td></tr><tr><td>ORM</td><td>用Python类操作数据库，无需写SQL。</td></tr><tr><td>表单处理</td><td>内置表单验证，防止CSRF攻击。</td></tr><tr><td>用户认证</td><td>提供登录、注册、权限管理（django.contrib.auth）。</td></tr><tr><td>路由系统</td><td>URL映射灵活，支持正则表达式。</td></tr><tr><td>缓存机制</td><td>支持Memcached、Redis等后端。</td></tr></table>",
                "table_type": "simple_table",
                "table_nest_level": 1
            },
            "bbox": [
                147,
                162,
                998,
                475
            ]
        },
        {
            "type": "image",
            "content": {
                "image_source": {
                    "path": "images/9e8b7b91d694be7a68319af4130f4b3e88f070e1faac0f9b9d52e5a8c0d292a6.jpg"
                },
                "image_caption": [],
                "image_footnote": []
            },
            "bbox": [
                147,
                506,
                715,
                709
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "MVC (Model-View-Controller) "
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                730,
                586,
                755
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "Model (模型)：处理与数据库的交互，定义数据的结构和业务逻辑。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "View (视图)：负责数据展示，生成用户看到的HTML 页面。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "Controller (控制器)：接收用户请求，调用Model 处理数据，并将结果传递给View 渲染页面。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                766,
                761,
                841
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "流程："
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                859,
                184,
                871
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "1. 用户发送请求到 Controller。"
                    }
                ]
            },
            "bbox": [
                176,
                890,
                371,
                902
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "2. Controller 处理逻辑，调用 Model 获取数据。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "3. Controller 将数据传递给 View。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "4. View 渲染并返回 HTML 页面给用户。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                93,
                470,
                168
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "MVT (Model-Template-View) —— Django 的实现方式"
                    }
                ],
                "level": 1
            },
            "bbox": [
                144,
                191,
                826,
                253
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 中采用了MVT 设计模式，类似于MVC，但有一些区别："
                    }
                ]
            },
            "bbox": [
                144,
                263,
                527,
                278
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "Model (模型)：与数据库交互，处理数据的创建、读取、更新、删除。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "Template (模板)：负责页面渲染，生成最终的HTML 内容。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "View (视图)：Django 的View 更偏向于控制器的角色，接收请求并决定使用哪个模板和数据。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                296,
                757,
                370
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "流程："
                    }
                ]
            },
            "bbox": [
                146,
                388,
                184,
                401
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "用户访问 URL，请求被 Django 的 urls.py 映射到相应的 View。"
                    }
                ],
                "level": 1
            },
            "bbox": [
                144,
                426,
                789,
                445
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "url.py下  \nurlpatterns  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " [url(r'^search-form/\\$,search.search_form)，#映射到search.py中search_form视图url(r'^search/\\$,search.search)， #映射到search.py中search视图url(r'^search-post/\\$,search2.search_post),#映射到search2.py中search_post视图]"
                    }
                ]
            },
            "bbox": [
                206,
                460,
                747,
                627
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 当访问 /search-form/ 时，Django 调用 search.search_form 视图函数"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "当提交表单到 /search/ 时，调用 search.search 视图函数"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                645,
                645,
                688
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "View 处理业务逻辑，调用Model 获取数据。"
                    }
                ],
                "level": 1
            },
            "bbox": [
                144,
                714,
                589,
                733
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "(1) 渲染搜索表单（但是这里无Model交互）"
                    }
                ]
            },
            "bbox": [
                206,
                747,
                470,
                760
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "# search.py\ndef search_form(request):\n    return render(request, 'search_form.html')  # 直接渲染模板"
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                206,
                778,
                576,
                854
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "流程："
                    }
                ]
            },
            "bbox": [
                176,
                871,
                243,
                883
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "View 只负责返回模板，未涉及Model 数据操作"
                    }
                ]
            },
            "bbox": [
                205,
                890,
                489,
                902
            ]
        }
    ],
    [
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [
                    {
                        "type": "text",
                        "content": "(2) 处理搜索请求（带参数校验）"
                    }
                ],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "def search(request): request_encoding  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " 'utf-8' if  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\mathrm{q}^{\\prime}"
                    },
                    {
                        "type": "text",
                        "content": " in request.GET and request.GET['q']: #业务逻辑判断 message  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " '你搜索的内容为:'  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "^+"
                    },
                    {
                        "type": "text",
                        "content": " request.GET['q'] else: message  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " '你提交了空表单' return HttpResponse(message)#直接返回响应（未用模板） "
                    }
                ]
            },
            "bbox": [
                206,
                155,
                591,
                357
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [
                    {
                        "type": "text",
                        "content": "（3）# 接收POST请求数据"
                    }
                ],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "def search_post(request):   \nctx  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "= \\{\\}"
                    },
                    {
                        "type": "text",
                        "content": "   \nif request.POST:   \nctx['rlt']  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " request.POST['q']   \nreturn render(request, \"post.html\", ctx) "
                    }
                ]
            },
            "bbox": [
                206,
                406,
                455,
                545
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "View 将数据传递给 Template。"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                599,
                470,
                620
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "return render(request, 'search_form.html') "
                    }
                ],
                "code_language": "lua"
            },
            "bbox": [
                206,
                663,
                460,
                676
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在这个例子中，search_form 只是用来展示HTML 表单页面，没有动态数据传入。"
                    }
                ]
            },
            "bbox": [
                206,
                694,
                687,
                708
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "虽然这里没有传递变量，但你可以通过 render 的第三个参数传数据给模板："
                    }
                ]
            },
            "bbox": [
                206,
                725,
                653,
                738
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "return render(request, 'search_form.html', {'key': value}) "
                    }
                ],
                "code_language": "lua"
            },
            "bbox": [
                206,
                756,
                542,
                769
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "第二个没有传输数据因为根本没有template"
                    }
                ]
            },
            "bbox": [
                208,
                789,
                468,
                803
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "第三个例子"
                    }
                ]
            },
            "bbox": [
                208,
                822,
                278,
                835
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "return render(request, \"post.html\", ctx) "
                    }
                ],
                "code_language": "lua"
            },
            "bbox": [
                206,
                854,
                438,
                866
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "1. Template 渲染 HTML，最终返回给用户。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "模板文件: search_form.html"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                95,
                450,
                137
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "</form> "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                176,
                250,
                226,
                261
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Tip：HTML <form> action 属性"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                291,
                500,
                311
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "<form action=\"/search/\" method=\"get\"> "
                    }
                ],
                "code_language": "twig"
            },
            "bbox": [
                176,
                351,
                413,
                363
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "<input type=\"text\" name=\"q\"> "
                    }
                ],
                "code_language": "twig"
            },
            "bbox": [
                184,
                384,
                363,
                395
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "<input type=\"submit\" value=\"搜索\"> "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                184,
                414,
                400,
                426
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "</form> "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                176,
                445,
                226,
                456
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "(1) <form> 标签 "
                    }
                ]
            },
            "bbox": [
                176,
                476,
                278,
                489
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "action=\"/search/\" "
                    }
                ]
            },
            "bbox": [
                176,
                508,
                322,
                518
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 表单提交的目标URL地址"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o /search/ 表示提交到当前网站的搜索端点（例如 https://example.com/search/）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 尾部斜杠/ 表示这是一个目录路径（符合RESTful风格）"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                539,
                744,
                612
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": ". method=\"get\""
                    }
                ]
            },
            "bbox": [
                176,
                632,
                300,
                643
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 使用 HTTP GET 方法提交数据"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 表单数据会附加在URL后（如 /search/?q=关键词）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 适合不修改服务器状态的查询操作（如搜索）"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                663,
                576,
                736
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "2. 实际工作流程"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                755,
                247,
                766
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "1. 用户交互"
                    }
                ]
            },
            "bbox": [
                176,
                787,
                265,
                799
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 在文本框中输入内容（如\"无人机\"）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 点击\"搜索\"按钮 "
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                816,
                473,
                860
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "2. 浏览器行为"
                    }
                ]
            },
            "bbox": [
                176,
                879,
                278,
                891
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 自动组装 URL：/search/?q=无人机"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 发起GET请求（HTTP头部示例）："
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                93,
                485,
                137
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "GET /search/?q=无人机 HTTP/1.1"
                    }
                ]
            },
            "bbox": [
                146,
                156,
                354,
                168
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Host: example.com "
                    }
                ]
            },
            "bbox": [
                146,
                187,
                265,
                199
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "3. 服务器处理 "
                    }
                ],
                "level": 1
            },
            "bbox": [
                176,
                218,
                278,
                230
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "o Django路由将请求交给对应的View处理："
                    }
                ]
            },
            "bbox": [
                236,
                249,
                517,
                261
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# urls.py "
                    }
                ]
            },
            "bbox": [
                146,
                281,
                203,
                293
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "path('search/', views.search) "
                    }
                ]
            },
            "bbox": [
                146,
                311,
                319,
                323
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# views.py "
                    }
                ]
            },
            "bbox": [
                146,
                343,
                215,
                354
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def search(request): "
                    }
                ]
            },
            "bbox": [
                146,
                373,
                270,
                385
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "query "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "request.GET.get('q') # 获取参数\"q\"的值 "
                    }
                ]
            },
            "bbox": [
                161,
                405,
                452,
                417
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(f\"搜索内容：{query}\")"
                    }
                ]
            },
            "bbox": [
                161,
                436,
                421,
                449
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "渲染过程: "
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                535,
                248,
                554
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "1. search_form 视图调用 render(request, 'search_form.html')"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "2. Django 模板引擎找到 templates/search_form.html"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "3. 生成纯静态HTML 返回给用户"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                569,
                638,
                642
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "第二个方式没有模板渲染，直接返回httpresponse响应。"
                    }
                ]
            },
            "bbox": [
                146,
                661,
                482,
                674
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "第三个例子"
                    }
                ]
            },
            "bbox": [
                206,
                694,
                278,
                707
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "<form action=\"/search-post/\" method=\"post\"> "
                    }
                ]
            },
            "bbox": [
                206,
                725,
                480,
                738
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "{% csrf_token %} "
                    }
                ]
            },
            "bbox": [
                221,
                756,
                329,
                769
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "<input type=\"text\" name=\"q\"> "
                    }
                ]
            },
            "bbox": [
                221,
                788,
                403,
                800
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "<input type "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\mathrel { \\mathop = } \\frac { \\ d } { \\ d t }"
                    },
                    {
                        "type": "text",
                        "content": "\"submit\" value=\"搜索\"> "
                    }
                ]
            },
            "bbox": [
                221,
                819,
                436,
                831
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "</form> "
                    }
                ]
            },
            "bbox": [
                206,
                850,
                258,
                860
            ]
        }
    ],
    [
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "<p>\\{rtt}></p> "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                206,
                95,
                299,
                107
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "项目 GET 示例 POST 示例"
                    }
                ]
            },
            "bbox": [
                176,
                126,
                623,
                139
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "URL 个数 2 个 (/search-form/ 和 /search/) 1 个 (/search-post/)"
                    }
                ]
            },
            "bbox": [
                176,
                159,
                684,
                173
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "表单方法 method=\"get\" method=\"post\""
                    }
                ]
            },
            "bbox": [
                176,
                192,
                660,
                205
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "数据传输方式 通过 URL 参数 (?q=...) 通过请求体"
                    }
                ]
            },
            "bbox": [
                176,
                225,
                625,
                237
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "安全性 较低，数据暴露在 URL 中 更安全，数据在请求体中"
                    }
                ]
            },
            "bbox": [
                176,
                256,
                705,
                271
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "CSRF Token 不需要 必须要"
                    }
                ]
            },
            "bbox": [
                176,
                290,
                600,
                303
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "View 函数数量 2 个 1 个 "
                    }
                ]
            },
            "bbox": [
                176,
                323,
                584,
                335
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "显示与处理 分开处理 合并处理"
                    }
                ]
            },
            "bbox": [
                176,
                356,
                611,
                369
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "(1) 您的两个视图函数"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                388,
                278,
                400
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 显示视图 （表面看只负责显示）"
                    }
                ]
            },
            "bbox": [
                146,
                419,
                344,
                431
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def search_form(request): "
                    }
                ]
            },
            "bbox": [
                146,
                450,
                305,
                462
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return render(request, 'search_form.html') # 但本质上仍是View 层 "
                    }
                ]
            },
            "bbox": [
                161,
                481,
                563,
                494
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 处理视图 （表面看只负责处理）"
                    }
                ]
            },
            "bbox": [
                146,
                512,
                344,
                524
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def search(request): "
                    }
                ]
            },
            "bbox": [
                146,
                543,
                270,
                555
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "message "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "process_request(request.GET) # 处理逻辑 "
                    }
                ]
            },
            "bbox": [
                161,
                574,
                495,
                586
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(message) # 响应生成"
                    }
                ]
            },
            "bbox": [
                161,
                605,
                428,
                618
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "本质："
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                636,
                183,
                646
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "这两个函数都属于View 层，只是内部逻辑侧重不同。Django 的View 是统一的请求处理器，不强制分离显示与处理。"
                    }
                ]
            },
            "bbox": [
                144,
                653,
                840,
                667
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "(2) 为什么不是两个MVT？"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                684,
                304,
                697
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "Model：两个视图可能共享同一个Model（如都查询Article 表）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "Template：search_form 使用模板，search 直接返回响应（动态选择）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "View：都是接收request 并返回响应的函数"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                715,
                633,
                791
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "创建第一个项目"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                820,
                428,
                850
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "使用 django-admin 来创建 HelloWorld 项目："
                    }
                ]
            },
            "bbox": [
                147,
                868,
                413,
                881
            ]
        }
    ],
    [
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "django-admin startproject HelloWorld "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                93,
                426,
                107
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "$ cd HelloWorld/ "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                123,
                250,
                135
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "$tree "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                155,
                184,
                166
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/ #项目根目录"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                186,
                366,
                198
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "manage.py #项目管理脚本"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                149,
                216,
                401,
                229
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "dbsqlite3 #SQLite数据库文件"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                149,
                247,
                420,
                260
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "—— Pycache_// #Python字节码缓存"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                149,
                278,
                440,
                292
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "—HelloWorld/#项目配置目录（与项目同名）"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                149,
                309,
                482,
                322
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "init.py #包标识文件"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                164,
                340,
                379,
                354
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "—settings.py #项目设置"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                164,
                370,
                364,
                384
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "├—urls.py #主路由配置 "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                164,
                401,
                364,
                414
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "— asgi.py #ASGI 配置 "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                164,
                432,
                363,
                447
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "—wsgi.py #WSGI配置 "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                164,
                464,
                369,
                478
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "目录说明："
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                502,
                253,
                521
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "项目根目录 (HelloWorld/)："
                    }
                ]
            },
            "bbox": [
                147,
                538,
                312,
                552
            ]
        },
        {
            "type": "table",
            "content": {
                "image_source": {
                    "path": "images/c43fbf5546482fbe70641375fef390807849c110805286d7c5ea772917c5c607.jpg"
                },
                "table_caption": [],
                "table_footnote": [],
                "html": "<table><tr><td>文件/目录</td><td>作用</td></tr><tr><td>manage.py</td><td>Django命令行工具入口，可让你以各种方式与该Django项目进行交互。用于运行开发服务器、数据库迁移等操作。</td></tr><tr><td>db.sql3</td><td>SQLite 数据库文件（默认数据库，开发环境使用）。</td></tr><tr><td>__pycache__I</td><td>Python字节码缓存目录（自动生成，无需手动修改）。</td></tr></table>",
                "table_type": "simple_table",
                "table_nest_level": 1
            },
            "bbox": [
                147,
                557,
                998,
                684
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "HelloWorld: 项目的容器。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "HelloWorld/__init__.py: 一个空文件，告诉 Python 该目录是一个 Python 包。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "HelloWorld/asgi.py: 一个 ASGI 兼容的 Web 服务器的入口，以便运行你的项目。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "HelloWorld/settings.py: 该 Django 项目的设置/配置。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                132,
                709,
                643,
                815
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": []
            },
            "bbox": [
                183,
                841,
                194,
                848
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "核心配置文件，包含："
                    }
                ]
            },
            "bbox": [
                213,
                858,
                344,
                871
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "- 数据库设置 (DATABASES)"
                    }
                ]
            },
            "bbox": [
                213,
                877,
                383,
                890
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "- 静态文件路径 (STATIC_URL)"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "- 应用注册 (INSTALLED_APPS) "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "- 调试模式 (DEBUG=True/False)"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                213,
                101,
                411,
                152
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/urls.py: 该 Django 项目的 URL 声明; 一份由 Django 驱动的网站\"目录\"。"
                    }
                ]
            },
            "bbox": [
                134,
                206,
                665,
                221
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "主路由配置文件，定义URL 路径与视图的映射关系。"
                    }
                ]
            },
            "bbox": [
                169,
                263,
                482,
                277
            ]
        },
        {
            "type": "image",
            "content": {
                "image_source": {
                    "path": "images/a823f7d1709065a5407af080d7f7f97b7690b14cc995738e94875496ffb4c9e6.jpg"
                },
                "image_caption": [],
                "image_footnote": []
            },
            "bbox": [
                166,
                332,
                771,
                456
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口，以便运行你的项目。"
                    }
                ]
            },
            "bbox": [
                134,
                475,
                652,
                489
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "关键文件详解"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                517,
                292,
                536
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "1. settings.py（核心配置）"
                    }
                ]
            },
            "bbox": [
                134,
                579,
                285,
                592
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ]
            },
            "bbox": [
                134,
                609,
                166,
                621
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# HelloWorld/settings.py 示例片段"
                    }
                ]
            },
            "bbox": [
                134,
                640,
                329,
                653
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 安全警告：生产环境必须关闭DEBUG！"
                    }
                ]
            },
            "bbox": [
                134,
                678,
                369,
                690
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "DEBUG "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "True "
                    }
                ]
            },
            "bbox": [
                134,
                697,
                215,
                707
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 允许访问的域名（DEBUG=False 时需配置）"
                    }
                ]
            },
            "bbox": [
                134,
                734,
                389,
                746
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "ALLOWED_HOSTS = [] "
                    }
                ]
            },
            "bbox": [
                134,
                752,
                255,
                764
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 注册的 Django 应用"
                    }
                ]
            },
            "bbox": [
                134,
                789,
                260,
                802
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "INSTALLED_APPS = [ "
                    }
                ]
            },
            "bbox": [
                134,
                807,
                248,
                820
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.admin', # 管理员后台"
                    }
                ]
            },
            "bbox": [
                147,
                826,
                359,
                838
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.auth', # 认证系统"
                    }
                ]
            },
            "bbox": [
                147,
                845,
                341,
                857
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.contenttypes', "
                    }
                ]
            },
            "bbox": [
                147,
                863,
                314,
                875
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.sessions', "
                    }
                ]
            },
            "bbox": [
                147,
                882,
                287,
                892
            ]
        }
    ],
    [
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.messages',  \n'django.contrib(staticfiles', #静态文件处理  \n]  \n#数据库配置（默认SQLite）  \nDATABASES = {  \n    'default': {  \n        'ENGINE': 'django.db.backendssqlite3',  \n        'NAME': BASE_DIR / 'db.sqlite3', #数据库文件路径}  \n}  \n#静态文件URL（CSS/JS/图片）  \nSTATIC_URL = 'static/'"
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                129,
                93,
                450,
                350
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "2. urls.py（路由配置）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                134,
                366,
                263,
                379
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                134,
                397,
                168,
                410
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# HelloWorld/urls.py 示例"
                    }
                ]
            },
            "bbox": [
                134,
                428,
                285,
                441
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import admin "
                    }
                ]
            },
            "bbox": [
                134,
                466,
                327,
                478
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.urls import path "
                    }
                ]
            },
            "bbox": [
                134,
                483,
                300,
                495
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "urlpatterns  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "= ["
                    },
                    {
                        "type": "text",
                        "content": " path('admin／',admin.site.urls)，#后台管理路由 #可在此添加自定义路由，如： #path('blog／',include('blog URLs'))   \n]"
                    }
                ]
            },
            "bbox": [
                134,
                521,
                416,
                608
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "3. manage.py（项目管理脚本）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                134,
                626,
                314,
                639
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                134,
                657,
                168,
                669
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "#!/usr/bin/env python "
                    }
                ]
            },
            "bbox": [
                134,
                688,
                262,
                700
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "import os "
                    }
                ]
            },
            "bbox": [
                134,
                707,
                193,
                718
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "import sys "
                    }
                ]
            },
            "bbox": [
                134,
                725,
                196,
                737
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "if __name__ == \"_main_:  \nos.environ.setdefault(\"DJANGO.SettingsMODULE\", \"HelloWorld.Settings\")  \nfrom django.core.management import execute_from_command_line  \nexecute_from_command_line(sys.argv) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                134,
                762,
                571,
                832
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "启动服务器"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                854,
                265,
                873
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "接下来我们进入 HelloWorld 目录输入以下命令，启动服务器："
                    }
                ]
            },
            "bbox": [
                132,
                889,
                495,
                902
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "0.0.0.0 让其它电脑可连接到开发服务器，8000 为端口号。如果不说明，那么端口号默认为 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "8 0 0 0 _ { \\circ }"
                    }
                ]
            },
            "bbox": [
                132,
                126,
                702,
                139
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在浏览器输入你服务器的 ip（这里我们输入本机 IP 地址： 127.0.0.1:8000） 及端口号。"
                    }
                ]
            },
            "bbox": [
                132,
                156,
                640,
                170
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "常用 django-admin 命令详解"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                193,
                458,
                215
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django-admin 是 Django 框架提供的一个命令行工具，它是管理 Django 项目的核心工具。"
                    }
                ]
            },
            "bbox": [
                144,
                227,
                677,
                241
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "无论是创建新项目、运行开发服务器，还是执行数据库迁移，django-admin 都是不可或缺的工具。"
                    }
                ]
            },
            "bbox": [
                144,
                249,
                724,
                262
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "要查看 django-admin 提供的所有命令，可以运行："
                    }
                ]
            },
            "bbox": [
                146,
                269,
                448,
                284
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django-admin help "
                    }
                ]
            },
            "bbox": [
                146,
                292,
                263,
                305
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "1. 创建新项目"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                355,
                294,
                375
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django-admin startproject 项目名称"
                    }
                ]
            },
            "bbox": [
                134,
                417,
                339,
                429
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "这个命令会在当前目录下创建一个新的 Django 项目，包含基本的项目结构："
                    }
                ]
            },
            "bbox": [
                132,
                447,
                579,
                460
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "manage.py：项目管理脚本"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "项目名称/：项目主目录"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                479,
                368,
                521
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o __init__.py"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o settings.py：项目设置文件"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o urls.py：URL 路由配置 "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o wsgi.py：WSGI 应用入口"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                539,
                425,
                645
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "2. 创建新应用"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                675,
                295,
                694
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "虽然通常使用 manage.py 来创建应用，但也可以通过 django-admin："
                    }
                ]
            },
            "bbox": [
                134,
                736,
                529,
                749
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django-admin startapp 应用名称"
                    }
                ]
            },
            "bbox": [
                134,
                768,
                319,
                780
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "这会创建一个新的 Django 应用，包含："
                    }
                ]
            },
            "bbox": [
                134,
                799,
                364,
                810
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "migrations/：数据库迁移文件目录"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "__init__.py"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "admin.py：管理后台配置"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                829,
                408,
                904
            ]
        },
        {
            "type": "page_header",
            "content": {
                "page_header_content": [
                    {
                        "type": "text",
                        "content": "python3 manage.py runserver 0.0.0.0:8000 "
                    }
                ]
            },
            "bbox": [
                134,
                95,
                376,
                107
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "apps.py：应用配置 "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "models.py：数据模型定义"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "tests.py：测试代码 "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "views.py：视图函数"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                95,
                359,
                199
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "models.py "
                    }
                ]
            },
            "bbox": [
                176,
                219,
                238,
                229
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "定义数据模型，与数据库表对应："
                    }
                ]
            },
            "bbox": [
                176,
                250,
                374,
                261
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                178,
                281,
                208,
                292
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.db import models "
                    }
                ]
            },
            "bbox": [
                176,
                312,
                349,
                323
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "class Product/models.Model): name  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " models.CharField(max_length  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\coloneqq"
                    },
                    {
                        "type": "text",
                        "content": " 100) price  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " modelsDecimalField(maxDigits  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\coloneqq"
                    },
                    {
                        "type": "text",
                        "content": " 10,decimal_places  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\coloneqq"
                    },
                    {
                        "type": "text",
                        "content": " 2) description  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " models.TextField() "
                    }
                ]
            },
            "bbox": [
                176,
                349,
                537,
                416
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def __str__(self): "
                    }
                ]
            },
            "bbox": [
                189,
                441,
                287,
                453
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return self.name "
                    }
                ]
            },
            "bbox": [
                201,
                461,
                295,
                470
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "views.py "
                    }
                ]
            },
            "bbox": [
                176,
                492,
                230,
                502
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "处理业务逻辑，返回响应："
                    }
                ]
            },
            "bbox": [
                176,
                521,
                334,
                533
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                178,
                552,
                208,
                564
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.shortcuts import render "
                    }
                ]
            },
            "bbox": [
                176,
                583,
                383,
                595
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from .models import Product "
                    }
                ]
            },
            "bbox": [
                176,
                602,
                342,
                613
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def product_list(request):\n    products = Product.objects.all()\n    return render(request, 'myapp/product_list.html', {'products': products}) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                176,
                640,
                589,
                688
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "admin.py "
                    }
                ]
            },
            "bbox": [
                176,
                708,
                233,
                719
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "配置 Django 管理后台："
                    }
                ]
            },
            "bbox": [
                176,
                739,
                310,
                751
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                178,
                770,
                208,
                781
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import admin "
                    }
                ]
            },
            "bbox": [
                176,
                800,
                369,
                812
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from .models import Product "
                    }
                ]
            },
            "bbox": [
                176,
                820,
                342,
                829
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "@admin.register(Product) "
                    }
                ]
            },
            "bbox": [
                178,
                856,
                322,
                866
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "3. 检查项目配置"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                186,
                319,
                205
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django-admin check "
                    }
                ]
            },
            "bbox": [
                134,
                247,
                250,
                259
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "这个命令会检查你的 Django 项目是否有配置错误，包括："
                    }
                ]
            },
            "bbox": [
                132,
                278,
                470,
                291
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 模型定义是否正确 "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "URL 配置是否有效"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "模板设置是否正确"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "静态文件配置等"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                309,
                319,
                414
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "4. 数据库迁移 "
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                444,
                295,
                463
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 使用迁移系统来管理数据库模式变更："
                    }
                ]
            },
            "bbox": [
                134,
                505,
                400,
                517
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django-admin makemigrations # 创建迁移文件"
                    }
                ]
            },
            "bbox": [
                134,
                537,
                401,
                548
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django-admin migrate # 应用迁移到数据库"
                    }
                ]
            },
            "bbox": [
                134,
                568,
                401,
                579
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "5. 创建超级用户"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                608,
                317,
                627
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django-admin createsuperuser "
                    }
                ]
            },
            "bbox": [
                134,
                671,
                305,
                681
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "这个命令会引导你创建一个可以访问 Django 管理后台的超级用户。"
                    }
                ]
            },
            "bbox": [
                132,
                701,
                524,
                714
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "6.启动开发服务器"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                743,
                336,
                762
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django-admin runserver "
                    }
                ]
            },
            "bbox": [
                134,
                804,
                273,
                816
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "基本语法:"
                    }
                ]
            },
            "bbox": [
                134,
                835,
                196,
                847
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "python manage.py runserver [IP:端口] "
                    }
                ]
            },
            "bbox": [
                134,
                866,
                347,
                879
            ]
        },
        {
            "type": "page_header",
            "content": {
                "page_header_content": [
                    {
                        "type": "text",
                        "content": "class ProductAdmin(admin.ModelAdmin): "
                    }
                ]
            },
            "bbox": [
                176,
                95,
                410,
                107
            ]
        },
        {
            "type": "page_header",
            "content": {
                "page_header_content": [
                    {
                        "type": "text",
                        "content": "list_display "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "('name', 'price') "
                    }
                ]
            },
            "bbox": [
                189,
                112,
                351,
                124
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "扩展目录（非自动生成，但常用）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                101,
                477,
                120
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/ "
                    }
                ]
            },
            "bbox": [
                134,
                135,
                206,
                145
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "├── apps/ # 推荐：存放所有自定义应用"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "│ └── blog/ # 示例应用"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "├── static/ # 静态文件（CSS/JS/图片）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "├── media/ # 用户上传文件"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "├── templates/ # 全局模板目录"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "└── requirements.txt # 项目依赖列表"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                136,
                165,
                410,
                332
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "1. apps/ 目录（推荐结构）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                362,
                421,
                382
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "将应用集中管理，避免散落在项目根目录。"
                    }
                ]
            },
            "bbox": [
                134,
                423,
                386,
                436
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "需在 settings.py 中配置 Python 路径："
                    }
                ]
            },
            "bbox": [
                134,
                454,
                347,
                467
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "import sys "
                    }
                ]
            },
            "bbox": [
                134,
                486,
                194,
                497
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))"
                    }
                ]
            },
            "bbox": [
                134,
                516,
                401,
                527
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "2. 静态文件与媒体文件"
                    }
                ],
                "level": 1
            },
            "bbox": [
                144,
                558,
                389,
                577
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "static/：存放 CSS、JavaScript、图片等，通过 STATIC_URL 访问。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "media/：用户上传的文件（如头像），通过 MEDIA_URL 访问。需配置服务器在开发时提供访问："
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". # urls.py（仅开发环境）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "from django.conf import settings "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "from django.conf.urls.static import static "
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                619,
                771,
                783
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "urlpatterns "
                    },
                    {
                        "type": "equation_inline",
                        "content": "+ ="
                    },
                    {
                        "type": "text",
                        "content": "static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) "
                    }
                ]
            },
            "bbox": [
                134,
                804,
                584,
                818
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "一个项目可以由多个应用"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                873,
                400,
                892
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "myproject/ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "├── manage.py "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "├── requirements.txt "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "├── static/ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "│ ── css/ ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "│ ── js/ ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "│ └── images/ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "├── media/ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "├── templates/ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "│ └── base.html "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "└── myproject/ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── __init__.py ├"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── settings.py ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── urls.py ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── wsgi.py ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "└── asgi.py "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "└── myapp1/ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── migrations/├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── templates/ ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "│ └── myapp1/ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── __init__.py ├"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── admin.py ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── apps.py ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── models.py ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── tests.py ├ "
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                134,
                93,
                255,
                882
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "── urls.py ├ "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "└── views.py "
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                147,
                93,
                221,
                137
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "└── myapp2/ "
                    }
                ]
            },
            "bbox": [
                136,
                156,
                211,
                168
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "└── ... (类似结构) "
                    }
                ]
            },
            "bbox": [
                147,
                187,
                248,
                200
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实践建议"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                218,
                205,
                230
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "1. 项目与应用分离：保持每个应用的独立性，便于复用"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "2. 环境配置：使用不同的 settings 文件区分开发和生产环境"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "3. 静态文件管理：开发时使用 STATICFILES_DIRS，生产时使用 collectstatic"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "4. URL 设计：在应用级别定义 URL，然后在项目级别包含"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "5. 模板组织：为每个应用创建子目录存放模板"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                249,
                618,
                386
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "生产环境vs 开发环境差异"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                404,
                304,
                418
            ]
        },
        {
            "type": "table",
            "content": {
                "image_source": {
                    "path": "images/d1a1f6ba9036662acf8c0bf0be0cbc4df02f97c028a0669d048704990c5b36eb.jpg"
                },
                "table_caption": [],
                "table_footnote": [],
                "html": "<table><tr><td>文件/配置</td><td>开发环境</td><td>生产环境</td></tr><tr><td>DEBUG</td><td>True（显示错误详情）</td><td>False（隐藏错误，记录到日志）</td></tr><tr><td>数据库</td><td>SQLite（默认）</td><td>PostgreSQL/MySQL（性能优化）</td></tr><tr><td>静态文件</td><td>runserver 自动服务</td><td>使用 collectstatic 收集到 CDN</td></tr><tr><td>ALLOWED_HOSTS</td><td>空列表或 [&#x27;localhost&#x27;]</td><td>必须配置域名（如 [&#x27;example.com&#x27;])</td></tr></table>",
                "table_type": "simple_table",
                "table_nest_level": 1
            },
            "bbox": [
                147,
                432,
                998,
                657
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "path() 函数"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                695,
                309,
                722
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django path() 可以接收四个参数，分别是两个必选参数：route、view 和两个可选参数：kwargs、name。"
                    }
                ]
            },
            "bbox": [
                146,
                728,
                766,
                743
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "语法格式："
                    }
                ]
            },
            "bbox": [
                147,
                747,
                203,
                760
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "path(route, view, kwargs=None, name=None) "
                    }
                ]
            },
            "bbox": [
                147,
                777,
                460,
                789
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "route：字符串，定义URL 的路径部分。可以包含变量，例如<int:my_variable>，以从URL 中捕获参数并将其传递给视图函数。"
                    }
                ]
            },
            "bbox": [
                144,
                806,
                847,
                837
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "view：视图函数，处理与给定路由匹配的请求。可以是一个函数或一个基于类的视图。"
                    }
                ]
            },
            "bbox": [
                146,
                843,
                658,
                856
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "kwargs（可选）：一个字典，包含传递给视图函数的额外关键字参数。"
                    }
                ]
            },
            "bbox": [
                146,
                862,
                568,
                875
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "name（可选）：为URL 路由指定一个唯一的名称，以便在代码的其他地方引用它。这对于在模板中生成URL 或在代码中进行重定向等操作非常有用。"
                    }
                ]
            },
            "bbox": [
                144,
                93,
                848,
                126
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "这样我们就完成了使用模板来输出数据，从而实现数据与视图分离。"
                    }
                ]
            },
            "bbox": [
                146,
                131,
                547,
                145
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "接下来我们将具体介绍模板中常用的语法规则。"
                    }
                ]
            },
            "bbox": [
                146,
                149,
                428,
                162
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 模板"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                193,
                329,
                222
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 的模板系统（Template System）是用于将业务逻辑（Python）与展示层（HTML）分离的核心组件，它允许开发者通过简单的标签和变量动态生成 HTML 页面。"
                    }
                ]
            },
            "bbox": [
                144,
                230,
                840,
                262
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在上一章节中我们使用 django.http.HttpResponse() 来输出 \"Hello World！\"，该方式将数据与视图混合在一起，不符合 Django 的 MVT 思想。"
                    }
                ]
            },
            "bbox": [
                144,
                269,
                843,
                302
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "本章节我们将为大家详细介绍Django 模板的应用，模板是一个文本，用于分离文档的表现形式和内容。"
                    }
                ]
            },
            "bbox": [
                146,
                309,
                757,
                323
            ]
        },
        {
            "type": "table",
            "content": {
                "image_source": {
                    "path": "images/d6715d65fc28226ad77843e37b6ae208fe41f5917292f96ae26d2c7786e130c3.jpg"
                },
                "table_caption": [],
                "table_footnote": [],
                "html": "<table><tr><td>功能</td><td>语法/示例</td><td>适用场景</td></tr><tr><td>变量渲染</td><td>{\\ variable }</td><td>动态显示数据</td></tr><tr><td>逻辑控制</td><td>{% if %}, {% for %}</td><td>条件/循环渲染</td></tr><tr><td>模板继承</td><td>{% extends %}, {% block %}</td><td>避免重复 HTML 结构</td></tr><tr><td>静态文件</td><td>{% static &#x27;path&#x27; %}</td><td>加载 CSS/JS/图片</td></tr><tr><td>自定义过滤器</td><td>@register.filter</td><td>扩展模板功能</td></tr></table>",
                "table_type": "simple_table",
                "table_nest_level": 1
            },
            "bbox": [
                147,
                329,
                1000,
                521
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 模板标签"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                577,
                389,
                607
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "变量"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                621,
                201,
                640
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "模板语法："
                    }
                ]
            },
            "bbox": [
                147,
                653,
                211,
                668
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "view：｛\"HTML 变量名\" : \"views 变量名\"｝ "
                    }
                ]
            },
            "bbox": [
                147,
                683,
                413,
                697
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HTML：｛｛变量名｝｝ "
                    }
                ]
            },
            "bbox": [
                147,
                712,
                275,
                726
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "列表"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                747,
                213,
                769
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "templates 中的 runoob.html 中，可以用 . 索引下标取出对应的元素。"
                    }
                ]
            },
            "bbox": [
                146,
                782,
                552,
                796
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/HelloWorld/views.py 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                800,
                472,
                815
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from django.shortcuts import render  \ndef runoob(request):  \n    views_list = [\"菜鸟教程1\", \"菜鸟教程2\", \"菜鸟教程3\"]  \n    return render(request, \"runoob.html\", {\"views_list\": views_list}) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                822,
                675,
                892
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "templates 中的 runoob.html 中，可以用 .键 取出对应的值。"
                    }
                ]
            },
            "bbox": [
                146,
                93,
                497,
                107
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "过滤器"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                122,
                225,
                142
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "模板语法："
                    }
                ]
            },
            "bbox": [
                146,
                156,
                203,
                168
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "{{ 变量名 | 过滤器：可选参数 }}"
                    }
                ]
            },
            "bbox": [
                147,
                185,
                354,
                198
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "模板过滤器可以在变量被显示前修改它，过滤器使用管道字符，如下所示："
                    }
                ]
            },
            "bbox": [
                146,
                214,
                586,
                227
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "safe "
                    }
                ]
            },
            "bbox": [
                147,
                233,
                179,
                243
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "将字符串标记为安全，不需要转义。"
                    }
                ]
            },
            "bbox": [
                146,
                250,
                357,
                263
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "要保证 views.py 传过来的数据绝对安全，才能用 safe。"
                    }
                ]
            },
            "bbox": [
                146,
                269,
                470,
                282
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "和后端 views.py 的 mark_safe 效果相同。"
                    }
                ]
            },
            "bbox": [
                146,
                288,
                391,
                300
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 会自动对 views.py 传到HTML文件中的标签语法进行转义，令其语义失效。加safe 过滤器是告诉Django 该"
                    }
                ]
            },
            "bbox": [
                144,
                307,
                835,
                319
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "数据是安全的，不必对其进行转义，可以让该数据语义生效。"
                    }
                ]
            },
            "bbox": [
                146,
                326,
                505,
                338
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "if/else 标签"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                353,
                275,
                373
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "基本语法格式如下："
                    }
                ]
            },
            "bbox": [
                146,
                386,
                265,
                399
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "equation_inline",
                        "content": "\\{\\% \\text{if condition}\\}"
                    },
                    {
                        "type": "text",
                        "content": " display{ "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\%"
                    },
                    {
                        "type": "text",
                        "content": "endif} "
                    }
                ]
            },
            "bbox": [
                147,
                414,
                357,
                458
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "或者："
                    }
                ]
            },
            "bbox": [
                146,
                474,
                184,
                486
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "equation_inline",
                        "content": "\\{\\%"
                    },
                    {
                        "type": "text",
                        "content": " if condition1  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\}"
                    },
                    {
                        "type": "text",
                        "content": " . display 1{% elif condition2  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\}"
                    },
                    {
                        "type": "text",
                        "content": " . display 2{% else  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\}"
                    },
                    {
                        "type": "text",
                        "content": " display 3{%endif  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\}"
                    }
                ]
            },
            "bbox": [
                147,
                502,
                431,
                604
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "根据条件判断是否输出。if/else 支持嵌套。"
                    }
                ]
            },
            "bbox": [
                146,
                621,
                396,
                633
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "equation_inline",
                        "content": "\\{ \\%"
                    },
                    {
                        "type": "text",
                        "content": "if %} 标签接受 and ， or 或者 not 关键字来对多个变量做判断 ，或者对变量取反（ not )，例如："
                    }
                ]
            },
            "bbox": [
                146,
                639,
                729,
                653
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "equation_inline",
                        "content": "\\{\\%"
                    },
                    {
                        "type": "text",
                        "content": " if athlete_list and coach_list  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\}"
                    },
                    {
                        "type": "text",
                        "content": " athletes和coaches变量都是可用的。  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\{\\%"
                    },
                    {
                        "type": "text",
                        "content": "endif  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\}"
                    }
                ]
            },
            "bbox": [
                147,
                667,
                521,
                711
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "遍历字典: 可以直接用字典.items 方法，用变量的解包分别获取键和值。"
                    }
                ]
            },
            "bbox": [
                146,
                727,
                571,
                739
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "for 标签 "
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                791,
                238,
                810
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "equation_inline",
                        "content": "\\{ \\%"
                    },
                    {
                        "type": "text",
                        "content": "for "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\% \\}"
                    },
                    {
                        "type": "text",
                        "content": "允许我们在一个序列上迭代。"
                    }
                ]
            },
            "bbox": [
                146,
                825,
                376,
                838
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "与 Python 的 for 语句的情形类似，循环语法是 for X in Y ，Y 是要迭代的序列而 X 是在每一个特定的循环中使用的变量名称。"
                    }
                ]
            },
            "bbox": [
                144,
                844,
                836,
                873
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "每一次循环中，模板系统会渲染在 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "6 \\%"
                    },
                    {
                        "type": "text",
                        "content": "for "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\% 3"
                    },
                    {
                        "type": "text",
                        "content": "和 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "6 \\%"
                    },
                    {
                        "type": "text",
                        "content": "endfor "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\% 3"
                    },
                    {
                        "type": "text",
                        "content": "之间的所有内容。"
                    }
                ]
            },
            "bbox": [
                146,
                881,
                648,
                894
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "例如，给定一个运动员列表 athlete_list 变量，我们可以使用下面的代码来显示这个列表："
                    }
                ]
            },
            "bbox": [
                146,
                95,
                606,
                105
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "{% empty %} "
                    }
                ]
            },
            "bbox": [
                146,
                112,
                233,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "可选的 {% empty "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\% \\}"
                    },
                    {
                        "type": "text",
                        "content": "从句：在循环为空的时候执行（即 in 后面的参数布尔值为 False ）。"
                    }
                ]
            },
            "bbox": [
                146,
                131,
                670,
                143
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "注释标签 "
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                159,
                248,
                179
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 注释使用 {# #}。"
                    }
                ]
            },
            "bbox": [
                146,
                193,
                285,
                206
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "{# 这是一个注释 #}"
                    }
                ]
            },
            "bbox": [
                147,
                221,
                268,
                234
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "include 标签 "
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                256,
                292,
                278
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "{% include %} 标签允许在模板中包含其它的模板的内容。"
                    }
                ]
            },
            "bbox": [
                146,
                291,
                485,
                304
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "下面这个例子都包含了 nav.html 模板："
                    }
                ]
            },
            "bbox": [
                147,
                310,
                374,
                322
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "{% include \"nav.html\" %} "
                    }
                ]
            },
            "bbox": [
                147,
                338,
                332,
                351
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "csrf_token "
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                373,
                307,
                395
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "csrf_token 用于form表单中，作用是跨站请求伪造保护。"
                    }
                ]
            },
            "bbox": [
                146,
                407,
                482,
                419
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "如果不用 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\{ \\%"
                    },
                    {
                        "type": "text",
                        "content": "csrf_token "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\% \\}"
                    },
                    {
                        "type": "text",
                        "content": "标签，在用 form 表单时，要再次跳转页面会报403 权限错误。"
                    }
                ]
            },
            "bbox": [
                146,
                425,
                684,
                437
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "用了{% csrf_token %} 标签，在 form 表单提交数据时，才会成功。"
                    }
                ]
            },
            "bbox": [
                146,
                444,
                544,
                456
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "自定义标签和过滤器"
                    }
                ],
                "level": 1
            },
            "bbox": [
                149,
                468,
                431,
                493
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "1、在应用目录下创建 templatetags 目录(与 templates 目录同级，目录名只能是 templatetags)"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "4、利用装饰器 "
                            },
                            {
                                "type": "equation_inline",
                                "content": "@"
                            },
                            {
                                "type": "text",
                                "content": "register.filter 自定义过滤器。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                146,
                502,
                710,
                533
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意：装饰器的参数最多只能有 2 个。 "
                    }
                ]
            },
            "bbox": [
                146,
                539,
                371,
                551
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "4、利用装饰器 @register.filter 自定义过滤器。"
                    }
                ]
            },
            "bbox": [
                146,
                558,
                418,
                570
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意：装饰器的参数最多只能有 2 个。 "
                    }
                ]
            },
            "bbox": [
                146,
                576,
                371,
                588
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "@register.filterdef my_filter(v1, v2): "
                    }
                ]
            },
            "bbox": [
                147,
                604,
                436,
                618
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return v1 * v2 "
                    }
                ]
            },
            "bbox": [
                178,
                634,
                287,
                645
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "5、利用装饰器 @register.simple_tag 自定义标签。"
                    }
                ]
            },
            "bbox": [
                146,
                664,
                445,
                677
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "配置静态文件"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                688,
                337,
                712
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "1、在项目根目录下创建 statics 目录。"
                    }
                ]
            },
            "bbox": [
                146,
                722,
                369,
                734
            ]
        },
        {
            "type": "image",
            "content": {
                "image_source": {
                    "path": "images/7a0bccfdc891cb8db6929d9ee4656cf5853f50e3339e9658e86f85cd0a8ec3cd.jpg"
                },
                "image_caption": [],
                "image_footnote": []
            },
            "bbox": [
                147,
                737,
                364,
                866
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "2、在 settings 文件的最下方配置添加以下配置："
                    }
                ]
            },
            "bbox": [
                146,
                871,
                431,
                883
            ]
        }
    ],
    [
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "STATIC_url  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " \"/static/'#别名  \nSTATICFILES_DIRS  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " [os.path.join(Base_DIR，\"statics\")，]"
                    }
                ]
            },
            "bbox": [
                147,
                93,
                453,
                165
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "3、在 statics 目录下创建 css 目录，js 目录，images 目录，plugins 目录， 分别放 css 文件，js 文件，图片，插件。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "4、把 bootstrap 框架放入插件目录 plugins。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "5、在 HTML 文件的 head 标签中引入 bootstrap。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                144,
                181,
                826,
                231
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意：此时引用路径中的要用配置文件中的别名static，而不是目录 statics。"
                    }
                ]
            },
            "bbox": [
                146,
                237,
                594,
                250
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "模板继承"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                281,
                275,
                306
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "模板可以用继承的方式来实现复用，减少冗余内容。"
                    }
                ]
            },
            "bbox": [
                144,
                317,
                452,
                329
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "网页的头部和尾部内容一般都是一致的，我们就可以通过模板继承来实现复用。"
                    }
                ]
            },
            "bbox": [
                146,
                336,
                611,
                348
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "父模板用于放置可重复利用的内容，子模板继承父模板的内容，并放置自己的内容。。"
                    }
                ]
            },
            "bbox": [
                146,
                355,
                652,
                367
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "父模板"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                382,
                223,
                401
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "标签 block...endblock: 父模板中的预留区域，该区域留给子模板填充差异性的内容，不同预留区域名字不能相同。"
                    }
                ]
            },
            "bbox": [
                144,
                416,
                821,
                429
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "equation_inline",
                        "content": "\\{\\% \\text{block} \\text{名称} \\% \\}"
                    },
                    {
                        "type": "text",
                        "content": " 预留给子模板的区域，可以设置设置默认内容  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\{\\% \\text{endblock} \\text{名称} \\% \\}"
                    }
                ]
            },
            "bbox": [
                147,
                445,
                662,
                458
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "子模板"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                480,
                223,
                500
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "子模板使用标签extends 继承父模板："
                    }
                ]
            },
            "bbox": [
                147,
                514,
                371,
                527
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "% extends \"父模板路径\"%}"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                544,
                326,
                556
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "子模板如果没有设置父模板预留区域的内容，则使用在父模板设置的默认内容，当然也可以都不设置，就为空。"
                    }
                ]
            },
            "bbox": [
                146,
                573,
                800,
                585
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "子模板设置父模板预留区域的内容："
                    }
                ]
            },
            "bbox": [
                147,
                590,
                357,
                602
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "{  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\%"
                    },
                    {
                        "type": "text",
                        "content": " block名称  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\%"
                    },
                    {
                        "type": "text",
                        "content": " }内容{  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\%"
                    },
                    {
                        "type": "text",
                        "content": " endblock名称  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\%"
                    },
                    {
                        "type": "text",
                        "content": " }"
                    }
                ]
            },
            "bbox": [
                147,
                621,
                448,
                633
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 模型使用自带的 ORM。"
                    }
                ]
            },
            "bbox": [
                146,
                650,
                329,
                662
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "对象关系映射（Object Relational Mapping，简称ORM ）用于实现面向对象编程语言里不同类型系统的数据之间的转换。"
                    }
                ]
            },
            "bbox": [
                144,
                671,
                843,
                702
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "ORM 在业务逻辑层和数据库层之间充当了桥梁的作用。"
                    }
                ]
            },
            "bbox": [
                146,
                711,
                473,
                722
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "ORM 是通过使用描述对象和数据库之间的映射的元数据，将程序中的对象自动持久化到数据库中。"
                    }
                ]
            },
            "bbox": [
                146,
                732,
                727,
                745
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "ORM 解析过程:"
                    }
                ]
            },
            "bbox": [
                147,
                772,
                243,
                785
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "1、ORM 会将 Python 代码转成为 SQL 语句。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "2、SQL 语句通过 pymysql 传送到数据库服务端。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "3、在数据库中执行 SQL 语句并将结果返回。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                134,
                791,
                423,
                865
            ]
        }
    ],
    [
        {
            "type": "image",
            "content": {
                "image_source": {
                    "path": "images/89ff050f91c03b4570c077c1d5a0b35eba5235ff5bcb76f7b6a8328a7ce6d1c7.jpg"
                },
                "image_caption": [],
                "image_footnote": []
            },
            "bbox": [
                157,
                91,
                963,
                218
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "ORM 对应关系表："
                    }
                ]
            },
            "bbox": [
                147,
                237,
                257,
                249
            ]
        },
        {
            "type": "image",
            "content": {
                "image_source": {
                    "path": "images/e3b1faa6363d2686aa3e435194c96d28a466d037563692d969fb0f4eb9f90257.jpg"
                },
                "image_caption": [],
                "image_footnote": []
            },
            "bbox": [
                193,
                293,
                793,
                495
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "数据库配置"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                558,
                218,
                570
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "ORM 无法操作到数据库级别，只能操作到数据表"
                    }
                ]
            },
            "bbox": [
                146,
                589,
                438,
                602
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "我们在项目的 settings.py 文件中找到 DATABASES 配置项，将其信息修改为："
                    }
                ]
            },
            "bbox": [
                146,
                651,
                584,
                664
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/HelloWorld/settings.py: 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                682,
                415,
                695
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "DATABASES "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "{ 'default': { 'ENGINE': 'django.db.backends.mysql', # 数 据 库 引 擎 'NAME': 'runoob', # 数 据 库 名 称 'HOST':'127.0.0.1', # 数据库地址，本机 ip 地址 127.0.0.1 'PORT': 3306, # 端口 'USER': 'root', # 数据库用户名 'PASSWORD': '123456',# 数据库密码 } }"
                    }
                ]
            },
            "bbox": [
                144,
                713,
                848,
                764
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "上面包含数据库名称和用户的信息，它们与 MySQL 中对应数据库和用户的设置相同。Django 根据这一设置，与 MySQL中相应的数据库和用户连接起来。"
                    }
                ]
            },
            "bbox": [
                144,
                781,
                848,
                812
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "接下来，告诉 Django 使用 pymysql 模块连接 mysql 数据库："
                    }
                ]
            },
            "bbox": [
                146,
                831,
                490,
                844
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                862,
                179,
                873
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 在与 settings.py 同级目录下的 __init__.py 中引入模块和进行配置"
                    }
                ]
            },
            "bbox": [
                144,
                93,
                534,
                109
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "import pymysql"
                    }
                ]
            },
            "bbox": [
                146,
                112,
                238,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "pymysql.install_as_MySQLdb() "
                    }
                ]
            },
            "bbox": [
                146,
                131,
                317,
                143
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "定义模型"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                218,
                275,
                243
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "创建 APP"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                261,
                255,
                280
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 规定，如果要使用模型，必须要创建一个 app。我们使用以下命令创建一个 TestModel 的 app:"
                    }
                ]
            },
            "bbox": [
                144,
                294,
                751,
                307
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "django-admin startapp TestModel "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                146,
                323,
                386,
                336
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "# models.py from django.db import models class Test(model.Model): name = models.CharField(max_length=20) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                146,
                353,
                705,
                384
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "以上的类名代表了数据库表名，且继承了models.Model，类里面的字段代表数据表中的字段(name)，数据类型则由CharField（相当于 varchar）、DateField（相当于 datetime）， max_length 参数限定长度。"
                    }
                ]
            },
            "bbox": [
                144,
                390,
                830,
                423
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在命令行中运行："
                    }
                ]
            },
            "bbox": [
                146,
                428,
                250,
                439
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "$ python3 manage.py migrate # 创建表结构"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                146,
                457,
                458,
                469
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "$ python3 manage.py makemigrations TestModel # 让 Django 知道我们在我们的模型有一些变更"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                146,
                486,
                776,
                499
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "$ python3 manage.py migrate TestModel # 创建表结构"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                146,
                516,
                532,
                529
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "看到几行 \"Creating table…\" 的字样，你的数据表就创建好了。"
                    }
                ]
            },
            "bbox": [
                144,
                543,
                608,
                558
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Creating tables ... "
                    }
                ]
            },
            "bbox": [
                146,
                563,
                275,
                576
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": []
            },
            "bbox": [
                146,
                586,
                176,
                594
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Creating table TestModel_test #我们自定义的表"
                    }
                ]
            },
            "bbox": [
                144,
                600,
                505,
                614
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": []
            },
            "bbox": [
                146,
                624,
                176,
                631
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "表名组成结构为：应用名_类名（如：TestModel_test）。"
                    }
                ]
            },
            "bbox": [
                144,
                636,
                576,
                652
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意：尽管我们没有在 models 给表设置主键，但是 Django 会自动添加一个 id 作为主键。"
                    }
                ]
            },
            "bbox": [
                144,
                653,
                826,
                670
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "添加数据"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                673,
                221,
                688
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "添加数据需要先创建对象，然后再执行 save 函数，相当于SQL中的INSERT："
                    }
                ]
            },
            "bbox": [
                144,
                692,
                727,
                707
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "- - coding: utf-8 - "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                146,
                709,
                300,
                724
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from django.http import HttpResponse "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                146,
                747,
                428,
                762
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from TestModel.models import Test "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                146,
                785,
                406,
                799
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "# 数据库操作"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                822,
                252,
                837
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def testdb(request): "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                146,
                841,
                292,
                854
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "test1 = Test(name='runoob') "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                161,
                859,
                366,
                873
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "test1.save() "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                163,
                877,
                248,
                891
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(\"<p>数据添加成功！</p>\")"
                    }
                ]
            },
            "bbox": [
                164,
                93,
                524,
                109
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "更新数据"
                    }
                ],
                "level": 1
            },
            "bbox": [
                149,
                112,
                221,
                127
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "修改数据可以使用 save() 或 update():"
                    }
                ]
            },
            "bbox": [
                147,
                130,
                428,
                145
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "- -coding: utf-8 - "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                149,
                300,
                162
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from django.http import HttpResponse "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                186,
                428,
                200
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from TestModel.models import Test "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                223,
                406,
                237
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [
                    {
                        "type": "text",
                        "content": "# 数据库操作"
                    }
                ],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def testdb(request): "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                279,
                292,
                293
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 修改其中一个 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\mathrm { i } { \\mathsf { d } } { = } 1"
                    },
                    {
                        "type": "text",
                        "content": "的 name 字段，再 save，相当于 SQL 中的 UPDATE"
                    }
                ]
            },
            "bbox": [
                163,
                297,
                695,
                312
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "test1 = Test.objects.get(id=1) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                163,
                316,
                371,
                330
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "test1.name = 'Google' "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                164,
                335,
                322,
                348
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "test1.save() "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                164,
                354,
                248,
                367
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "# 另外一种方式"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                164,
                390,
                285,
                405
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "Test.objects.filter(id=1).update(name='Google') "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                164,
                407,
                512,
                423
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "修改所有的列"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                164,
                445,
                285,
                460
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "Test.objects.all().update(name='Google') "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                164,
                464,
                468,
                479
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(\"/<p>修改成功</p>\")"
                    }
                ],
                "code_language": "lua"
            },
            "bbox": [
                164,
                501,
                470,
                517
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "删除数据"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                520,
                221,
                533
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "删除数据库中的对象只需调用该对象的delete()方法即可："
                    }
                ]
            },
            "bbox": [
                147,
                538,
                588,
                552
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 表单"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                588,
                359,
                619
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HTML表单是网站交互性的经典方式。 本章将介绍如何用Django对用户提交的表单数据进行处理。"
                    }
                ]
            },
            "bbox": [
                146,
                638,
                729,
                652
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "HTTP 请求"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                663,
                302,
                687
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HTTP协议以\"请求－回复\"的方式工作。客户发送请求时，可以在请求中附加数据。服务器通过解析请求，就可以获得客户传来的数据，并根据URL来提供特定的服务。"
                    }
                ]
            },
            "bbox": [
                146,
                697,
                843,
                728
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "GET 方法"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                746,
                257,
                765
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "用户提交了表单，服务器解析表单并回复"
                    }
                ]
            },
            "bbox": [
                147,
                781,
                468,
                796
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "我们在之前的项目中创建一个 search.py 文件，用于接收用户的请求："
                    }
                ]
            },
            "bbox": [
                146,
                801,
                557,
                814
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from django.http import HttpResponse "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                822,
                378,
                835
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from django.shortcuts import render "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                845,
                364,
                856
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "#表单 "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                866,
                189,
                876
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def search_form(request): "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                887,
                304,
                898
            ]
        }
    ],
    [
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "return render(request, 'search_form.html')  \n#接收请求数据  \ndef search(request):  \n    request_encoding='utf-8'  \n    if 'q' in request.GET and request.GET['q']:  \n        message = '你搜索的内容为: ' + request.GET['q']  \n    else:  \n        message = '你提交了空表单'  \n    return HttpResponse(message)  \n在模板目录templates中添加search_form.html表单：  \n/HelloWorld/template/search_form.html文件代码：  \n<!DOCTYPE html>  \n<html>  \n<head>  \n<meta charset=\"utf-8\">  \n<title>菜鸟教程(runob.com)</title>  \n</head>  \n<body>  \n<form action=\"/search/\" method=\"get\">  \n    <input type=\"text\" name=\"q\">  \n    <input type=\"submit\" value=\"搜索\">  \n</form>  \n</body>  \n</html>  \nurls.py规则修改为如下形式：  \n/HelloWorld/HelloWorld URLs.py文件代码：  \nfrom django.conf.urls import url  \nfrom . import views,testdb,search  \nurlpatterns = [url(r'^hello/$', views.runoob),url(r'^testdb/$', testdb.testdb),url(r'^search-form/$', search.search_form),url(r'^search/$', search.search),]"
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                91,
                468,
                858
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "POST 方法"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                873,
                263,
                894
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "上面我们使用了GET 方法，视图显示和请求处理分成两个函数处理。"
                    }
                ]
            },
            "bbox": [
                146,
                95,
                502,
                105
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "提交数据时更常用POST 方法。我们下面使用该方法，并用一个URL和处理函数，同时显示视图和处理请求。"
                    }
                ]
            },
            "bbox": [
                144,
                112,
                715,
                124
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "1. GET 方法实现（search.py）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                131,
                309,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "python "
                    }
                ]
            },
            "bbox": [
                147,
                151,
                189,
                162
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 两个独立的函数： 一个显示表单， 一个处理请求"
                    }
                ]
            },
            "bbox": [
                146,
                168,
                411,
                181
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def search_form(request): # 显示表单 "
                    }
                ]
            },
            "bbox": [
                147,
                187,
                359,
                199
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return render(request, 'search_form.html') "
                    }
                ]
            },
            "bbox": [
                159,
                206,
                396,
                218
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def search(request): # 处理请求"
                    }
                ]
            },
            "bbox": [
                147,
                243,
                327,
                255
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "if 'q' in request.GET and request.GET['q']: "
                    }
                ]
            },
            "bbox": [
                159,
                261,
                384,
                273
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "message "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "'你搜索的内容为: ' "
                    },
                    {
                        "type": "equation_inline",
                        "content": "^ +"
                    },
                    {
                        "type": "text",
                        "content": "request.GET['q'] "
                    }
                ]
            },
            "bbox": [
                171,
                280,
                431,
                292
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "else: "
                    }
                ]
            },
            "bbox": [
                159,
                299,
                189,
                309
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "message "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "'你提交了空表单' "
                    }
                ]
            },
            "bbox": [
                171,
                317,
                324,
                328
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(message)"
                    }
                ]
            },
            "bbox": [
                159,
                336,
                336,
                347
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "2. POST 方法实现（search2.py）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                355,
                322,
                367
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "python "
                    }
                ]
            },
            "bbox": [
                147,
                373,
                189,
                384
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 单个函数同时处理表单显示和请求处理"
                    }
                ]
            },
            "bbox": [
                147,
                391,
                364,
                401
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def search_post(request): "
                    }
                ]
            },
            "bbox": [
                147,
                410,
                290,
                420
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "equation_inline",
                        "content": "\\mathsf { c t x } = \\left\\{ \\right\\}"
                    }
                ]
            },
            "bbox": [
                159,
                429,
                201,
                439
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "if request.POST: # 如果是POST 请求 （表单提交）"
                    }
                ]
            },
            "bbox": [
                159,
                447,
                423,
                458
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "ctx['rlt'] "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "request.POST['q'] "
                    }
                ]
            },
            "bbox": [
                171,
                466,
                322,
                476
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return render(request, \"post.html\", ctx) # 总是返回模板"
                    }
                ]
            },
            "bbox": [
                159,
                483,
                468,
                495
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "何时用 GET？何时用 POST？"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                502,
                297,
                514
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "适合 GET 的情况："
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                521,
                243,
                532
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "搜索功能（用户可能想收藏或分享搜索结果URL）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 筛选和排序（参数在URL中便于分享）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "幂等操作（不改变服务器状态的操作）"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                539,
                463,
                588
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "适合 POST 的情况："
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                595,
                250,
                606
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "登录/注册（包含敏感信息）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 表单提交（创建新数据）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 任何会改变服务器状态的操作"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 大量数据提交 "
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                614,
                364,
                680
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "最佳实践总结"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                688,
                221,
                699
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "1. GET 完全可以用单函数处理显示和处理逻辑"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "2. 原代码设计是过时的模式，现代 Django 开发不推荐这样分离"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "3. 选择GET 还是 POST 取决于具体场景，而不是技术限制"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "4. 单函数模式更简洁、更易维护"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                706,
                526,
                772
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Request 对象"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                808,
                294,
                828
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "每个视图函数的第一个参数是一个HttpRequest 对象，就像下面这个runoob() 函数:"
                    }
                ]
            },
            "bbox": [
                146,
                841,
                579,
                854
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.http import HttpResponse "
                    }
                ]
            },
            "bbox": [
                147,
                860,
                349,
                872
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "QueryDict 对象"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                102,
                315,
                122
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 HttpRequest 对象中, GET 和 POST 属性是 django.http.QueryDict 类的实例。QueryDict类似字典的自定义类，用来处理单键对应多值的情况。QueryDict实现所有标准的词典方法。还包括一些特有的方法："
                    }
                ]
            },
            "bbox": [
                144,
                135,
                554,
                184
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def runoob(request): return HttpResponse(\"Hello world\")"
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                146,
                209,
                347,
                239
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 视图"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                259,
                386,
                293
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "视图层 "
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                312,
                240,
                335
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "一个视图函数，简称视图，是一个简单的Python 函数，它接受Web 请求并且返回Web 响应。"
                    }
                ]
            },
            "bbox": [
                146,
                347,
                635,
                359
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "响应可以是一个HTML 页面、一个404 错误页面、重定向页面、XML 文档、或者一张图片..."
                    }
                ]
            },
            "bbox": [
                146,
                366,
                626,
                376
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "无论视图本身包含什么逻辑，都要返回响应。代码写在哪里都可以，只要在Python 目录下面，一般放在项目的views.py 文件中。"
                    }
                ]
            },
            "bbox": [
                146,
                384,
                811,
                395
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "每个视图函数都负责返回一个HttpResponse 对象，对象中包含生成的响应。"
                    }
                ]
            },
            "bbox": [
                146,
                403,
                542,
                414
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "视图层中有两个重要的对象：请求对象(request)与响应对象(HttpResponse)。"
                    }
                ]
            },
            "bbox": [
                146,
                420,
                544,
                432
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "请求对象: HttpRequest 对象（简称 request 对象）"
                    }
                ]
            },
            "bbox": [
                146,
                439,
                413,
                451
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "以下介绍几个常用的request 属性。"
                    }
                ]
            },
            "bbox": [
                146,
                458,
                329,
                470
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "1、GET"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                488,
                228,
                504
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "数据类型是QueryDict，一个类似于字典的对象，包含HTTP GET 的所有参数。"
                    }
                ]
            },
            "bbox": [
                146,
                520,
                556,
                531
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "有相同的键，就把所有的值放到对应的列表里。"
                    }
                ]
            },
            "bbox": [
                146,
                539,
                391,
                549
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "取值格式：对象.方法。"
                    }
                ]
            },
            "bbox": [
                146,
                557,
                265,
                568
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "get()：返回字符串，如果该键对应有多个值，取出该键的最后一个值。"
                    }
                ]
            },
            "bbox": [
                146,
                576,
                509,
                587
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ]
            },
            "bbox": [
                147,
                595,
                174,
                605
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def runoob(request):\n    name = request.GET.get(\"name\")\n    return HttpResponse('姓名：{}''.format(name)) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                146,
                613,
                405,
                662
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "2、POST"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                678,
                245,
                695
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "数据类型是QueryDict，一个类似于字典的对象，包含HTTP POST 的所有参数。"
                    }
                ]
            },
            "bbox": [
                146,
                711,
                563,
                722
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "常用于form 表单，form 表单里的标签name 属性对应参数的键，value 属性对应参数的值。"
                    }
                ]
            },
            "bbox": [
                146,
                730,
                618,
                741
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "取值格式：对象.方法。"
                    }
                ]
            },
            "bbox": [
                146,
                747,
                267,
                759
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "get()：返回字符串，如果该键对应有多个值，取出该键的最后一个值。"
                    }
                ]
            },
            "bbox": [
                146,
                766,
                509,
                778
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ]
            },
            "bbox": [
                147,
                785,
                174,
                796
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def runoob(request):\n    name = request.POST.get(\"name\")\n    return HttpResponse('姓名：{}'.format(name)) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                146,
                804,
                405,
                853
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "3、body "
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                870,
                243,
                889
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "数据类型是二进制字节流，是原生请求体里的参数内容，在HTTP 中用于POST，因为GET 没有请求体。"
                    }
                ]
            },
            "bbox": [
                144,
                95,
                690,
                107
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在HTTP 中不常用，而在处理非HTTP 形式的报文时非常有用，例如：二进制图片、XML、Json 等。"
                    }
                ]
            },
            "bbox": [
                144,
                112,
                670,
                124
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                131,
                176,
                143
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "def runoob(request): name  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " request.body print(name) return HttpResponse(\"菜鸟教程\") "
                    }
                ]
            },
            "bbox": [
                147,
                151,
                339,
                219
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "获取URL 中的路径部分，数据类型是字符串。"
                    }
                ]
            },
            "bbox": [
                146,
                224,
                384,
                236
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                243,
                176,
                255
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "def runoob(request): name  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " request.path print(name) return HttpResponse(\"菜鸟教程\") "
                    }
                ]
            },
            "bbox": [
                147,
                262,
                336,
                330
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "4、path "
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                346,
                240,
                365
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "获取URL 中的路径部分，数据类型是字符串。"
                    }
                ]
            },
            "bbox": [
                146,
                379,
                384,
                391
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                397,
                176,
                409
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "def runoob(request): name  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " request.path print(name) return HttpResponse(\"菜鸟教程\") "
                    }
                ]
            },
            "bbox": [
                147,
                414,
                337,
                483
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "5、method "
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                519,
                278,
                536
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "获取当前请求的方式，数据类型是字符串，且结果为大写。"
                    }
                ]
            },
            "bbox": [
                146,
                551,
                450,
                563
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                570,
                176,
                581
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "def runoob(request): name  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " request.method print(name) return HttpResponse(\"菜鸟教程\") "
                    }
                ]
            },
            "bbox": [
                147,
                588,
                339,
                656
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "响应对象：HttpResponse 对象"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                670,
                584,
                696
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "响应对象主要有三种形式：HttpResponse()、render()、redirect()。"
                    }
                ]
            },
            "bbox": [
                146,
                705,
                492,
                718
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HttpResponse(): 返回文本，参数为字符串，字符串中写文本内容。如果参数为字符串里含有html 标签，也可以渲染。"
                    }
                ]
            },
            "bbox": [
                144,
                724,
                759,
                736
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "ender(): 返回文本，第一个参数为 request，第二个参数为字符串（页面名称），第三个参数为字典（可选参数，向页面传递的参数："
                    }
                ]
            },
            "bbox": [
                144,
                741,
                840,
                753
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "键为页面参数名，值为views参数名）。"
                    }
                ]
            },
            "bbox": [
                146,
                760,
                354,
                772
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                778,
                176,
                791
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def runoob(request):\n    name = \"菜鸟教程\"\n    return render(request, \"runoob.html\", {\"name\": name}) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                797,
                438,
                847
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "redirect()：重定向，跳转新页面。参数为字符串，字符串中填写页面路径。一般用于form 表单提交后，跳转到新页面。"
                    }
                ]
            },
            "bbox": [
                146,
                854,
                766,
                866
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                872,
                176,
                884
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def runoob(request): "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                891,
                260,
                903
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return redirect(\"/index/\") "
                    }
                ]
            },
            "bbox": [
                159,
                96,
                290,
                105
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "render 和 redirect 是在 HttpResponse 的基础上进行了封装："
                    }
                ]
            },
            "bbox": [
                146,
                112,
                460,
                124
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "render：底层返回的也是 HttpResponse 对象"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "redirect：底层继承的是 HttpResponse 对象"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                131,
                443,
                162
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 路由"
                    }
                ],
                "level": 1
            },
            "bbox": [
                149,
                183,
                384,
                217
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "路由简单的来说就是根据用户请求的URL 链接来判断对应的处理程序，并返回处理结果，也就是URL 与Django 的视图建立映射关系。"
                    }
                ]
            },
            "bbox": [
                144,
                230,
                845,
                243
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 路由在 urls.py 配置，urls.py 中的每一条配置对应相应的处理方法。"
                    }
                ]
            },
            "bbox": [
                146,
                249,
                534,
                261
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Path 设置 "
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                275,
                287,
                298
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 2.2.x 之后的版本"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                311,
                282,
                322
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "path：用于普通路径，不需要自己手动添加正则首位限制符号，底层已经添加。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". re_path：用于正则路径，需要自己手动添加正则首位限制符号。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                329,
                616,
                359
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ]
            },
            "bbox": [
                146,
                366,
                174,
                376
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from django.url import re_path # 用re_path 需要引入\nurlpatterns = [\n    path('admin/', admin.site URLs),\n    path('index/', views.index), # 普通路径\n    re_path(r'^articles/[0-9]{4}]/$', views_articles), # 正则路径 "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                144,
                384,
                465,
                489
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "正则路径中的分组"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                502,
                394,
                526
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "正则路径中的无名分组"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                544,
                378,
                563
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "无名分组按位置传参，一一对应。"
                    }
                ]
            },
            "bbox": [
                146,
                577,
                322,
                590
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "views 中除了request，其他形参的数量要与urls 中的分组数量一致。"
                    }
                ]
            },
            "bbox": [
                146,
                596,
                502,
                609
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "urls.py "
                    }
                ]
            },
            "bbox": [
                146,
                615,
                189,
                627
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "urlpatterns  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " [ path('admin'/,admin.site URLs), re_path(\"^index/([0-9]{4})/$\",views.index), ] views.py from django.shortcuts import HttpResponse "
                    }
                ]
            },
            "bbox": [
                146,
                634,
                384,
                739
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def index(request, year):\n    print(year) # 一个形参代表路径中一个分组的内容，按顺序匹配\n    return HttpResponse('菜鸟教程')"
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                146,
                764,
                494,
                813
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "正则路径中的有名分组"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                828,
                379,
                847
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "语法："
                    }
                ]
            },
            "bbox": [
                147,
                862,
                181,
                873
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "(?P<组名>正则表达式) "
                    }
                ]
            },
            "bbox": [
                147,
                881,
                270,
                892
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "有名分组按关键字传参，与位置顺序无关。"
                    }
                ]
            },
            "bbox": [
                144,
                95,
                366,
                105
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "views 中除了request，其他形参的数量要与urls 中的分组数量一致，并且views 中的形参名称要与urls 中的组名对应。"
                    }
                ]
            },
            "bbox": [
                144,
                112,
                764,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "urls.py "
                    }
                ]
            },
            "bbox": [
                146,
                131,
                189,
                143
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "urlpatterns  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " [path('admin／',admin.site.urls),re_path(\"^index/(?P[0-9]{4})/(?P[0-9]{2})/\\$\"，views.index),]views.pyfrom django.shortcuts import HttpResponsedef index(request, year, month):print(year,month)#一个形参代表路径中一个分组的内容,return HttpResponse('菜鸟教程') "
                    }
                ]
            },
            "bbox": [
                146,
                151,
                463,
                312
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "路由分发(include) "
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                326,
                339,
                346
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "存在问题：Django 项目里多个app目录共用一个urls 容易造成混淆，后期维护也不方便。"
                    }
                ]
            },
            "bbox": [
                144,
                360,
                608,
                372
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "解决：使用路由分发（include），让每个app目录都单独拥有自己的urls。"
                    }
                ]
            },
            "bbox": [
                144,
                379,
                532,
                390
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "步骤："
                    }
                ]
            },
            "bbox": [
                146,
                397,
                179,
                407
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "1、在每个 app 目录里都创建一个 urls.py 文件。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "2、在项目名称目录下的urls 文件里，统一将路径分发给各个app 目录。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                416,
                578,
                445
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ]
            },
            "bbox": [
                146,
                451,
                174,
                464
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import admin "
                    }
                ]
            },
            "bbox": [
                144,
                470,
                329,
                482
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from django.url import path, include # 从 django.url 引入 include  \nurlpatterns = [  \n    path('admin/', admin.site URLs),  \n    path(\"app01/\", include(\"app01 URLs\")),  \n    path(\"app02/\", include(\"app02 URLs\")), "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                144,
                489,
                495,
                575
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "反向解析"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                608,
                272,
                631
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "随着功能的增加，路由层的url 发生变化，就需要去更改对应的视图层和模板层的url，非常麻烦，不便维护。"
                    }
                ]
            },
            "bbox": [
                144,
                644,
                707,
                655
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "这时我们可以利用反向解析，当路由层url 发生改变，在视图层和模板层动态反向解析出更改后的url，免去修改的操作。"
                    }
                ]
            },
            "bbox": [
                144,
                662,
                766,
                673
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "反向解析一般用在模板中的超链接及视图中的重定向。"
                    }
                ]
            },
            "bbox": [
                146,
                681,
                426,
                692
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "普通路径"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                709,
                240,
                727
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在urls.py 中给路由起别名，name=\"路由别名\"。"
                    }
                ]
            },
            "bbox": [
                144,
                741,
                396,
                753
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "path(\"login1/\", views.login, name=\"login\") "
                    }
                ]
            },
            "bbox": [
                146,
                760,
                364,
                772
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 views.py 中，从 django.urls 中引入 reverse，利用 reverse(\"路由别名\") 反向解析:"
                    }
                ]
            },
            "bbox": [
                146,
                778,
                588,
                791
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return redirect(reverse(\"login\")) "
                    }
                ]
            },
            "bbox": [
                146,
                797,
                312,
                809
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在模板 templates 中的 HTML 文件中，利用 {% url \"路由别名\" %} 反向解析。"
                    }
                ]
            },
            "bbox": [
                144,
                816,
                544,
                828
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "<form action=\"{% url 'login' %}\" method=\"post\"> "
                    }
                ]
            },
            "bbox": [
                146,
                835,
                400,
                846
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "正则路径（无名分组）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                863,
                364,
                882
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 urls.py 中给路由起别名，name=\"路由别名\"。"
                    }
                ]
            },
            "bbox": [
                144,
                95,
                400,
                107
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "re_path(r\"^login/([0-9]{2})/$\", views.login, name=\"login\") "
                    }
                ]
            },
            "bbox": [
                144,
                112,
                440,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 views.py 中，从 django.urls 中引入 reverse，利用 reverse(\"路由别名\"，args=(符合正则匹配的参数,)) 反向解析。"
                    }
                ]
            },
            "bbox": [
                144,
                131,
                751,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return redirect(reverse(\"login\",args=(10,))) "
                    }
                ]
            },
            "bbox": [
                144,
                151,
                369,
                162
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在模板 templates 中的 HTML 文件中利用 {% url \"路由别名\" 符合正则匹配的参数 %} 反向解析。"
                    }
                ]
            },
            "bbox": [
                144,
                168,
                642,
                181
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "<form action=\"{% url 'login' 10 %}\" method=\"post\"> "
                    }
                ]
            },
            "bbox": [
                144,
                187,
                416,
                199
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "正则路径（有名分组）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                215,
                366,
                234
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 urls.py 中给路由起别名，name=\"路由别名\"。"
                    }
                ]
            },
            "bbox": [
                144,
                249,
                400,
                261
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "re_path(r\"^login/(?P<year>[0-9]{4})/$\", views.login, name=\"login\") "
                    }
                ]
            },
            "bbox": [
                144,
                267,
                490,
                279
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 views.py 中，从 django.urls 中引入 reverse，利用 reverse(\"路由别名\"，kwargs={\"分组名\":符合正则匹配的参数}) 反向解析。"
                    }
                ]
            },
            "bbox": [
                144,
                286,
                813,
                298
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return redirect(reverse(\"login\",kwargs={\"year\":3333})) "
                    }
                ]
            },
            "bbox": [
                146,
                304,
                428,
                316
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在模板 templates 中的 HTML 文件中，利用{% url \"路由别名\" 分组名=符合正则匹配的参数 %} 反向解析。"
                    }
                ]
            },
            "bbox": [
                144,
                323,
                695,
                335
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "<form action=\"{% url 'login' year=3333 %}\" method=\"post\"> "
                    }
                ]
            },
            "bbox": [
                144,
                342,
                458,
                353
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "命名空间"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                386,
                273,
                409
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "命名空间（英语：Namespace）是表示标识符的可见范围。"
                    }
                ]
            },
            "bbox": [
                144,
                420,
                455,
                432
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "一个标识符可在多个命名空间中定义，它在不同命名空间中的含义是互不相干的。"
                    }
                ]
            },
            "bbox": [
                144,
                439,
                569,
                451
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "一个新的命名空间中可定义任何标识符，它们不会与任何重复的标识符发生冲突，因为重复的定义都处于其它命名空间中。"
                    }
                ]
            },
            "bbox": [
                144,
                458,
                779,
                469
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "存在问题：路由别名 name 没有作用域，Django 在反向解析 URL 时，会在项目全局顺序搜索，当查找到第一个路由别名 name 指定"
                    }
                ]
            },
            "bbox": [
                144,
                476,
                848,
                488
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "URL 时，立即返回。当在不同的 app 目录下的 urls 中定义相同的路由别名 name 时，可能会导致 URL 反向解析错误。"
                    }
                ]
            },
            "bbox": [
                144,
                495,
                756,
                507
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "解决：使用命名空间。"
                    }
                ]
            },
            "bbox": [
                144,
                514,
                262,
                526
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "普通路径"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                533,
                200,
                544
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "定义命名空间（include 里面是一个元组）格式如下："
                    }
                ]
            },
            "bbox": [
                144,
                551,
                420,
                562
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "include((\"app 名称：urls\"，\"app 名称\"))"
                    }
                ]
            },
            "bbox": [
                144,
                570,
                354,
                582
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "实例："
                    }
                ]
            },
            "bbox": [
                146,
                588,
                179,
                599
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "path(\"app01/\", include((\"app01.urls\",\"app01\"))) "
                    }
                ]
            },
            "bbox": [
                144,
                606,
                393,
                618
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "path(\"app02/\", include((\"app02.urls\",\"app02\"))) "
                    }
                ]
            },
            "bbox": [
                144,
                625,
                393,
                637
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 app01/urls.py 中起相同的路由别名。"
                    }
                ]
            },
            "bbox": [
                144,
                644,
                349,
                655
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "path(\"login/\", views.login, name=\"login\") "
                    }
                ]
            },
            "bbox": [
                144,
                662,
                357,
                674
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在views.py 中使用名称空间，语法格式如下："
                    }
                ]
            },
            "bbox": [
                144,
                681,
                383,
                692
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "reverse(\"app 名称：路由别名\")"
                    }
                ]
            },
            "bbox": [
                144,
                699,
                310,
                711
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "实例："
                    }
                ]
            },
            "bbox": [
                146,
                718,
                179,
                728
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return redirect(reverse(\"app01:login\") "
                    }
                ]
            },
            "bbox": [
                144,
                737,
                344,
                747
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django Admin 管理工具"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                768,
                610,
                802
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 提供了基于web 的管理工具。"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                822,
                532,
                843
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 自动管理工具是 django.contrib 的一部分。你可以在项目的 settings.py 中的 INSTALLED_APPS 看到它："
                    }
                ]
            },
            "bbox": [
                144,
                856,
                727,
                869
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "/HelloWorld/HelloWorld/settings.py 文件代码："
                    }
                ]
            },
            "bbox": [
                144,
                875,
                386,
                887
            ]
        }
    ],
    [
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "INSTALLED_APPS = ( "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                95,
                270,
                105
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib_admin', "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                161,
                114,
                280,
                124
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.auth', "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                161,
                131,
                272,
                143
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.contenttypes', "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                161,
                151,
                315,
                162
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.authenticated', "
                    }
                ],
                "code_language": "javascript"
            },
            "bbox": [
                161,
                168,
                295,
                180
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.messages', "
                    }
                ],
                "code_language": "javascript"
            },
            "bbox": [
                161,
                187,
                302,
                199
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib(staticfiles',"
                    }
                ],
                "code_language": "javascript"
            },
            "bbox": [
                161,
                206,
                297,
                217
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": ")django.contrib 是一套庞大的功能集，它是 Django 基本代码的组成部分。"
                    }
                ]
            },
            "bbox": [
                146,
                224,
                524,
                236
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "激活管理工具"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                252,
                287,
                271
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "通常我们在生成项目时会在urls.py 中自动设置好，我们只需去掉注释即可。"
                    }
                ]
            },
            "bbox": [
                146,
                286,
                537,
                298
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "配置项如下所示："
                    }
                ]
            },
            "bbox": [
                147,
                304,
                238,
                316
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "/HelloWorld/HelloWorld/url.py文件代码："
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                146,
                323,
                366,
                335
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "urls.py "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                342,
                196,
                353
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from django.conf.urls import url "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                360,
                312,
                370
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import admin "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                378,
                322,
                390
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "urlpatterns  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " [ "
                    }
                ]
            },
            "bbox": [
                147,
                397,
                223,
                409
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "url(r'^admin\"', admin.site.url), "
                    }
                ],
                "code_language": "javascript"
            },
            "bbox": [
                161,
                414,
                319,
                426
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "] "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                435,
                156,
                445
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "当这一切都配置好后，Django 管理工具就可以运行了。"
                    }
                ]
            },
            "bbox": [
                147,
                451,
                431,
                464
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "你可以通过命令 python manage.py createsuperuser 来创建超级用户，如下所示："
                    }
                ]
            },
            "bbox": [
                146,
                470,
                584,
                483
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "python manage.py createsuperuser "
                    }
                ],
                "code_language": "batch"
            },
            "bbox": [
                147,
                489,
                347,
                502
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "Username (leave blank to use 'root'): admin "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                508,
                376,
                520
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "Email address: admin@runoob.com "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                527,
                337,
                538
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "Password: "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                546,
                205,
                556
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "Password (again): "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                564,
                245,
                576
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "Superuser created successfully. "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                582,
                317,
                594
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "[root@solar HelloWorld]# "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                601,
                282,
                613
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "复杂模型"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                629,
                242,
                646
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "管理页面的功能强大，完全有能力处理更加复杂的数据模型。"
                    }
                ]
            },
            "bbox": [
                146,
                662,
                462,
                674
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "django-admin.py startproject app01 "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                681,
                336,
                693
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "接下来在 settings.py 中找到 INSTALLED_APPS 这一项，如下："
                    }
                ]
            },
            "bbox": [
                147,
                699,
                478,
                711
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "INSTALLED_APPS = ( "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                718,
                270,
                728
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib_admin', "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                161,
                737,
                280,
                747
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.auth', "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                161,
                755,
                272,
                766
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.contenttypes', "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                161,
                772,
                315,
                785
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contribsessions', "
                    }
                ],
                "code_language": "javascript"
            },
            "bbox": [
                161,
                791,
                295,
                804
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib.messages', "
                    }
                ],
                "code_language": "javascript"
            },
            "bbox": [
                161,
                810,
                302,
                822
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'django.contrib(staticfiles',"
                    }
                ],
                "code_language": "javascript"
            },
            "bbox": [
                161,
                829,
                297,
                840
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "'testmodel', # 添加此项 "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                161,
                847,
                329,
                859
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "）"
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                147,
                866,
                156,
                878
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "建表"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                101,
                200,
                120
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "先在 TestModel/models.py 中增加一个更复杂的数据模型："
                    }
                ]
            },
            "bbox": [
                147,
                162,
                450,
                175
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/TestModel/models.py: 文件代码："
                    }
                ]
            },
            "bbox": [
                147,
                181,
                381,
                193
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.db import models "
                    }
                ]
            },
            "bbox": [
                147,
                199,
                307,
                212
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# Create your models here. "
                    }
                ]
            },
            "bbox": [
                147,
                237,
                295,
                249
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "class Test(models.Model): "
                    }
                ]
            },
            "bbox": [
                147,
                255,
                287,
                267
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "name = models.CharField(max_length=20) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                161,
                273,
                388,
                286
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "class Contact(models.Model): "
                    }
                ]
            },
            "bbox": [
                147,
                311,
                307,
                323
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "name  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " models.CharField(max_length=200) "
                    }
                ]
            },
            "bbox": [
                161,
                329,
                401,
                341
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "age  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " models.IntegerField(default=0) "
                    }
                ]
            },
            "bbox": [
                161,
                348,
                366,
                360
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "email = models.EmailField() "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                161,
                367,
                312,
                378
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def __unicode__(self): "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                161,
                385,
                280,
                397
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "return self.name "
                    }
                ],
                "code_language": "lua"
            },
            "bbox": [
                173,
                404,
                263,
                414
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "class Tag(models.Model): "
                    }
                ]
            },
            "bbox": [
                147,
                439,
                285,
                451
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "contact = models.FireignKey(Contact, on_delete=models.CASCADE,) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                161,
                458,
                531,
                470
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "name  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " models.CharField(max_length=50) "
                    }
                ]
            },
            "bbox": [
                161,
                478,
                396,
                489
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "def __unicode__(self): "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                161,
                495,
                280,
                508
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "return self.name "
                    }
                ],
                "code_language": "lua"
            },
            "bbox": [
                173,
                514,
                263,
                525
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "这里有两个表。Tag 以 Contact 为外部键。一个 Contact 可以对应多个 Tag。"
                    }
                ]
            },
            "bbox": [
                147,
                533,
                539,
                546
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "我们还可以看到许多在之前没有见过的属性类型，比如 IntegerField 用于存储整数。"
                    }
                ]
            },
            "bbox": [
                146,
                570,
                578,
                583
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "用 django 创建表"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                611,
                337,
                633
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "$ python manage.py migrate # 创建表结构"
                    }
                ]
            },
            "bbox": [
                146,
                674,
                379,
                686
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "python manage.py makemigrations testmodel 让模型知道我们的表有变更"
                    }
                ]
            },
            "bbox": [
                146,
                692,
                536,
                703
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "python manage.py migrate TestModel 创建表结构"
                    }
                ]
            },
            "bbox": [
                147,
                709,
                408,
                722
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "接下来我们在 app01 项目里添加 views.py 和 models.py 文件，app01 项目目录结构："
                    }
                ]
            },
            "bbox": [
                146,
                728,
                586,
                741
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "app01 "
                    }
                ]
            },
            "bbox": [
                147,
                747,
                184,
                759
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "|-- app01 "
                    }
                ]
            },
            "bbox": [
                147,
                766,
                196,
                777
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "| |-- __init__.py"
                    }
                ]
            },
            "bbox": [
                147,
                785,
                236,
                797
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "| |-- __pycache__"
                    }
                ]
            },
            "bbox": [
                147,
                803,
                248,
                815
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "| |-- asgi.py "
                    }
                ]
            },
            "bbox": [
                147,
                822,
                216,
                833
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "| |-- migrations "
                    }
                ]
            },
            "bbox": [
                147,
                840,
                233,
                852
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "| |-- models.py"
                    }
                ]
            },
            "bbox": [
                147,
                859,
                233,
                870
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "| |-- settings.py"
                    }
                ]
            },
            "bbox": [
                147,
                877,
                235,
                889
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "| |-- urls.py"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "| |-- views.py"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "| `-- wsgi.py"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                146,
                95,
                223,
                143
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "显示模型"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                192,
                245,
                211
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 TestModel/admin.py 注册多个模型并显示："
                    }
                ]
            },
            "bbox": [
                146,
                252,
                490,
                268
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/TestModel/admin.py: 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                290,
                376,
                302
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import admin "
                    }
                ]
            },
            "bbox": [
                146,
                309,
                322,
                319
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from TestModel.models import Test,Contact,Tag "
                    }
                ]
            },
            "bbox": [
                146,
                328,
                400,
                338
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# Register your models here. "
                    }
                ]
            },
            "bbox": [
                146,
                365,
                302,
                376
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "admin.site.register([Test, Contact, Tag]) "
                    }
                ]
            },
            "bbox": [
                146,
                382,
                354,
                395
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "每个栏也可以定义自己的格式。"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                424,
                465,
                444
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "修改 TestModel/admin.py 为："
                    }
                ]
            },
            "bbox": [
                146,
                486,
                302,
                498
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/TestModel/admin.py: 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                523,
                374,
                535
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import admin "
                    }
                ]
            },
            "bbox": [
                146,
                542,
                322,
                552
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from TestModel.models import Test,Contact,Tag "
                    }
                ]
            },
            "bbox": [
                146,
                560,
                400,
                571
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# Register your models here. "
                    }
                ]
            },
            "bbox": [
                146,
                596,
                302,
                608
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "class ContactAdmin(admin.ModelAdmin): "
                    }
                ]
            },
            "bbox": [
                146,
                615,
                366,
                627
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "fieldsets = (\n    ['Main', {\n        'fields': ('name', 'email'),\n    }],\n    ['Advance', {\n        'classes': ('collapse'), # CSS\n        'fields': ('age'), }\n    }]) "
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                146,
                634,
                341,
                793
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "admin.site.register(Contact, ContactAdmin) "
                    }
                ]
            },
            "bbox": [
                146,
                820,
                376,
                831
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "admin.site.register([Test, Tag]) "
                    }
                ]
            },
            "bbox": [
                146,
                838,
                309,
                848
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "上面的栏目分为了Main 和Advance 两部分。classes 说明它所在的部分的CSS 格式。这里让Advance 部分隐藏："
                    }
                ]
            },
            "bbox": [
                146,
                856,
                739,
                868
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "内联(Inline)显示"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                101,
                329,
                122
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "上面的Contact 是Tag 的外部键，所以有外部参考的关系。"
                    }
                ]
            },
            "bbox": [
                146,
                162,
                450,
                174
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "而在默认的页面显示中，将两者分离开来，无法体现出两者的从属关系。我们可以使用内联显示，让 Tag 附加在Contact 的编辑页面上显示。"
                    }
                ]
            },
            "bbox": [
                144,
                181,
                847,
                210
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "修改 TestModel/admin.py："
                    }
                ]
            },
            "bbox": [
                146,
                219,
                285,
                229
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/TestModel/admin.py: 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                237,
                386,
                248
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import admin "
                    }
                ]
            },
            "bbox": [
                146,
                255,
                322,
                265
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from TestModel.models import Test,Contact,Tag "
                    }
                ]
            },
            "bbox": [
                146,
                274,
                400,
                284
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# Register your models here. "
                    }
                ]
            },
            "bbox": [
                146,
                311,
                300,
                321
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "class TagInline(admin.TabularInline): "
                    }
                ]
            },
            "bbox": [
                146,
                329,
                339,
                338
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "model = Tag "
                    }
                ]
            },
            "bbox": [
                161,
                349,
                226,
                359
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "class ContactAdmin(admin.ModelAdmin): "
                    }
                ]
            },
            "bbox": [
                146,
                385,
                366,
                395
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "inlines "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "[TagInline] # Inline "
                    }
                ]
            },
            "bbox": [
                161,
                404,
                307,
                414
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "fieldsets = ( "
                    }
                ]
            },
            "bbox": [
                161,
                422,
                225,
                432
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "['Main',{ "
                    }
                ]
            },
            "bbox": [
                174,
                441,
                216,
                451
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "'fields':('name','email'), "
                    }
                ]
            },
            "bbox": [
                186,
                460,
                305,
                470
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "}], "
                    }
                ]
            },
            "bbox": [
                174,
                479,
                184,
                488
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "['Advance',{ "
                    }
                ]
            },
            "bbox": [
                174,
                495,
                236,
                506
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "'classes': ('collapse',), "
                    }
                ]
            },
            "bbox": [
                186,
                514,
                300,
                526
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "'fields': ('age',), "
                    }
                ]
            },
            "bbox": [
                188,
                533,
                267,
                544
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "}] "
                    }
                ]
            },
            "bbox": [
                174,
                552,
                184,
                562
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": ") "
                    }
                ]
            },
            "bbox": [
                157,
                589,
                168,
                599
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "admin.site.register(Contact, ContactAdmin) "
                    }
                ]
            },
            "bbox": [
                146,
                626,
                374,
                637
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "admin.site.register([Test]) "
                    }
                ]
            },
            "bbox": [
                147,
                645,
                282,
                655
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "自定义该页面的显示"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                686,
                363,
                705
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "比如在列表中显示更多的栏目，只需要在 ContactAdmin 中增加 list_display 属性:"
                    }
                ]
            },
            "bbox": [
                146,
                747,
                568,
                759
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/TestModel/admin.py: 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                785,
                374,
                795
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import admin "
                    }
                ]
            },
            "bbox": [
                146,
                804,
                322,
                813
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from TestModel.models import Test,Contact,Tag "
                    }
                ]
            },
            "bbox": [
                146,
                822,
                398,
                832
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# Register your models here. "
                    }
                ]
            },
            "bbox": [
                146,
                859,
                300,
                869
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "class TagInline(admin.TabularInline): "
                    }
                ]
            },
            "bbox": [
                146,
                877,
                339,
                888
            ]
        }
    ],
    [
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "model  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " Tag   \nclass ContactAdmin(admin.ModelAdmin): list_display  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\equiv"
                    },
                    {
                        "type": "text",
                        "content": " ('name','age'，'email')#list inlines  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " [TagInline] # Inline fieldsets  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " ( ['Main',{ 'fields':('name','email'), }], ['Advance',{ 'classes':('collapse'), 'fields':('age'), }]}   \n）   \nadmin.site.register(Contact,ContactAdmin)   \nadmin.site.register([Test]) "
                    }
                ]
            },
            "bbox": [
                147,
                93,
                374,
                423
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "搜索功能"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                451,
                247,
                470
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "search_fields 为该列表页增加搜索栏："
                    }
                ]
            },
            "bbox": [
                147,
                513,
                347,
                525
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "HelloWorld/TestModel/admin.py:文件代码：  \nfrom django.contrib import admin  \nfrom TestModel.models import Test,Contact,Tag"
                    }
                ],
                "code_language": "python"
            },
            "bbox": [
                147,
                550,
                400,
                600
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "# Register your models here.   \nclass TagInline(admin.TabularInline): model  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " Tag   \nclass ContactAdmin(admin.ModelAdmin): list_display  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\equiv"
                    },
                    {
                        "type": "text",
                        "content": " ('name','age'，'email') #list search_fields  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " ('name') inlines  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " [TagInline] # Inline fieldsets  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " ( ['Main',{ 'fields':('name','email'), }], ['Advance',{ 'classes':('collapse'), 'fields':('age'), "
                    }
                ]
            },
            "bbox": [
                147,
                623,
                371,
                895
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "}] "
                    }
                ]
            },
            "bbox": [
                174,
                96,
                184,
                105
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": ") "
                    }
                ]
            },
            "bbox": [
                161,
                131,
                168,
                142
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "admin.site.register(Contact, ContactAdmin) "
                    }
                ]
            },
            "bbox": [
                147,
                168,
                376,
                180
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "admin.site.register([Test]) "
                    }
                ]
            },
            "bbox": [
                147,
                187,
                282,
                198
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 django2.0 后，定义外键和一对一关系的时候需要加 on_delete 选项，此参数为了避免两个表里的数据不一致问题，不然会报错："
                    }
                ]
            },
            "bbox": [
                146,
                206,
                840,
                218
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "TypeError: __init__() missing 1 required positional argument: 'on_delete'。 "
                    }
                ]
            },
            "bbox": [
                147,
                225,
                561,
                236
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "owner=models.ForeignKey(UserProfile,on_delete=models.CASCADE) --在老版本这个参数（models.CASCADE）是默认值参数"
                    }
                ]
            },
            "bbox": [
                146,
                243,
                815,
                254
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "说明：on_delete 有 CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET() 五个可选择的值。"
                    }
                ]
            },
            "bbox": [
                146,
                262,
                677,
                273
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "CASCADE：此值设置，是级联删除。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". PROTECT：此值设置，是会报完整性错误。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". SET_NULL：此值设置，会把外键设置为null，前提是允许为null。 "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". SET_DEFAULT：此值设置，会把设置为外键的默认值。 "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "SET()：此值设置，会调用外面的值，可以是一个函数。一般情况下使用CASCADE 就可以了。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                280,
                700,
                366
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "如果你之前还未创建表结构，可使用以下命令创建："
                    }
                ]
            },
            "bbox": [
                147,
                373,
                416,
                384
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "$ python manage.py makemigrations TestModel # 让 Django 知道我们在我们的模型有一些变更"
                    }
                ]
            },
            "bbox": [
                146,
                391,
                648,
                403
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "$ python manage.py migrate TestModel # 创建表结构"
                    }
                ]
            },
            "bbox": [
                147,
                410,
                435,
                422
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "数据库添加"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                451,
                267,
                470
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "规则配置："
                    }
                ]
            },
            "bbox": [
                147,
                513,
                203,
                524
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "app01/urls.py: 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                550,
                280,
                561
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import admin "
                    }
                ]
            },
            "bbox": [
                147,
                568,
                322,
                579
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.urls import path "
                    }
                ]
            },
            "bbox": [
                147,
                587,
                297,
                598
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from . import views "
                    }
                ]
            },
            "bbox": [
                147,
                606,
                250,
                615
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "urlpatterns = [ "
                    }
                ]
            },
            "bbox": [
                147,
                643,
                223,
                653
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "path('add_book/', views.add_book), "
                    }
                ]
            },
            "bbox": [
                161,
                661,
                347,
                671
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "] "
                    }
                ]
            },
            "bbox": [
                147,
                681,
                156,
                690
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式一：模型类实例化对象"
                    }
                ]
            },
            "bbox": [
                147,
                697,
                292,
                709
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "需从 app 目录引入 models.py 文件："
                    }
                ]
            },
            "bbox": [
                147,
                734,
                334,
                747
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from app 目录 import models "
                    }
                ]
            },
            "bbox": [
                146,
                772,
                300,
                783
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "并且实例化对象后要执行 对象.save() 才能在数据库中新增成功。"
                    }
                ]
            },
            "bbox": [
                146,
                791,
                480,
                802
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "app01/views.py: 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                828,
                290,
                839
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.shortcuts import render,HttpResponse "
                    }
                ]
            },
            "bbox": [
                146,
                846,
                413,
                857
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from app01 import models "
                    }
                ]
            },
            "bbox": [
                147,
                865,
                287,
                876
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def add_book(request): "
                    }
                ]
            },
            "bbox": [
                147,
                883,
                272,
                895
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "book "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book(title "
                    },
                    {
                        "type": "equation_inline",
                        "content": "! = \""
                    },
                    {
                        "type": "text",
                        "content": "菜鸟教程\",price=300,publish=\"菜鸟出版社\",pub_date=\"2008-8-8\") "
                    }
                ]
            },
            "bbox": [
                156,
                93,
                640,
                105
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "book.save() "
                    }
                ]
            },
            "bbox": [
                159,
                114,
                225,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse( "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\" < p >"
                    },
                    {
                        "type": "text",
                        "content": "数据添加成功！ "
                    },
                    {
                        "type": "equation_inline",
                        "content": "< / { \\mathsf { p } } > \""
                    },
                    {
                        "type": "text",
                        "content": ")"
                    }
                ]
            },
            "bbox": [
                159,
                131,
                415,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式二：通过 ORM 提供的 objects 提供的方法create 来实现（推荐）"
                    }
                ]
            },
            "bbox": [
                147,
                149,
                505,
                161
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "app01/views.py: 文件代码："
                    }
                ]
            },
            "bbox": [
                147,
                187,
                290,
                199
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.shortcuts import render,HttpResponse "
                    }
                ]
            },
            "bbox": [
                147,
                206,
                413,
                217
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from app01 import models "
                    }
                ]
            },
            "bbox": [
                147,
                225,
                287,
                235
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def add_book(request): "
                    }
                ]
            },
            "bbox": [
                147,
                243,
                272,
                254
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.create(title=\"如来神掌\",price=200,publish=\"功夫出版社\",pub_date=\"2010-10-10\") "
                    }
                ]
            },
            "bbox": [
                159,
                262,
                739,
                273
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books, type(books)) # Book object (18) "
                    }
                ]
            },
            "bbox": [
                159,
                280,
                393,
                291
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(\"<p>数据添加成功！</p>\")"
                    }
                ]
            },
            "bbox": [
                159,
                299,
                413,
                310
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "查找"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                338,
                200,
                357
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "使用 all() 方法来查询所有内容。"
                    }
                ]
            },
            "bbox": [
                144,
                400,
                388,
                414
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的是 QuerySet 类型数据，类似于 list，里面放的是一个个模型类的对象，可用索引下标取出模型类的对象。"
                    }
                ]
            },
            "bbox": [
                144,
                418,
                847,
                451
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "（for I in books）"
                    }
                ]
            },
            "bbox": [
                159,
                456,
                268,
                470
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.all() "
                    }
                ]
            },
            "bbox": [
                159,
                476,
                339,
                487
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books,type(books)) # QuerySet 类型，类似于 list，访问 url 时数据显示在命令行窗口中。"
                    }
                ]
            },
            "bbox": [
                159,
                494,
                642,
                505
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "查询符合条件的数据。"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                535,
                371,
                555
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "filter() 方法"
                    }
                ]
            },
            "bbox": [
                146,
                598,
                208,
                608
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的是 QuerySet 类型数据，类似于 list，里面放的是满足条件的模型类的对象，可用索引下标取出模型类的对象。"
                    }
                ]
            },
            "bbox": [
                144,
                615,
                746,
                627
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "pk=3 的意思是主键 primary key=3，相当于 id=3。"
                    }
                ]
            },
            "bbox": [
                146,
                653,
                403,
                664
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "因为 id 在 pycharm 里有特殊含义，是看内存地址的内置函数 id()，因此用 pk。"
                    }
                ]
            },
            "bbox": [
                144,
                690,
                549,
                702
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.filter(pk=5) "
                    }
                ]
            },
            "bbox": [
                157,
                726,
                376,
                738
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books) "
                    }
                ]
            },
            "bbox": [
                159,
                746,
                226,
                756
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(\"//////////////////////////////////////\") "
                    }
                ]
            },
            "bbox": [
                159,
                764,
                327,
                775
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.filter(publish='菜鸟出版社', price=300) "
                    }
                ]
            },
            "bbox": [
                159,
                783,
                515,
                794
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books, type(books)) # QuerySet 类型，类似于 list。"
                    }
                ]
            },
            "bbox": [
                159,
                802,
                453,
                813
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "查询不符合条件的数据。"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                101,
                394,
                120
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "exclude() 方法"
                    }
                ]
            },
            "bbox": [
                144,
                162,
                226,
                174
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的是 QuerySet 类型数据，类似于 list，里面放的是不满足条件的模型类的对象，可用索引下标取出模型类的对象。"
                    }
                ]
            },
            "bbox": [
                144,
                181,
                757,
                193
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "books  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " models.Book.objectsexclude(pk=5) "
                    }
                ]
            },
            "bbox": [
                159,
                199,
                394,
                211
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books) "
                    }
                ]
            },
            "bbox": [
                159,
                218,
                226,
                229
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "print(\"|||||||||||||||||||||||||||||||||\") "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                159,
                237,
                327,
                248
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.exclude(publish='菜鸟出版社', price=300) "
                    }
                ]
            },
            "bbox": [
                159,
                255,
                534,
                267
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books, type(books)) # QuerySet 类型，类似于 list。"
                    }
                ]
            },
            "bbox": [
                159,
                274,
                455,
                286
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "get() 方法"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                315,
                260,
                336
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "用于查询符合条件的返回模型类的对象符合条件的对象只能为一个，如果符合筛选条件的对象超过了一个或者没有一个都会抛出错误。"
                    }
                ]
            },
            "bbox": [
                144,
                376,
                840,
                388
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "books  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " models.Book.objects.get(pk=5) "
                    }
                ]
            },
            "bbox": [
                159,
                395,
                371,
                407
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.get "
                    },
                    {
                        "type": "equation_inline",
                        "content": "{ \\tt p k } { = } 1 8"
                    },
                    {
                        "type": "text",
                        "content": ") # 报错，没有符合条件的对象"
                    }
                ]
            },
            "bbox": [
                159,
                414,
                534,
                425
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "books = models.Book.objects.get(price=200) # 报错，符合条件的对象超过一个 "
                    }
                ],
                "code_language": "txt"
            },
            "bbox": [
                159,
                432,
                576,
                444
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books, type(books)) # 模型类的对象 "
                    }
                ]
            },
            "bbox": [
                159,
                451,
                381,
                463
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "排序 "
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                492,
                198,
                511
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "order_by() "
                    }
                ]
            },
            "bbox": [
                144,
                554,
                205,
                565
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的是 QuerySet类型数据，类似于list，里面放的是排序后的模型类的对象，可用索引下标取出模型类的对象。"
                    }
                ]
            },
            "bbox": [
                144,
                571,
                732,
                583
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意："
                    }
                ]
            },
            "bbox": [
                146,
                609,
                179,
                620
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "a、参数的字段名要加引号。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "b、降序为在字段前面加个负号-。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                146,
                646,
                322,
                676
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.order_by(\"price\") # 查询所有，按照价格升序排列"
                    }
                ]
            },
            "bbox": [
                159,
                684,
                576,
                695
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.order_by(\"-price\") # 查询所有，按照价格降序排列"
                    }
                ]
            },
            "bbox": [
                159,
                702,
                579,
                714
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "对查询结果进行反转。"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                744,
                369,
                762
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "reverse() 方法"
                    }
                ]
            },
            "bbox": [
                144,
                804,
                226,
                816
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的是 QuerySe t类型数据，类似于 list，里面放的是反转后的模型类的对象，可用索引下标取出模型类的对象。"
                    }
                ]
            },
            "bbox": [
                144,
                822,
                736,
                835
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 按照价格升序排列：降序再反转 "
                    }
                ]
            },
            "bbox": [
                159,
                860,
                339,
                872
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.order_by(\"-price\").reverse()"
                    }
                ]
            },
            "bbox": [
                159,
                879,
                463,
                890
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "查询数据的数量"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                101,
                317,
                120
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "返回的数据是整数。"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                161,
                302,
                177
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "count() 方法"
                    }
                ]
            },
            "bbox": [
                147,
                181,
                215,
                193
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.count() # 查询所有数据的数量"
                    }
                ]
            },
            "bbox": [
                159,
                199,
                478,
                212
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.filter(price=200).count() # 查询符合条件数据的数量"
                    }
                ]
            },
            "bbox": [
                159,
                218,
                586,
                231
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "first() 方法返回第一条数据返回的数据是模型类的对象也可以用索引下标 [0]。"
                    }
                ]
            },
            "bbox": [
                146,
                237,
                544,
                249
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.first() # 返回所有数据的第一条数据"
                    }
                ]
            },
            "bbox": [
                159,
                255,
                502,
                267
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "last() 方法返回最后一条数据返回的数据是模型类的对象不能用索引下标[-1]，ORM 没有逆序索引。"
                    }
                ]
            },
            "bbox": [
                146,
                274,
                660,
                286
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.last() # 返回所有数据的最后一条数据"
                    }
                ]
            },
            "bbox": [
                159,
                292,
                514,
                304
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "是否存在数据"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                334,
                294,
                353
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "exists() 方法用于判断查询的结果 QuerySet 列表里是否有数据。"
                    }
                ]
            },
            "bbox": [
                146,
                395,
                477,
                407
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的数据类型是布尔，有为 true，没有为 false。"
                    }
                ]
            },
            "bbox": [
                146,
                432,
                406,
                444
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意：判断的数据类型只能为 QuerySet 类型数据，不能为整型和模型类的对象。"
                    }
                ]
            },
            "bbox": [
                146,
                469,
                564,
                481
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.exists()"
                    }
                ]
            },
            "bbox": [
                159,
                506,
                359,
                518
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 报错，判断的数据类型只能为QuerySet类型数据，不能为整型"
                    }
                ]
            },
            "bbox": [
                159,
                525,
                500,
                537
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.count().exists()"
                    }
                ]
            },
            "bbox": [
                159,
                543,
                400,
                555
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 报错，判断的数据类型只能为QuerySet类型数据，不能为模型类对象"
                    }
                ]
            },
            "bbox": [
                159,
                562,
                534,
                574
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.first().exists()"
                    }
                ]
            },
            "bbox": [
                159,
                581,
                389,
                592
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "查询数据"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                621,
                247,
                640
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "values() 方法用于查询部分字段的数据。"
                    }
                ]
            },
            "bbox": [
                146,
                684,
                354,
                695
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的是 QuerySet 类型数据，类似于 list，里面不是模型类的对象，而是一个可迭代的字典序列，字典里的键是字段，值是数据。"
                    }
                ]
            },
            "bbox": [
                144,
                720,
                816,
                732
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意："
                    }
                ]
            },
            "bbox": [
                147,
                758,
                179,
                769
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "参数的字段名要加引号"
                    }
                ]
            },
            "bbox": [
                147,
                795,
                268,
                806
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "想要字段名和数据用 values"
                    }
                ]
            },
            "bbox": [
                147,
                814,
                294,
                825
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.values(\"pk\",\"price\") "
                    }
                ]
            },
            "bbox": [
                159,
                832,
                420,
                843
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books[0][\"price\"],type(books)) # 得到的是第一条记录的 price 字段的数据"
                    }
                ]
            },
            "bbox": [
                159,
                851,
                564,
                862
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "查询数据 2"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                101,
                265,
                120
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "values_list() 方法用于查询部分字段的数据。"
                    }
                ]
            },
            "bbox": [
                144,
                162,
                381,
                174
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的是 QuerySet 类型数据，类似于 list，里面不是模型类的对象，而是一个个元组，元组里放的是查询字段对应的数据。"
                    }
                ]
            },
            "bbox": [
                144,
                181,
                781,
                193
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意："
                    }
                ]
            },
            "bbox": [
                146,
                199,
                181,
                211
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "参数的字段名要加引号"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 只想要数据用 values_list"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                218,
                339,
                247
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.values_list(\"price\",\"publish\") "
                    }
                ]
            },
            "bbox": [
                159,
                255,
                465,
                266
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books) "
                    }
                ]
            },
            "bbox": [
                159,
                274,
                228,
                285
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books[0][0],type(books)) # 得到的是第一条记录的 price 字段的数据"
                    }
                ]
            },
            "bbox": [
                159,
                292,
                539,
                304
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "去重"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                334,
                200,
                351
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "distinct() 方法用于对数据进行去重。"
                    }
                ]
            },
            "bbox": [
                144,
                395,
                339,
                407
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的是 QuerySet 类型数据。"
                    }
                ]
            },
            "bbox": [
                146,
                414,
                307,
                425
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意："
                    }
                ]
            },
            "bbox": [
                146,
                432,
                181,
                444
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 对模型类的对象去重没有意义，因为每个对象都是一个不一样的存在。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "distinct() 一般是联合 values 或者 values_list 使用。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                451,
                569,
                481
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def add_book(request): "
                    }
                ]
            },
            "bbox": [
                146,
                506,
                273,
                518
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 查询一共有多少个出版社"
                    }
                ]
            },
            "bbox": [
                159,
                525,
                304,
                536
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.values_list(\"publish\").distinct() # 对模型类的对象去重没有意义，因为每个对象都是一个不一样的存在。"
                    }
                ]
            },
            "bbox": [
                157,
                543,
                847,
                555
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.distinct() "
                    }
                ]
            },
            "bbox": [
                159,
                562,
                366,
                573
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "基于双下划线的模糊查询"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                602,
                411,
                623
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "filter() 方法（exclude 同理）。"
                    }
                ]
            },
            "bbox": [
                144,
                665,
                307,
                676
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意：filter 中运算符号只能使用等于号 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "，不能使用大于号 "
                    },
                    {
                        "type": "equation_inline",
                        "content": ">"
                    },
                    {
                        "type": "text",
                        "content": "，小于号 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "<"
                    },
                    {
                        "type": "text",
                        "content": "，等等其他符号。"
                    }
                ]
            },
            "bbox": [
                144,
                683,
                618,
                695
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "_in 用于读取区间， "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "号后面为列表 。"
                    }
                ]
            },
            "bbox": [
                146,
                702,
                347,
                713
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "_gt 大于号 ， "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "号后面为数字。__gte 大于等于， "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "号后面为数字。__lt,__lte"
                    }
                ]
            },
            "bbox": [
                146,
                720,
                554,
                733
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "_range 在 ... 之间，左闭右闭区间， "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "号后面为两个元素的列表。"
                    }
                ]
            },
            "bbox": [
                146,
                739,
                489,
                751
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "_contains 包含， "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "号后面为字符串。"
                    }
                ]
            },
            "bbox": [
                146,
                758,
                347,
                769
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "_icontains 不区分大小写的包含， "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "号后面为字符串。"
                    }
                ]
            },
            "bbox": [
                146,
                776,
                433,
                788
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "_startswith 以指定字符开头， "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "号后面为字符串。"
                    }
                ]
            },
            "bbox": [
                146,
                795,
                413,
                806
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "_endswith 以指定字符结尾， "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "号后面为字符串。"
                    }
                ]
            },
            "bbox": [
                146,
                813,
                410,
                825
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "_year 是 DateField 数据类型的年份， "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "号后面为数字。__day/__month "
                    }
                ]
            },
            "bbox": [
                146,
                832,
                527,
                844
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "删除 "
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                101,
                200,
                120
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式一：使用模型类的 对象.delete()。"
                    }
                ]
            },
            "bbox": [
                144,
                162,
                344,
                174
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回值：元组，第一个元素为受影响的行数。"
                    }
                ]
            },
            "bbox": [
                146,
                181,
                379,
                192
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books=models.Book.objects.filter(pk=8).first().delete() "
                    }
                ]
            },
            "bbox": [
                146,
                199,
                428,
                211
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式二：使用 QuerySet 类型数据.delete()(推荐)"
                    }
                ]
            },
            "bbox": [
                146,
                218,
                401,
                230
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回值：元组，第一个元素为受影响的行数。"
                    }
                ]
            },
            "bbox": [
                146,
                237,
                379,
                248
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books=models.Book.objects.filter(pk__in=[1,2]).delete() "
                    }
                ]
            },
            "bbox": [
                146,
                255,
                438,
                267
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "a. Django 删除数据时，会模仿 SQL约束 ON DELETE CASCADE 的行为，也就是删除一个对象时也会删除与它相关联的外键对象。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". b. delete() 方法是 QuerySet 数据类型的方法，但并不适用于 Manager 本身。也就是想要删除所有数据，不能不写 all。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                274,
                845,
                323
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books=models.Book.objects.delete() # 报错 "
                    }
                ]
            },
            "bbox": [
                146,
                330,
                388,
                341
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books=models.Book.objects.all().delete() # 删除成功 "
                    }
                ]
            },
            "bbox": [
                146,
                348,
                447,
                360
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "修改"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                388,
                200,
                407
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式一："
                    }
                ]
            },
            "bbox": [
                146,
                451,
                191,
                462
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "模型类的对象.属性 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "更改的属性值"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                491,
                514,
                512
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "模型类的对象.save()"
                    }
                ]
            },
            "bbox": [
                146,
                554,
                258,
                565
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回值：编辑的模型类的对象。"
                    }
                ]
            },
            "bbox": [
                146,
                573,
                309,
                583
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {b o o k s} = \\text {m o d e l s . B o o k . o b j e c t s . f i l t e r} (\\mathrm {p k} = 7). \\text {f i r s t ()}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/fc7d89fc8ea84557914ba9e46bca67e5d5bf02f50cd0f88b0e1ac05676caa516.jpg"
                }
            },
            "bbox": [
                146,
                590,
                393,
                602
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {b o o k s . p r i c e} = 4 0 0",
                "math_type": "latex",
                "image_source": {
                    "path": "images/0f917cfef6ef803be7974ce3fc37fe598f54c058b8efa1cadfe6c982686a3191.jpg"
                }
            },
            "bbox": [
                146,
                609,
                243,
                620
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\mathsf {b o o k s . s a v e ()}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/db6352a8096c8c7d2fd044e72ff86e9983a034fcd5f2e297052e5d72da7ab12b.jpg"
                }
            },
            "bbox": [
                146,
                627,
                218,
                639
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式二：QuerySet 类型数据.update(字段名 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\mathbf { \\tau } = \\mathbf { \\dot { \\tau } }"
                    },
                    {
                        "type": "text",
                        "content": "更改的数据)（推荐）"
                    }
                ]
            },
            "bbox": [
                146,
                646,
                485,
                658
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回值：整数，受影响的行数"
                    }
                ]
            },
            "bbox": [
                146,
                665,
                304,
                676
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ]
            },
            "bbox": [
                147,
                684,
                174,
                695
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.shortcuts import render,HttpResponse "
                    }
                ]
            },
            "bbox": [
                146,
                702,
                420,
                713
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from app01 import models "
                    }
                ]
            },
            "bbox": [
                146,
                720,
                294,
                731
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def add_book(request): "
                    }
                ]
            },
            "bbox": [
                146,
                739,
                273,
                750
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.filter(pk__in=[7,8]).update(price=888) "
                    }
                ]
            },
            "bbox": [
                159,
                758,
                514,
                769
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "ORM - 添加数据"
                    }
                ]
            },
            "bbox": [
                146,
                795,
                236,
                806
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "一对多(外键 ForeignKey)"
                    }
                ]
            },
            "bbox": [
                146,
                813,
                285,
                825
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式一: 传对象的形式，返回值的数据类型是对象，书籍对象。"
                    }
                ]
            },
            "bbox": [
                146,
                832,
                468,
                843
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "步骤："
                    }
                ]
            },
            "bbox": [
                146,
                851,
                179,
                860
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "a. 获取出版社对象"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "b. 给书籍的出版社属性pulish 传出版社对象"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                869,
                436,
                898
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "app01/views.py 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                95,
                292,
                105
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def add_book(request): "
                    }
                ]
            },
            "bbox": [
                146,
                112,
                273,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 获取出版社对象"
                    }
                ]
            },
            "bbox": [
                159,
                131,
                260,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "pub_ob "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Publish.objects.filter(pk=1).first() "
                    }
                ]
            },
            "bbox": [
                159,
                151,
                428,
                162
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 给书籍的出版社属性publish传出版社对象"
                    }
                ]
            },
            "bbox": [
                159,
                168,
                396,
                181
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "book "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.create(title=\"菜鸟教程\", price "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\scriptstyle \\sum 0 0"
                    },
                    {
                        "type": "text",
                        "content": ", pub_date "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\cdot = \""
                    },
                    {
                        "type": "text",
                        "content": "2010-10-10\", publish=pub_obj) "
                    }
                ]
            },
            "bbox": [
                159,
                187,
                717,
                200
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(book, type(book)) "
                    }
                ]
            },
            "bbox": [
                159,
                206,
                285,
                218
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(book)"
                    }
                ]
            },
            "bbox": [
                159,
                225,
                309,
                236
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式二: 传对象 id 的形式(由于传过来的数据一般是 id,所以传对象 id 是常用的)。"
                    }
                ]
            },
            "bbox": [
                146,
                243,
                556,
                255
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "一对多中，设置外键属性的类(多的表)中，MySQL 中显示的字段名是:外键属性名_id。"
                    }
                ]
            },
            "bbox": [
                146,
                262,
                589,
                273
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回值的数据类型是对象，书籍对象。"
                    }
                ]
            },
            "bbox": [
                146,
                280,
                344,
                291
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "步骤："
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                299,
                179,
                310
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". a. 获取出版社对象的 id"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "b. 给书籍的关联出版社字段pulish_id 传出版社对象的 id"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                317,
                500,
                347
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "多对多(ManyToManyField)：在第三张关系表中新增数据"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                354,
                448,
                366
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式一: 传对象形式，无返回值。"
                    }
                ]
            },
            "bbox": [
                146,
                373,
                315,
                384
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "步骤："
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                392,
                179,
                401
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "a. 获取作者对象 "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". b. 获取书籍对象"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "c. 给书籍对象的 authors 属性用 add 方法传作者对象"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                410,
                482,
                458
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "方式二: 传对象id形式，无返回值。"
                    }
                ]
            },
            "bbox": [
                146,
                464,
                329,
                476
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "步骤："
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                483,
                179,
                495
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "a. 获取作者对象的 id"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". b. 获取书籍对象"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "c. 给书籍对象的 authors 属性用 add 方法传作者对象的 id"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                502,
                505,
                551
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "app01/views.py 文件代码："
                    }
                ]
            },
            "bbox": [
                146,
                558,
                292,
                570
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def add_book(request): "
                    }
                ]
            },
            "bbox": [
                146,
                577,
                273,
                588
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 获取作者对象"
                    }
                ]
            },
            "bbox": [
                159,
                595,
                248,
                606
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "chong "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Author.objects.filter(name=\"令狐冲\").first() "
                    }
                ]
            },
            "bbox": [
                159,
                614,
                468,
                626
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 获取作者对象的id "
                    }
                ]
            },
            "bbox": [
                159,
                632,
                270,
                643
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "pk "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "chong.pk "
                    }
                ]
            },
            "bbox": [
                159,
                651,
                238,
                661
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 获取书籍对象"
                    }
                ]
            },
            "bbox": [
                159,
                670,
                248,
                680
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "book "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.filter(titl "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\mathrel { \\mathop : } \\mathbf { \\overline { { \\mathbf { \\Lambda } } } }"
                    },
                    {
                        "type": "text",
                        "content": "\"冲灵剑法\").first() "
                    }
                ]
            },
            "bbox": [
                159,
                688,
                455,
                699
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 给书籍对象的 authors 属性用 add 方法传作者对象的 id"
                    }
                ]
            },
            "bbox": [
                159,
                706,
                458,
                717
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "book.authors.add(pk) "
                    }
                ]
            },
            "bbox": [
                159,
                725,
                275,
                736
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "关联管理器(对象调用)"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                744,
                265,
                755
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "前提："
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                762,
                179,
                772
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "多对多（双向均有关联管理器）"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "一对多（只有多的那个类的对象有关联管理器，即反向才有）"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                780,
                522,
                810
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "语法格式："
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                816,
                203,
                829
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "正向：属性名"
                    }
                ]
            },
            "bbox": [
                146,
                835,
                221,
                847
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "反向：小写类名加_set"
                    }
                ]
            },
            "bbox": [
                146,
                854,
                270,
                866
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意：一对多只能反向"
                    }
                ]
            },
            "bbox": [
                146,
                873,
                268,
                884
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "常用方法："
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                892,
                203,
                903
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "add()：用于多对多，把指定的模型对象添加到关联对象集（关系表）中。"
                    }
                ]
            },
            "bbox": [
                144,
                95,
                527,
                105
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意：add() 在一对多(即外键)中，只能传对象（ *QuerySet数据类型），不能传 id（*[id表]）。"
                    }
                ]
            },
            "bbox": [
                144,
                112,
                640,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "*[ ] 的使用:"
                    }
                ]
            },
            "bbox": [
                146,
                133,
                208,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 方式一：传对象"
                    }
                ]
            },
            "bbox": [
                146,
                151,
                243,
                161
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {b o o k} \\_ \\text {o b j} = \\text {m o d e l s . B o o k . o b j e c t s . g e t (i d = 1 0)}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/d56ee4c86568325d864d0a31c1f11c4c5a646b8fa6a24c5508d8de83a654f01e.jpg"
                }
            },
            "bbox": [
                146,
                168,
                376,
                180
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {a u t o r} = \\text {m o d e l s . A u t o r . o b j e c t s . f i l t e r (i d \\_ g t = 2)}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/42e44f97eabe1dc2cbe007beb2d33e8eae4f45807cb45fbd8f8a2b2323fd276b.jpg"
                }
            },
            "bbox": [
                146,
                187,
                413,
                199
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "book_obj.authors.add(*author_list) # 将 id 大于 2 的作者对象添加到这本书的作者集合中"
                    }
                ]
            },
            "bbox": [
                144,
                206,
                608,
                218
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 方式二：传对象id"
                    }
                ]
            },
            "bbox": [
                146,
                225,
                255,
                235
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "book_obj.authors.add(*[1,3]) # 将 id=1 和 id=3 的作者对象添加到这本书的作者集合中"
                    }
                ]
            },
            "bbox": [
                144,
                243,
                591,
                255
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(\"ok\")"
                    }
                ]
            },
            "bbox": [
                146,
                262,
                292,
                273
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "反向：小写表名_set"
                    }
                ]
            },
            "bbox": [
                146,
                280,
                258,
                292
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "y i n g = \\text {m o d e l s . A u t h o r . o b j e c t s . f i l t e r} (\\text {n a m e} = ^ {\\prime \\prime} \\text {任 盈 盈} ^ {\\prime \\prime}). \\text {f i r s t ()}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/70f231bec2a80631a4c6676abfeddf00a003a605aaa3d71dd45d3338c1765795.jpg"
                }
            },
            "bbox": [
                146,
                299,
                445,
                311
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {b o o k} = \\text {m o d e l s . B o o k . o b j e c t s . f i l t e r (t i t l e = ＂ 冲 灵 剑 法 ＂) . f i r s t ()}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/0240a07293fce298184f72d18b3ce7853709900e7b3a444043c58e6eba1a6a38.jpg"
                }
            },
            "bbox": [
                146,
                317,
                442,
                329
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {y i n g . b o o k \\_ s e t . a d d (b o o k)}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/68223dbe76a8e10f070b148b4d74280836be2efb9a0baa4774d55c00954cbae6.jpg"
                }
            },
            "bbox": [
                146,
                336,
                280,
                347
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "1. 正向查询（Forward Query）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                373,
                312,
                385
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "定义"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                392,
                176,
                401
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "从“持有外键的模型”访问“被关联的模型”。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "使用属性名直接访问关联对象。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                409,
                458,
                439
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "2. 反向查询（Reverse Query）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                447,
                312,
                458
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "定义"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                466,
                174,
                476
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "从“被关联的模型”访问“持有外键的模型”。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "默认使用小写类名_set 作为关联管理器名称。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                483,
                458,
                514
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "remove()：从关联对象集中移除执行的模型对象。"
                    }
                ]
            },
            "bbox": [
                146,
                521,
                405,
                533
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "对于 ForeignKey 对象，这个方法仅在 null=True（可以为空）时存在，无返回值。"
                    }
                ]
            },
            "bbox": [
                144,
                539,
                566,
                551
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                558,
                174,
                569
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {a u t o r} = \\text {m o d e l s . A u t h o r . o b j e c t s . g e t (i d = 1)}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/fb270fcf57b2e290c2edb9b562db20088f0d2adae0d65c9a375938493764fa93.jpg"
                }
            },
            "bbox": [
                146,
                577,
                381,
                588
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {b o o k} \\_ \\text {o b j} = \\text {m o d e l s . B o o k . o b j e c t s . g e t (i d = 1 1)}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/4026222efcdaca598f9a968f93e1cf4be6211422ca2110470e125dc99a7a2481.jpg"
                }
            },
            "bbox": [
                146,
                595,
                376,
                606
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {a t h o r} \\quad \\text {o b j . b o o k} \\quad \\text {s e t . r e m o v e} (\\text {b o o k} \\quad \\text {o b j})",
                "math_type": "latex",
                "image_source": {
                    "path": "images/82085a5b7734a85b367d97b9b65e7db3abfffb8588626a2e511204b330427821.jpg"
                }
            },
            "bbox": [
                146,
                614,
                356,
                625
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "clear()：从关联对象集中移除一切对象，删除关联，不会删除对象。"
                    }
                ]
            },
            "bbox": [
                146,
                632,
                497,
                644
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "对于 ForeignKey 对象，这个方法仅在 null=True（可以为空）时存在。"
                    }
                ]
            },
            "bbox": [
                146,
                651,
                509,
                662
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "无返回值。"
                    }
                ]
            },
            "bbox": [
                146,
                670,
                203,
                680
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 清空独孤九剑关联的所有作者"
                    }
                ]
            },
            "bbox": [
                146,
                688,
                317,
                699
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {b o o k} = \\text {m o d e l s . B o o k . o b j e c t s . f i l t e r (t i t l e} = \\text {＂ 菜 鸟 教 程 ＂) . f i r s t ()}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/7baba95449cf64632b073e8451b04d66d26a048231befdf5b1cdc6bae7659411.jpg"
                }
            },
            "bbox": [
                146,
                707,
                442,
                718
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {b o o k . a u t h o r s . c l e a r ()}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/4016f64b976c8d90b410ec2fa430152a2b8d93b434ca2b84ea77c6344e25aa42.jpg"
                }
            },
            "bbox": [
                146,
                725,
                255,
                736
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "ORM 查询"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                744,
                205,
                753
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "基于对象的跨表查询。"
                    }
                ]
            },
            "bbox": [
                146,
                762,
                262,
                772
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "正向：属性名称"
                    }
                ]
            },
            "bbox": [
                146,
                781,
                233,
                791
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "反向：小写类名_set"
                    }
                ]
            },
            "bbox": [
                146,
                799,
                255,
                810
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "一对多"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                818,
                186,
                829
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询主键为 1 的书籍的出版社所在的城市（正向）。"
                    }
                ]
            },
            "bbox": [
                146,
                835,
                415,
                847
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                854,
                174,
                866
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\begin{array}{l} \\text {b o o k} = \\text {m o d e l s . B o o k . o b j e c t s . f i l t e r (p k = 1 0) . f i r s t ()} \\\\ \\mathrm {r e s} = \\text {b o o k . p u b l i s h . c i t y} \\\\ \\end{array}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/c5b0ce11005726d00766646118865cd52ba65dd0d2671caf9660bbb808f40dff.jpg"
                }
            },
            "bbox": [
                146,
                873,
                394,
                903
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询明教出版社出版的书籍名（反向）。"
                    }
                ]
            },
            "bbox": [
                146,
                95,
                354,
                105
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "反向：对象.小写类名_set(pub.book_set) 可以跳转到关联的表(书籍表)。"
                    }
                ]
            },
            "bbox": [
                146,
                112,
                524,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "pub.book_set.all()：取出书籍表的所有书籍对象，在一个 QuerySet 里，遍历取出一个个书籍对象。"
                    }
                ]
            },
            "bbox": [
                146,
                131,
                663,
                143
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                151,
                174,
                161
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\begin{array}{l} \\mathrm {p u b} = \\text {m o d e l s . P u b l i s h . o b j e c t s . f i l t e r (n a m e = \" 明 教 出 版 社\")}. \\text {f i r s t ()} \\\\ \\operatorname {r e s} = \\operatorname {p u b}. \\operatorname {b o o k} _ {\\text {s e t}}. \\operatorname {a l l} () \\\\ f o r i \\text {i n} \\\\ \\mathbf {p r i n t} (i. t i l e) \\\\ \\end{array}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/c476199b7cd2e33749abde48bc4d596f4bb28126f6714339febc01770feffb55.jpg"
                }
            },
            "bbox": [
                146,
                168,
                470,
                235
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "一对一"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                244,
                186,
                254
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询令狐冲的电话（正向）"
                    }
                ]
            },
            "bbox": [
                146,
                261,
                284,
                272
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "正向：对象.属性 (author.au_detail) 可以跳转到关联的表(作者详情表)"
                    }
                ]
            },
            "bbox": [
                146,
                280,
                505,
                292
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                299,
                174,
                309
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {a u t h o r} = \\text {m o d e l s . A u t h o r . o b j e c t s . f i l t e r (n a m e = \" 令 狐 冲\") . f i r s t ()}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/caf120c07fa74354a9df98079154b8e11fb40df6efbd79131d0dc61145637437.jpg"
                }
            },
            "bbox": [
                146,
                317,
                455,
                329
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\mathrm {r e s} = \\text {a u t h o r}.",
                "math_type": "latex",
                "image_source": {
                    "path": "images/782dc3f135a797056669a0428372934b56972148b14242407f64ed6b12bca116.jpg"
                }
            },
            "bbox": [
                147,
                336,
                280,
                346
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\operatorname {p r i n t} (\\text {r e s}, \\text {t y p e} (\\text {r e s}))",
                "math_type": "latex",
                "image_source": {
                    "path": "images/36ea7268349795267049cad1ff91b54047aca5bad2d530728168b3d10e099d61.jpg"
                }
            },
            "bbox": [
                147,
                355,
                253,
                366
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询所有住址在黑木崖的作者的姓名（反向）。"
                    }
                ]
            },
            "bbox": [
                146,
                373,
                389,
                384
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "一对一的反向，用对象.小写类名即可，不用加_set。"
                    }
                ]
            },
            "bbox": [
                146,
                391,
                423,
                403
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "反向：对象.小写类名(addr.author)可以跳转到关联的表(作者表)。"
                    }
                ]
            },
            "bbox": [
                146,
                410,
                480,
                420
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                429,
                174,
                439
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\begin{array}{l} \\text {a d d r} = \\text {m o d e l s . A u t h o r D e a t i l . o b j e c t s . f i l t e r} (\\text {a d d r} = ^ {\\prime \\prime} \\text {黑 木 崖}) ^ {\\prime \\prime}). \\text {f i r s t} () \\\\ \\text {r e s} = \\text {a d d r . a u t h o r . n a m e} \\\\ \\operatorname {p r i n t} (\\text {r e s}, \\text {t y p e} (\\text {r e s})) \\\\ \\end{array}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/c6fba145eb89255591d4ccf14d3f9a2434f8c9f8433a673542ec975f0e81936f.jpg"
                }
            },
            "bbox": [
                146,
                447,
                470,
                495
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "多对多"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                502,
                186,
                513
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "菜鸟教程所有作者的名字以及手机号（正向）。"
                    }
                ]
            },
            "bbox": [
                146,
                521,
                389,
                532
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "正向：对象.属性(book.authors)可以跳转到关联的表(作者表)。"
                    }
                ]
            },
            "bbox": [
                146,
                539,
                472,
                551
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "作者表里没有作者电话，因此再次通过对象.属性(i.au_detail)跳转到关联的表（作者详情表）。"
                    }
                ]
            },
            "bbox": [
                146,
                558,
                635,
                570
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                577,
                174,
                588
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {b o o k} = \\text {m o d e l s . B o o k . o b j e c t s . f i l t e r (t i t l e = \" 菜 鸟 教 程 ) . f i r s t ()}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/07aac130929d87bb15a69d9b7239a6d0182c7c386dde69f66a81ac9862e986a9.jpg"
                }
            },
            "bbox": [
                146,
                595,
                440,
                607
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\mathrm {r e s} = \\text {b o o k . a u t h o r s . a l l ()}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/cf4a473d2ad348e82a4c14c9ba50684a75aa034b27bc0828b9639a8d7e120c12.jpg"
                }
            },
            "bbox": [
                147,
                614,
                270,
                625
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "f o r i n \\text {r e s}:",
                "math_type": "latex",
                "image_source": {
                    "path": "images/815d75152ece8a6590b2a48f9288bb5205311dd6de47bb30c0ed549bd6e063b8.jpg"
                }
            },
            "bbox": [
                147,
                633,
                208,
                643
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {p r i n t} (\\mathrm {i . n a m e}, \\mathrm {i . a u} _ {\\text {d e t a l}}. \\text {t e l})",
                "math_type": "latex",
                "image_source": {
                    "path": "images/80a35abcbe2d1b0045801ea23518504d19841dc95dfe3a30bea49662c5c10a29.jpg"
                }
            },
            "bbox": [
                161,
                651,
                309,
                662
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询任我行出过的所有书籍的名字（反向）。"
                    }
                ]
            },
            "bbox": [
                146,
                669,
                379,
                681
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                688,
                174,
                697
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\begin{array}{l} \\text {a u t h o r} = \\text {m o d e l s . A u t h o r . o b j e c t s . f i l t e r (n a m e} = ^ {\\prime \\prime} \\text {任 我 行}) ^ {\\prime \\prime}. \\text {f i r s t ()} \\\\ \\operatorname {r e s} = \\text {a u t h o r . b o o k \\_ s e t . a l l ()} \\\\ f o r i n \\text {r e s}: \\\\ \\mathbf {p r i n t} (i. t i l e) \\\\ \\end{array}",
                "math_type": "latex",
                "image_source": {
                    "path": "images/027afd4c68f929d890e6680396e7ef3c74b9adcdc1d5b26b0c42e0a0490c8d21.jpg"
                }
            },
            "bbox": [
                146,
                707,
                455,
                772
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "正向：属性名称__跨表的属性名称反向：小写类名__跨表的属性名称"
                    }
                ]
            },
            "bbox": [
                146,
                780,
                509,
                791
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "一对多"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                799,
                186,
                809
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询菜鸟出版社出版过的所有书籍的名字与价格。"
                    }
                ]
            },
            "bbox": [
                146,
                816,
                401,
                829
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                837,
                174,
                847
            ]
        },
        {
            "type": "equation_interline",
            "content": {
                "math_content": "\\text {r e s} = \\text {m o d e l s . B o o k . o b j e c t s . f i l t e r (p u b l i s h \\_ n a m e = \" 菜 鸟 出 版 社\") . v a l u e s \\_ l i s t (\"} t h i t e , \" p r i c e \")",
                "math_type": "latex",
                "image_source": {
                    "path": "images/f8b3087e0752d8c51be4dcb83795a20b5f7a15fcff3ba00d4801d215b95bbbb4.jpg"
                }
            },
            "bbox": [
                146,
                854,
                608,
                866
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "正向：属性名称__跨表的属性名称反向：小写类名__跨表的属性名称"
                    }
                ]
            },
            "bbox": [
                146,
                873,
                509,
                884
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "一对多"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                892,
                186,
                903
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询菜鸟出版社出版过的所有书籍的名字与价格。"
                    }
                ]
            },
            "bbox": [
                146,
                95,
                403,
                105
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                112,
                174,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "res "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.filter(publish__name=\"菜鸟出版社\").values_list(\"title\", \"price\") "
                    }
                ]
            },
            "bbox": [
                144,
                131,
                608,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "反向：通过 小写类名__跨表的属性名称（book__title，book__price）跨表获取数据。"
                    }
                ]
            },
            "bbox": [
                146,
                151,
                600,
                162
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                168,
                174,
                180
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "res "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Publish.objects.filter(name=\"菜鸟出版社\").values_list(\"book__title\",\"book__price\") "
                    }
                ]
            },
            "bbox": [
                144,
                187,
                643,
                199
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(\"ok\")"
                    }
                ]
            },
            "bbox": [
                146,
                206,
                290,
                217
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "多对多"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                224,
                186,
                235
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询任我行出过的所有书籍的名字。"
                    }
                ]
            },
            "bbox": [
                146,
                243,
                332,
                254
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "正向：通过 属性名称__跨表的属性名称(authors__name) 跨表获取数据："
                    }
                ]
            },
            "bbox": [
                146,
                261,
                524,
                273
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "res "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.filter(authors__name=\"任我行\").values_list(\"title\") "
                    }
                ]
            },
            "bbox": [
                146,
                280,
                547,
                292
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "反向：通过 小写类名__跨表的属性名称（book__title） 跨表获取数据："
                    }
                ]
            },
            "bbox": [
                146,
                299,
                514,
                311
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "res "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Author.objects.filter(name=\"任我行\").values_list(\"book__title\") "
                    }
                ]
            },
            "bbox": [
                146,
                317,
                541,
                329
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "一对一"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                336,
                186,
                346
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询任我行的手机号。"
                    }
                ]
            },
            "bbox": [
                146,
                354,
                260,
                365
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "正向：通过属性名称__跨表的属性名称(au_detail__tel) 跨表获取数据。"
                    }
                ]
            },
            "bbox": [
                146,
                372,
                519,
                384
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "res "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Author.objects.filter(name=\"任我行\").values_list(\"au_detail__tel\") "
                    }
                ]
            },
            "bbox": [
                146,
                391,
                557,
                403
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "反向：通过小写类名__跨表的属性名称（author__name）跨表获取数据。"
                    }
                ]
            },
            "bbox": [
                146,
                410,
                537,
                420
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "res "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.AuthorDetail.objects.filter(author__name=\"任我行\").values_list(\"tel\") "
                    }
                ]
            },
            "bbox": [
                146,
                428,
                573,
                439
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django ORM – 多表实例（聚合与分组查询）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                447,
                381,
                458
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "聚合查询（aggregate）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                464,
                270,
                476
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "聚合查询函数是对一组值执行计算，并返回单个值。"
                    }
                ]
            },
            "bbox": [
                146,
                483,
                413,
                495
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 使用聚合查询前要先从 django.db.models 引入 Avg、Max、Min、Count、Sum（首字母大写）。"
                    }
                ]
            },
            "bbox": [
                146,
                502,
                685,
                514
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.db.models import Avg,Max,Min,Count,Sum # 引入函数"
                    }
                ]
            },
            "bbox": [
                146,
                521,
                509,
                532
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "聚合查询返回值的数据类型是字典。"
                    }
                ]
            },
            "bbox": [
                146,
                539,
                332,
                551
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "聚合函数 aggregate() 是 QuerySet 的一个终止子句， 生成的一个汇总值，相当于 count()。"
                    }
                ]
            },
            "bbox": [
                146,
                558,
                613,
                570
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "使用 aggregate() 后，数据类型就变为字典，不能再使用 QuerySet 数据类型的一些 API 了。"
                    }
                ]
            },
            "bbox": [
                146,
                576,
                620,
                588
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "日期数据类型(DateField)可以用 Max 和 Min。"
                    }
                ]
            },
            "bbox": [
                146,
                595,
                381,
                606
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回的字典中：键的名称默认是（属性名称加上__聚合函数名），值是计算出来的聚合值。"
                    }
                ]
            },
            "bbox": [
                146,
                613,
                616,
                625
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "如果要自定义返回字典的键的名称，可以起别名："
                    }
                ]
            },
            "bbox": [
                146,
                632,
                403,
                643
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "aggregate(别名 "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "聚合函数名(\"属性名称\"))"
                    }
                ]
            },
            "bbox": [
                146,
                651,
                369,
                662
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "分组查询（annotate）"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                688,
                263,
                699
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "分组查询一般会用到聚合函数，所以使用前要先从 django.db.models 引入 Avg,Max,Min,Count,Sum（首字母大写）。"
                    }
                ]
            },
            "bbox": [
                144,
                706,
                751,
                718
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.db.models import Avg,Max,Min,Count,Sum # 引入函数"
                    }
                ]
            },
            "bbox": [
                146,
                725,
                509,
                736
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "返回值："
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                743,
                191,
                753
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "分组后，用 values 取值，则返回值是 QuerySet 数据类型里面为一个个字典；"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "分组后，用 values_list 取值，则返回值是 QuerySet 数据类型里面为一个个元组。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                762,
                626,
                791
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "MySQL 中的 limit 相当于 ORM 中的 QuerySet 数据类型的切片。"
                    }
                ]
            },
            "bbox": [
                146,
                799,
                478,
                810
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "注意："
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                816,
                179,
                829
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "annotate 里面放聚合函数。"
                    }
                ]
            },
            "bbox": [
                146,
                835,
                287,
                847
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "values 或者 values_list 放在 annotate 前面：values 或者 values_list 是声明以什么字段分组，annotate 执行分组。前者相当于GROUP BY,后者相当于聚合函数"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "values 或者 values_list 放在 annotate 后面： annotate 表示直接以当前表的 pk 执行分组，values 或者 values_list 表示查询哪"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                144,
                854,
                847,
                903
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "些字段， 并且要将 annotate 里的聚合函数起别名，在 values 或者 values_list 里写其别名。"
                    }
                ]
            },
            "bbox": [
                176,
                95,
                645,
                107
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "annotate 里相当于聚合函数，value 相当于 groupby 了"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                114,
                468,
                126
            ]
        },
        {
            "type": "algorithm",
            "content": {
                "algorithm_caption": [],
                "algorithm_content": [
                    {
                        "type": "text",
                        "content": "res  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " models.Publish.objects.values(\"name\"). annotate(in_price  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\equiv"
                    },
                    {
                        "type": "text",
                        "content": " Min(\"book_price\"))   \nprint(res)   \nres  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " models.Book.objects annotate(c  "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": " Count(\"authors_name\").values(\"title\",\"c\")   \nprint(res) "
                    }
                ]
            },
            "bbox": [
                146,
                131,
                594,
                200
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "F() 查询"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                206,
                193,
                218
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "F() 的实例可以在查询中引用字段，来比较同一个 model 实例中两个不同字段的值。"
                    }
                ]
            },
            "bbox": [
                146,
                224,
                576,
                236
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "之前构造的过滤器都只是将字段值与某个常量做比较，如果想要对两个字段的值做比较，就需要用到 F()。"
                    }
                ]
            },
            "bbox": [
                146,
                243,
                690,
                255
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "使用前要先从 django.db.models 引入 F:"
                    }
                ]
            },
            "bbox": [
                146,
                262,
                357,
                273
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.db.models import F "
                    }
                ]
            },
            "bbox": [
                146,
                280,
                317,
                291
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "用法："
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                299,
                179,
                310
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "F(\"字段名称\")"
                    }
                ]
            },
            "bbox": [
                146,
                317,
                221,
                329
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "F 动态获取对象字段的值，可以进行运算。"
                    }
                ]
            },
            "bbox": [
                146,
                335,
                366,
                347
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取余的操作。"
                    }
                ]
            },
            "bbox": [
                146,
                354,
                544,
                366
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "修改操作（update）也可以使用 F() 函数。"
                    }
                ]
            },
            "bbox": [
                146,
                373,
                366,
                384
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询工资大于年龄的人："
                    }
                ]
            },
            "bbox": [
                146,
                391,
                273,
                403
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                410,
                174,
                420
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.db.models import F "
                    }
                ]
            },
            "bbox": [
                146,
                428,
                322,
                439
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "... "
                    }
                ]
            },
            "bbox": [
                147,
                450,
                161,
                456
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "book=models.Emp.objects.filter(salary__gt=F(\"age\")).values(\"name\",\"age\") "
                    }
                ]
            },
            "bbox": [
                146,
                464,
                539,
                476
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Q() 查询"
                    }
                ]
            },
            "bbox": [
                147,
                483,
                194,
                495
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "使用前要先从 django.db.models 引入 Q:"
                    }
                ]
            },
            "bbox": [
                146,
                502,
                359,
                514
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.db.models import Q "
                    }
                ]
            },
            "bbox": [
                147,
                521,
                319,
                533
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "用法："
                    }
                ]
            },
            "bbox": [
                147,
                539,
                179,
                551
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Q(条件判断) "
                    }
                ]
            },
            "bbox": [
                147,
                577,
                215,
                589
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "例如："
                    }
                ]
            },
            "bbox": [
                147,
                595,
                179,
                606
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Q(title__startswith=\"菜\") "
                    }
                ]
            },
            "bbox": [
                146,
                633,
                275,
                645
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "之前构造的过滤器里的多个条件的关系都是 and，如果需要执行更复杂的查询（例如 or 语句），就可以使用 Q 。"
                    }
                ]
            },
            "bbox": [
                146,
                650,
                726,
                662
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Q 对象可以使用 & | ~ （与 或非）操作符进行组合。"
                    }
                ]
            },
            "bbox": [
                146,
                688,
                415,
                700
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "优先级从高到低：~ & |。"
                    }
                ]
            },
            "bbox": [
                146,
                725,
                273,
                737
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "可以混合使用 Q 对象和关键字参数，Q 对象和关键字参数是用\"and\"拼在一起的（即将逗号看成 and ），但是 Q 对象必须位于所有关键字参数的前面。"
                    }
                ]
            },
            "bbox": [
                144,
                762,
                847,
                791
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询价格大于 350 或者名称以菜开头的书籍的名称和价格。"
                    }
                ]
            },
            "bbox": [
                146,
                816,
                450,
                829
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "查询出版日期是 2004 或者1999 年，并且书名中包含有\"菜\"的书籍。"
                    }
                ]
            },
            "bbox": [
                146,
                835,
                497,
                848
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Q 对象和关键字混合使用，Q 对象要在所有关键字的前面:"
                    }
                ]
            },
            "bbox": [
                146,
                854,
                448,
                866
            ]
        }
    ],
    [
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "总结"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                101,
                200,
                120
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books=models.Book.objects "
                    }
                ]
            },
            "bbox": [
                159,
                181,
                310,
                193
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books,type(books)) "
                    }
                ]
            },
            "bbox": [
                159,
                199,
                292,
                212
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "TestModel.Book.objects <class 'django.db.models.manager.Manager'> "
                    }
                ]
            },
            "bbox": [
                147,
                215,
                781,
                233
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.create(title=\"如来神掌\",price=200,publish=\"功夫出版社\",pub_date=\"2010-10-10\") "
                    }
                ]
            },
            "bbox": [
                147,
                237,
                727,
                250
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books, type(books)) # Book object (18) "
                    }
                ]
            },
            "bbox": [
                161,
                255,
                393,
                267
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Book object (7) <class 'TestModel.models.Book'> "
                    }
                ]
            },
            "bbox": [
                147,
                272,
                517,
                288
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.all() "
                    }
                ]
            },
            "bbox": [
                159,
                292,
                339,
                304
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books,type(books)) "
                    }
                ]
            },
            "bbox": [
                159,
                311,
                292,
                323
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "<QuerySet [<Book: Book object "
                    },
                    {
                        "type": "equation_inline",
                        "content": "\\cdot"
                    },
                    {
                        "type": "text",
                        "content": "…,<Book: Book object (7)>]> <class 'django.db.models.query.QuerySet'> "
                    }
                ]
            },
            "bbox": [
                147,
                329,
                727,
                341
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.first() # 返回所有数据的第一条数据"
                    }
                ]
            },
            "bbox": [
                159,
                347,
                502,
                360
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books, type(books)) "
                    }
                ]
            },
            "bbox": [
                159,
                366,
                295,
                378
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Book object (1) <class 'TestModel.models.Book'> "
                    }
                ]
            },
            "bbox": [
                147,
                385,
                406,
                395
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "等同于"
                    }
                ]
            },
            "bbox": [
                147,
                404,
                186,
                414
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.filter() # 返回所有数据的第一条数据"
                    }
                ]
            },
            "bbox": [
                159,
                422,
                505,
                434
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books[0], type(books[0])) "
                    }
                ]
            },
            "bbox": [
                159,
                439,
                321,
                451
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Book object (1) <class 'TestModel.models.Book'> "
                    }
                ]
            },
            "bbox": [
                147,
                458,
                406,
                470
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.values(\"pk\",\"price\") "
                    }
                ]
            },
            "bbox": [
                147,
                476,
                408,
                489
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books,type(books)) # 得到的是第一条记录的 price 字段的数据"
                    }
                ]
            },
            "bbox": [
                159,
                495,
                510,
                508
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "<QuerySet [{'pk': 1, 'price': Decimal('300.00')},… , {'pk': 7, 'price': Decimal('200.00')}]> <class 'django.db.models.query.QuerySet'> "
                    }
                ]
            },
            "bbox": [
                147,
                514,
                821,
                526
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "books "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.Book.objects.values_list(\"price\",\"publish\") "
                    }
                ]
            },
            "bbox": [
                159,
                533,
                467,
                545
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "print(books,type(books)) "
                    }
                ]
            },
            "bbox": [
                159,
                552,
                292,
                563
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "<QuerySet [(Decimal('300.00'), ' 菜 鸟 出 版 社 '), …. (Decimal('200.00'), ' 功 夫 出 版 社 '), (Decimal('200.00'), ' 功 夫 出 版 社 ')]> <class"
                    }
                ]
            },
            "bbox": [
                146,
                570,
                848,
                583
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "'django.db.models.query.QuerySet'> "
                    }
                ]
            },
            "bbox": [
                147,
                588,
                339,
                600
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "1. Book 对象（<class 'TestModel.models.Book'>）"
                    }
                ]
            },
            "bbox": [
                147,
                607,
                423,
                619
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "含义：Book 是 Django 模型（Model）的一个实例，对应数据库中的一行记录。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "作用：表示单个数据对象，可以访问其字段（如book.title、book.price）。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 示例："
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 特点："
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                626,
                620,
                692
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 是 TestModel.models.Book 类的实例。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 可以直接修改并保存到数据库（book.save()）。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                699,
                517,
                730
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "2. Book.objects（<class 'django.db.models.manager.Manager'>）"
                    }
                ]
            },
            "bbox": [
                146,
                755,
                510,
                768
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "含义：objects 是 Django 模型的默认管理器（Manager），用于执行数据库查询操作。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "作用：提供查询方法（如 all(), filter(), get(), create()），用于操作数据库。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "示例："
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                774,
                658,
                822
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 是 Manager 类的实例。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 不直接返回数据，而是返回QuerySet（查询集）或单个Book。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 可以自定义管理器（如 class BookManager(models.Manager)）。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                829,
                620,
                879
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "3. QuerySet（<class 'django.db.models.query.QuerySet'>）"
                    }
                ]
            },
            "bbox": [
                144,
                95,
                475,
                107
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "含义：QuerySet 是 Django 查询数据库返回的结果集，可以包含0 个、1 个或多个Book 对象。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "作用：用于链式查询（如过滤、排序、聚合等），但不会立即执行查询（惰性加载）。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "示例："
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                112,
                702,
                161
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 是惰性的，只有在真正使用时（如遍历、list(queryset)、len(queryset)）才会查询数据库。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 可以进一步过滤（filter()）、排序（order_by()）、切片（[:5]）等。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 如果只返回一个对象（如 get()），则返回 Book 对象，而不是 QuerySet。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                168,
                741,
                217
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "2. 为什么 QuerySet 类型不变，但数据形式不同？"
                    }
                ]
            },
            "bbox": [
                144,
                224,
                406,
                236
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "QuerySet 是 Django 的惰性查询集，它只是生成 SQL 查询的容器，具体返回的数据形式由调用的方法决定："
                    }
                ]
            },
            "bbox": [
                174,
                243,
                769,
                255
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o all() → 返回模型实例。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o values() → 返回字典。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o values_list() → 返回元组或单个值。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                261,
                457,
                310
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "但 QuerySet 本身的类型始终是 django.db.models.query.QuerySet，因为它代表的是“查询能力”，而不是具体的数据形式。"
                    }
                ]
            },
            "bbox": [
                174,
                317,
                847,
                347
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "3. 如何选择合适的方法？"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                372,
                275,
                384
            ]
        },
        {
            "type": "table",
            "content": {
                "image_source": {
                    "path": "images/325e9eead8dd4eb708f6b6ae0407571b2100f9723cb4103acdda3536fd974f7f.jpg"
                },
                "table_caption": [],
                "table_footnote": [],
                "html": "<table><tr><td>方法</td><td>返回的数据形式</td><td>适用场景</td></tr><tr><td>all()</td><td>QuerySet[Model 实例]</td><td>需要完整模型对象（如调用 save()、访问关联字段）</td></tr><tr><td>values(&quot;field1&quot;, &quot;field2&quot;)</td><td>QuerySet[dict]</td><td>只需要部分字段，且希望用字段名访问</td></tr><tr><td>values_list(&quot;field1&quot;, &quot;field2&quot;)</td><td>QuerySet[tuple]</td><td>只需要字段值，不关心字段名</td></tr><tr><td>values_list(&quot;field&quot;, flat=True)</td><td>QuerySet[单值]</td><td>只需要一个字段的列表（如 [1, 2, 3])</td></tr></table>",
                "table_type": "simple_table",
                "table_nest_level": 1
            },
            "bbox": [
                144,
                398,
                848,
                592
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "是的！authors "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.ManyToManyField(\"Author\") 这一行代码会自动创建一个中间表（关联表）来存储多对多关系，但不会直接修改Author 表或当前模型表的结构。以下是详细解释："
                    }
                ]
            },
            "bbox": [
                144,
                594,
                848,
                626
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "1. 自动创建的中间表"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                650,
                258,
                661
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 会为你生成一个名为<当前模型表名>_authors 的中间表（例如，如果当前模型是 Book，则表名为book_authors），其结构如下："
                    }
                ]
            },
            "bbox": [
                144,
                668,
                848,
                697
            ]
        },
        {
            "type": "code",
            "content": {
                "code_caption": [],
                "code_content": [
                    {
                        "type": "text",
                        "content": "CREATE TABLE book_authors (\nid INTEGER PRIMARY KEY AUTOINCREMENT, -- SQLite 示例\nbook_id INTEGER NOT NULL, -- 外键指向Book表\nauthor_id INTEGER NOT NULL, -- 外键指向Author表\nFOREIGN KEY (book_id) REFERENCES book(id),\nFOREIGN KEY (author_id) REFERENCES author(id)"
                    }
                ],
                "code_language": "sql"
            },
            "bbox": [
                146,
                706,
                502,
                810
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "); "
                    }
                ]
            },
            "bbox": [
                146,
                818,
                159,
                828
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "一 这个表只有 3 个字段：id（主键）、book_id（外键）、author_id（外键）。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "你不需要手动定义这个表，Django 在运行makemigrations 和migrate 时会自动创建。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                835,
                662,
                866
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "5. 注意事项"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                872,
                213,
                884
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "1. 表名规则："
                    }
                ]
            },
            "bbox": [
                176,
                891,
                263,
                902
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 自动生成的中间表名格式：<当前模型表名>_<字段名 "
                            },
                            {
                                "type": "equation_inline",
                                "content": ">"
                            },
                            {
                                "type": "text",
                                "content": "（如 book_authors）。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o 如果当前模型表名是 app_book，则中间表名为 app_book_authors。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                236,
                93,
                673,
                124
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "2. 迁移顺序："
                    }
                ],
                "level": 1
            },
            "bbox": [
                176,
                131,
                263,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "o 确保Author 模型已正确定义并先迁移，否则会报错。"
                    }
                ]
            },
            "bbox": [
                236,
                149,
                544,
                161
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "3. 数据库一致性："
                    }
                ],
                "level": 1
            },
            "bbox": [
                176,
                168,
                287,
                180
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "o 不要手动修改中间表，始终通过 Django ORM 操作（如 add()、remove()）。"
                    }
                ]
            },
            "bbox": [
                236,
                187,
                665,
                199
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "总结"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                224,
                174,
                236
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "行为 结果"
                    }
                ]
            },
            "bbox": [
                146,
                252,
                327,
                263
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "定义 ManyToManyField Django 自动创建中间表"
                    }
                ]
            },
            "bbox": [
                146,
                288,
                426,
                300
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "默认中间表字段 id、<当前模型>_id、<关联模型>_id"
                    }
                ]
            },
            "bbox": [
                146,
                325,
                494,
                338
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "自定义中间表 使用 through= 参数指定模型"
                    }
                ]
            },
            "bbox": [
                146,
                363,
                455,
                375
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "操作关系 通过 add()、remove()、clear() 等方法"
                    }
                ]
            },
            "bbox": [
                146,
                399,
                505,
                412
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 Django 中，当你定义一个 ForeignKey 字段时，例如："
                    }
                ]
            },
            "bbox": [
                146,
                428,
                445,
                439
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "python "
                    }
                ]
            },
            "bbox": [
                147,
                447,
                186,
                458
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "复制"
                    }
                ]
            },
            "bbox": [
                147,
                464,
                174,
                476
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "下载"
                    }
                ]
            },
            "bbox": [
                147,
                483,
                174,
                494
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "publish "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "models.ForeignKey(\"Publish\", on_delete=models.CASCADE) "
                    }
                ]
            },
            "bbox": [
                146,
                502,
                521,
                513
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 实际上会在数据库中创建一个名为publish_id 的列，而不是publish。这是由 Django 的设计机制决定的，原因如下："
                    }
                ]
            },
            "bbox": [
                146,
                520,
                796,
                532
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "1. 为什么字段名是 publish_id 而不是 publish？"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                557,
                396,
                569
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "(1) 数据库层面的外键存储"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                576,
                287,
                587
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "在关系型数据库（如 MySQL、PostgreSQL、SQLite）中，外键关系是通过存储目标表的主键值来实现的。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": ". 例如，如果 Publish 表的主键是 id，那么 Book 表会有一个 publish_id 列，存储的是 Publish 表中某条记录的 id 值。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "1. 为什么列名不同也能关联？"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "在关系型数据库（如 MySQL、PostgreSQL、SQLite）中，外键关联的本质是值匹配，而不是列名匹配。只要满足以下条件即可："
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                594,
                847,
                678
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": []
            },
            "bbox": [
                176,
                687,
                189,
                696
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "(2) Django 的 ORM 抽象"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                706,
                280,
                718
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "虽然数据库列名是publish_id，但 Django 在Python 模型层面提供了一个名为publish 的属性，用于方便地访问关联对象。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "当你访问 book.publish 时，Django 会自动执行查询，获取对应的 Publish 对象。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "而 book.publish_id 则直接返回数据库中存储的原始外键值（即 Publish 表的 id）。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                724,
                850,
                772
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "2. Django 如何实现这种关联？"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                780,
                307,
                791
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "（1）数据库层面"
                    }
                ],
                "level": 1
            },
            "bbox": [
                154,
                799,
                240,
                810
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 生成的 SQL 会明确指定外键关联的目标列："
                    }
                ]
            },
            "bbox": [
                176,
                816,
                473,
                828
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "sql"
                    }
                ]
            },
            "bbox": [
                147,
                835,
                166,
                846
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "复制"
                    }
                ]
            },
            "bbox": [
                147,
                854,
                174,
                865
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "下载"
                    }
                ]
            },
            "bbox": [
                147,
                873,
                174,
                883
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "FOREIGN KEY (publish_id) REFERENCES Publish(id) "
                    }
                ]
            },
            "bbox": [
                146,
                891,
                436,
                902
            ]
        }
    ],
    [
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "这里显式声明了 publish_id 关联到 Publish.id，与列名无关。"
                    }
                ]
            },
            "bbox": [
                146,
                95,
                467,
                105
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "（2）ORM 层面"
                    }
                ],
                "level": 1
            },
            "bbox": [
                154,
                112,
                236,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "当你访问 book.publish 时，Django 会自动执行类似以下的查询："
                    }
                ]
            },
            "bbox": [
                176,
                131,
                547,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "SELECT * FROM Publish WHERE id "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "book.publish_id; "
                    }
                ]
            },
            "bbox": [
                146,
                149,
                443,
                162
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "通过 publish_id 的值找到对应的 Publish 记录。"
                    }
                ]
            },
            "bbox": [
                146,
                168,
                398,
                181
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "3. 核心区别对比"
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                190,
                235,
                200
            ]
        },
        {
            "type": "table",
            "content": {
                "image_source": {
                    "path": "images/253ad5b303793ce0d4769c6b4c028e01ed1cc3015c9f13cf55d54a3c3ee543c6.jpg"
                },
                "table_caption": [],
                "table_footnote": [],
                "html": "<table><tr><td>特性</td><td>.add()</td><td>.create()</td></tr><tr><td>作用</td><td>关联已存在的对象</td><td>创建新对象并关联</td></tr><tr><td>是否创建新对象</td><td>□否</td><td>□是</td></tr><tr><td>适用关系类型</td><td>ManyToManyField, ForeignKey</td><td>ManyToManyField, ForeignKey的反向查询</td></tr><tr><td>参数类型</td><td>对象或ID</td><td>新对象的字段键值对</td></tr><tr><td>返回值</td><td>无</td><td>新创建的对象</td></tr></table>",
                "table_type": "simple_table",
                "table_nest_level": 1
            },
            "bbox": [
                144,
                216,
                702,
                444
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django Form 组件"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                481,
                500,
                514
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django Form 组件用于对页面进行初始化，生成 HTML 标签，此外还可以对用户提交的数据进行校验（显示错误信息）。"
                    }
                ]
            },
            "bbox": [
                146,
                527,
                769,
                539
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "报错信息显示顺序："
                    }
                ]
            },
            "bbox": [
                146,
                565,
                250,
                576
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "先显示字段属性中的错误信息，然后再显示局部钩子的错误信息。"
                    }
                ]
            },
            "bbox": [
                146,
                602,
                485,
                613
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "若显示了字段属性的错误信息，就不会显示局部钩子的错误信息。"
                    }
                ]
            },
            "bbox": [
                146,
                621,
                485,
                632
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "若有全局钩子，则全局钩子是等所有的数据都校验完，才开始进行校验，并且全局钩子的错误信息一定会显示。"
                    }
                ]
            },
            "bbox": [
                146,
                639,
                719,
                651
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 用户认证（Auth）组件"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                671,
                726,
                705
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 用户认证（Auth）组件一般用在用户的登录注册上，用于判断当前的用户是否合法，并跳转到登陆成功或失败页面。"
                    }
                ]
            },
            "bbox": [
                144,
                719,
                784,
                731
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 用户认证（Auth）组件需要导入 auth 模块:"
                    }
                ]
            },
            "bbox": [
                146,
                738,
                413,
                749
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 认证模块 "
                    }
                ]
            },
            "bbox": [
                146,
                757,
                208,
                766
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import auth "
                    }
                ]
            },
            "bbox": [
                146,
                775,
                312,
                785
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "# 对应数据库"
                    }
                ]
            },
            "bbox": [
                146,
                812,
                220,
                822
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib.auth.models import User "
                    }
                ]
            },
            "bbox": [
                146,
                831,
                383,
                841
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回值是用户对象。"
                    }
                ]
            },
            "bbox": [
                146,
                848,
                250,
                860
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "创建用户对象的三种方法："
                    }
                ]
            },
            "bbox": [
                146,
                868,
                285,
                879
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "create()：创建一个普通用户，密码是明文的。"
                    }
                ]
            },
            "bbox": [
                176,
                885,
                447,
                897
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "create_user()：创建一个普通用户，密码是密文的。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "create_superuser()：创建一个超级用户，密码是密文的，要多传一个邮箱email 参数。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                95,
                660,
                124
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "验证用户的用户名和密码使用 authenticate() 方法，从需要auth_user 表中过滤出用户对象。"
                    }
                ]
            },
            "bbox": [
                147,
                131,
                621,
                143
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "使用前要导入："
                    }
                ]
            },
            "bbox": [
                147,
                168,
                226,
                181
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import auth "
                    }
                ]
            },
            "bbox": [
                146,
                206,
                314,
                218
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "参数："
                    }
                ]
            },
            "bbox": [
                147,
                225,
                179,
                235
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "username：用户名"
                    }
                ]
            },
            "bbox": [
                146,
                262,
                250,
                273
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "password：密码"
                    }
                ]
            },
            "bbox": [
                147,
                281,
                236,
                291
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回值：如果验证成功，就返回用户对象，反之，返回 None。"
                    }
                ]
            },
            "bbox": [
                146,
                299,
                468,
                310
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "给验证成功的用户加 session，将 request.user 赋值为用户对象。"
                    }
                ]
            },
            "bbox": [
                146,
                317,
                480,
                328
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "登陆使用 login() 方法。"
                    }
                ]
            },
            "bbox": [
                147,
                336,
                265,
                347
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "使用前要导入："
                    }
                ]
            },
            "bbox": [
                147,
                355,
                226,
                365
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import auth "
                    }
                ]
            },
            "bbox": [
                146,
                373,
                312,
                384
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "参数："
                    }
                ]
            },
            "bbox": [
                147,
                392,
                179,
                401
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "request：用户对象"
                    }
                ]
            },
            "bbox": [
                176,
                410,
                310,
                420
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注销用户使用 logout() 方法，需要清空 session 信息，将 request.user 赋值为匿名用户。"
                    }
                ]
            },
            "bbox": [
                146,
                428,
                600,
                439
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "使用前要导入："
                    }
                ]
            },
            "bbox": [
                147,
                447,
                226,
                458
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib import auth "
                    }
                ]
            },
            "bbox": [
                146,
                466,
                314,
                476
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "参数："
                    }
                ]
            },
            "bbox": [
                147,
                485,
                179,
                494
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "request：用户对象"
                    }
                ]
            },
            "bbox": [
                176,
                502,
                310,
                514
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "返回值：None "
                    }
                ]
            },
            "bbox": [
                147,
                521,
                226,
                532
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "设置装饰器，给需要登录成功后才能访问的页面统一加装饰器。"
                    }
                ]
            },
            "bbox": [
                146,
                539,
                472,
                550
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "使用前要导入："
                    }
                ]
            },
            "bbox": [
                147,
                558,
                226,
                569
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib.auth.decorators import login_required "
                    }
                ]
            },
            "bbox": [
                146,
                577,
                450,
                588
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "实例"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                596,
                174,
                606
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "from django.contrib.auth.decorators import login_required "
                    },
                    {
                        "type": "equation_inline",
                        "content": "@"
                    },
                    {
                        "type": "text",
                        "content": "login_required "
                    }
                ]
            },
            "bbox": [
                146,
                614,
                547,
                625
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "def index(request): "
                    }
                ]
            },
            "bbox": [
                147,
                633,
                250,
                643
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "return HttpResponse(\"index 页面。。。\")"
                    }
                ]
            },
            "bbox": [
                152,
                652,
                374,
                662
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "设置从哪个页面访问，登录成功后就返回哪个页面。"
                    }
                ]
            },
            "bbox": [
                147,
                670,
                413,
                680
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "解析："
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                688,
                179,
                699
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django 在用户访问页面时，如果用户是未登录的状态，就给用户返回登录页面。"
                    }
                ]
            },
            "bbox": [
                146,
                707,
                559,
                717
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "此时，该登录页面的 URL 后面有参数：next=用户访问的页面的 URL。"
                    }
                ]
            },
            "bbox": [
                146,
                725,
                510,
                736
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "因此，设置在用户登录成功后重定向的 URL 为 next 参数的值。"
                    }
                ]
            },
            "bbox": [
                146,
                744,
                472,
                755
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "但是，若用户一开始就输入登录页面 logi，request.GET.get(\"next\") 就取不到值，所以在后面加or，可以设置自定义返回的页面。"
                    }
                ]
            },
            "bbox": [
                146,
                762,
                810,
                772
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django cookie 与 session"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                795,
                645,
                828
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Cookie 是存储在客户端计算机上的文本文件，并保留了各种跟踪信息。"
                    }
                ]
            },
            "bbox": [
                146,
                841,
                514,
                853
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "识别返回用户包括三个步骤："
                    }
                ]
            },
            "bbox": [
                147,
                860,
                297,
                872
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "服务器脚本向浏览器发送一组Cookie。例如：姓名、年龄或识别号码等。"
                    }
                ]
            },
            "bbox": [
                176,
                879,
                584,
                890
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "浏览器将这些信息存储在本地计算机上，以备将来使用。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "当下一次浏览器向 Web 服务器发送任何请求时，浏览器会把这些 Cookie 信息发送到服务器，服务器将使用这些信息来识别用户。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                95,
                847,
                142
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "HTTP 是一种\"无状态\"协议，这意味着每次客户端检索网页时，客户端打开一个单独的连接到 Web 服务器，服务器会自动不保留之前客户端请求的任何记录。"
                    }
                ]
            },
            "bbox": [
                144,
                149,
                847,
                180
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "但是仍然有以下三种方式来维持 Web 客户端和 Web 服务器之间的 session 会话："
                    }
                ]
            },
            "bbox": [
                146,
                187,
                566,
                199
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Cookies "
                    }
                ],
                "level": 1
            },
            "bbox": [
                146,
                206,
                196,
                216
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "一个 Web 服务器可以分配一个唯一的 session 会话 ID 作为每个 Web 客户端的 cookie，对于客户端的后续请求可以使用接收到的cookie 来识别。"
                    }
                ]
            },
            "bbox": [
                144,
                224,
                845,
                254
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "在 Web 开发中，使用 session 来完成会话跟踪，session 底层依赖 Cookie 技术。"
                    }
                ]
            },
            "bbox": [
                146,
                261,
                564,
                273
            ]
        },
        {
            "type": "image",
            "content": {
                "image_source": {
                    "path": "images/9a48075248f18fba9020fddb11e4edfdde6582563e4eadd68f5b3ee2169d2f8d.jpg"
                },
                "image_caption": [],
                "image_footnote": []
            },
            "bbox": [
                147,
                275,
                655,
                456
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Session(保存在服务端的键值对)"
                    }
                ],
                "level": 1
            },
            "bbox": [
                144,
                464,
                381,
                479
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "服务器在运行时可以为每一个用户的浏览器创建一个其独享的 session 对象，由于 session 为用户浏览器独享，所以用户在访问服务器的 web 资源时，可以把各自的数据放在各自的 session 中，当用户再去访问该服务器中的其它web 资源时，其它web 资源再从用户各自的 session 中取出数据为用户服务。"
                    }
                ]
            },
            "bbox": [
                144,
                482,
                855,
                554
            ]
        },
        {
            "type": "image",
            "content": {
                "image_source": {
                    "path": "images/13016cbec949f6ef478321a5634a2c0188ff9b392a433e44d44ca4da2df9e845.jpg"
                },
                "image_caption": [],
                "image_footnote": []
            },
            "bbox": [
                152,
                570,
                801,
                875
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "工作原理"
                    }
                ],
                "level": 1
            },
            "bbox": [
                147,
                890,
                218,
                904
            ]
        }
    ],
    [
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "a. 浏览器第一次请求获取登录页面 login。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " b. 浏览器输入账号密码第二次请求，若输入正确，服务器响应浏览器一个 index 页面和一个键为 sessionid，值为随机字符串的 cookie，即 set_cookie (\"sessionid\",随机字符串)。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " c. 服务器内部在 django.session 表中记录一条数据。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                93,
                843,
                164
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "django.session 表中有三个字段。"
                    }
                ]
            },
            "bbox": [
                144,
                168,
                379,
                183
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o session_key：存的是随机字符串，即响应给浏览器的 cookie 的 sessionid 键对应的值。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o session_data：存的是用户的信息，即多个 request.session[\"key\"]=value，且是密文。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "o expire_date：存的是该条记录的过期时间（默认 14 天）"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                235,
                186,
                843,
                275
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": " d. 浏览器第三次请求其他资源时，携带cookie :{sessionid:随机字符串}，服务器从django.session 表中根据该随机字符串取出该用户的数据，供其使用（即保存状态）。"
                    }
                ]
            },
            "bbox": [
                174,
                279,
                826,
                313
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "注意: django.session 表中保存的是浏览器的信息，而不是每一个用户的信息。 因此， 同一浏览器多个用户请求只保存一条记录（后面覆盖前面）,多个浏览器请求才保存多条记录。"
                    }
                ]
            },
            "bbox": [
                144,
                316,
                842,
                349
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "cookie 弥补了 http 无状态的不足，让服务器知道来的人是\"谁\"，但是 cookie 以文本的形式保存在浏览器端，安全性较差，且最大只支持 4096 字节，所以只通过 cookie 识别不同的用户，然后，在对应的 session 里保存私密的信息以及超过 4096 字节的文本。"
                    }
                ]
            },
            "bbox": [
                144,
                353,
                836,
                405
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "session 设置："
                    }
                ]
            },
            "bbox": [
                144,
                409,
                243,
                423
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "request.session[\"key\"] "
                    },
                    {
                        "type": "equation_inline",
                        "content": "="
                    },
                    {
                        "type": "text",
                        "content": "value "
                    }
                ]
            },
            "bbox": [
                144,
                426,
                356,
                442
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "执行步骤："
                    }
                ]
            },
            "bbox": [
                144,
                445,
                226,
                460
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": "a. 生成随机字符串 "
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " b. 把随机字符串和设置的键值对保存到 django_session 表的 session_key 和 session_data里"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " c. 设置 cookie：set_cookie(\"sessionid\",随机字符串) 响应给浏览器"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                464,
                836,
                535
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "session 获取："
                    }
                ]
            },
            "bbox": [
                144,
                539,
                243,
                552
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "request.session.get('key') "
                    }
                ]
            },
            "bbox": [
                144,
                557,
                319,
                571
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "执行步骤："
                    }
                ]
            },
            "bbox": [
                144,
                575,
                226,
                590
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " a. 从 cookie 中获取 sessionid 键的值，即随机字符串。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " b. 根据随机字符串从 django_session 表过滤出记录。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " c. 取出 session_data 字段的数据。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                594,
                591,
                646
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "session 删除，删除整条记录（包括 session_key、session_data、expire_date 三个字段）："
                    }
                ]
            },
            "bbox": [
                144,
                649,
                781,
                665
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "request.session.flush() "
                    }
                ]
            },
            "bbox": [
                144,
                668,
                300,
                683
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "删除 session_data 里的其中一组键值对："
                    }
                ]
            },
            "bbox": [
                144,
                686,
                435,
                702
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "del request.session[\"key\"] "
                    }
                ]
            },
            "bbox": [
                144,
                705,
                326,
                720
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "执行步骤："
                    }
                ]
            },
            "bbox": [
                144,
                722,
                226,
                738
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " a. 从 cookie 中获取 sessionid 键的值，即随机字符串"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " b. 根据随机字符串从 django_session 表过滤出记录"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " c. 删除过滤出来的记录"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                174,
                741,
                584,
                793
            ]
        },
        {
            "type": "title",
            "content": {
                "title_content": [
                    {
                        "type": "text",
                        "content": "Django 中间件"
                    }
                ],
                "level": 1
            },
            "bbox": [
                144,
                797,
                258,
                813
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 中间件是修改 Django request 或者 response 对象的钩子，可以理解为是介于 HttpRequest与 HttpResponse 处理之间的一道处理过程。"
                    }
                ]
            },
            "bbox": [
                144,
                816,
                838,
                850
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "浏览器从请求到响应的过程中，Django 需要通过很多中间件来处理，可以看如下图所示："
                    }
                ]
            },
            "bbox": [
                144,
                853,
                800,
                869
            ]
        }
    ],
    [
        {
            "type": "image",
            "content": {
                "image_source": {
                    "path": "images/eff2575789a078e5215193fc6d91fb3d590196cf4b9a4bc9c76cfb08807856a7.jpg"
                },
                "image_caption": [],
                "image_footnote": []
            },
            "bbox": [
                147,
                95,
                815,
                363
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "Django 中间件作用："
                    }
                ]
            },
            "bbox": [
                146,
                390,
                295,
                405
            ]
        },
        {
            "type": "list",
            "content": {
                "list_type": "text_list",
                "list_items": [
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " 修改请求，即传送到 view 中的 HttpRequest 对象。"
                            }
                        ]
                    },
                    {
                        "item_type": "text",
                        "item_content": [
                            {
                                "type": "text",
                                "content": " 修改响应，即 view 返回的 HttpResponse 对象。"
                            }
                        ]
                    }
                ]
            },
            "bbox": [
                176,
                409,
                569,
                443
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "中间件组件配置在 settings.py 文件的 MIDDLEWARE 选项列表中。"
                    }
                ]
            },
            "bbox": [
                144,
                445,
                630,
                461
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "配置中的每个字符串选项都是一个类，也就是一个中间件。"
                    }
                ]
            },
            "bbox": [
                146,
                464,
                576,
                479
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "自定义中间件"
                    }
                ]
            },
            "bbox": [
                147,
                482,
                253,
                497
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "中间件可以定义四个方法，分别是："
                    }
                ]
            },
            "bbox": [
                146,
                501,
                410,
                516
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "process_request(self,request) "
                    }
                ]
            },
            "bbox": [
                144,
                539,
                347,
                552
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "process_view(self, request, view_func, view_args, view_kwargs) "
                    }
                ]
            },
            "bbox": [
                146,
                557,
                589,
                571
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "process_exception(self, request, exception) "
                    }
                ]
            },
            "bbox": [
                147,
                576,
                440,
                590
            ]
        },
        {
            "type": "paragraph",
            "content": {
                "paragraph_content": [
                    {
                        "type": "text",
                        "content": "process_response(self, request, response) "
                    }
                ]
            },
            "bbox": [
                147,
                595,
                428,
                609
            ]
        }
    ]
]